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 1830edc14bSKonrad Rzeszutek Wilk #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) 1930edc14bSKonrad Rzeszutek Wilk #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) 2030edc14bSKonrad Rzeszutek Wilk 21*fd5b221bSZhao, Yu static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) 22*fd5b221bSZhao, Yu { 23*fd5b221bSZhao, Yu int i; 24*fd5b221bSZhao, Yu int ret; 25*fd5b221bSZhao, Yu 26*fd5b221bSZhao, Yu ret = pciback_read_config_word(dev, offset, value, data); 27*fd5b221bSZhao, Yu if (!atomic_read(&dev->enable_cnt)) 28*fd5b221bSZhao, Yu return ret; 29*fd5b221bSZhao, Yu 30*fd5b221bSZhao, Yu for (i = 0; i < PCI_ROM_RESOURCE; i++) { 31*fd5b221bSZhao, Yu if (dev->resource[i].flags & IORESOURCE_IO) 32*fd5b221bSZhao, Yu *value |= PCI_COMMAND_IO; 33*fd5b221bSZhao, Yu if (dev->resource[i].flags & IORESOURCE_MEM) 34*fd5b221bSZhao, Yu *value |= PCI_COMMAND_MEMORY; 35*fd5b221bSZhao, Yu } 36*fd5b221bSZhao, Yu 37*fd5b221bSZhao, Yu return ret; 38*fd5b221bSZhao, Yu } 39*fd5b221bSZhao, Yu 4030edc14bSKonrad Rzeszutek Wilk static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) 4130edc14bSKonrad Rzeszutek Wilk { 4230edc14bSKonrad Rzeszutek Wilk int err; 4330edc14bSKonrad Rzeszutek Wilk 4430edc14bSKonrad Rzeszutek Wilk if (!pci_is_enabled(dev) && is_enable_cmd(value)) { 4530edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 4630edc14bSKonrad Rzeszutek Wilk printk(KERN_DEBUG "pciback: %s: enable\n", 4730edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 4830edc14bSKonrad Rzeszutek Wilk err = pci_enable_device(dev); 4930edc14bSKonrad Rzeszutek Wilk if (err) 5030edc14bSKonrad Rzeszutek Wilk return err; 5130edc14bSKonrad Rzeszutek Wilk } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { 5230edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 5330edc14bSKonrad Rzeszutek Wilk printk(KERN_DEBUG "pciback: %s: disable\n", 5430edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 5530edc14bSKonrad Rzeszutek Wilk pci_disable_device(dev); 5630edc14bSKonrad Rzeszutek Wilk } 5730edc14bSKonrad Rzeszutek Wilk 5830edc14bSKonrad Rzeszutek Wilk if (!dev->is_busmaster && is_master_cmd(value)) { 5930edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 6030edc14bSKonrad Rzeszutek Wilk printk(KERN_DEBUG "pciback: %s: set bus master\n", 6130edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 6230edc14bSKonrad Rzeszutek Wilk pci_set_master(dev); 6330edc14bSKonrad Rzeszutek Wilk } 6430edc14bSKonrad Rzeszutek Wilk 6530edc14bSKonrad Rzeszutek Wilk if (value & PCI_COMMAND_INVALIDATE) { 6630edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 6730edc14bSKonrad Rzeszutek Wilk printk(KERN_DEBUG 6830edc14bSKonrad Rzeszutek Wilk "pciback: %s: enable memory-write-invalidate\n", 6930edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 7030edc14bSKonrad Rzeszutek Wilk err = pci_set_mwi(dev); 7130edc14bSKonrad Rzeszutek Wilk if (err) { 7230edc14bSKonrad Rzeszutek Wilk printk(KERN_WARNING 7330edc14bSKonrad Rzeszutek Wilk "pciback: %s: cannot enable " 7430edc14bSKonrad Rzeszutek Wilk "memory-write-invalidate (%d)\n", 7530edc14bSKonrad Rzeszutek Wilk pci_name(dev), err); 7630edc14bSKonrad Rzeszutek Wilk value &= ~PCI_COMMAND_INVALIDATE; 7730edc14bSKonrad Rzeszutek Wilk } 7830edc14bSKonrad Rzeszutek Wilk } 7930edc14bSKonrad Rzeszutek Wilk 8030edc14bSKonrad Rzeszutek Wilk return pci_write_config_word(dev, offset, value); 8130edc14bSKonrad Rzeszutek Wilk } 8230edc14bSKonrad Rzeszutek Wilk 8330edc14bSKonrad Rzeszutek Wilk static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data) 8430edc14bSKonrad Rzeszutek Wilk { 8530edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 8630edc14bSKonrad Rzeszutek Wilk 8730edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 8830edc14bSKonrad Rzeszutek Wilk printk(KERN_WARNING "pciback: driver data not found for %s\n", 8930edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 9030edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 9130edc14bSKonrad Rzeszutek Wilk } 9230edc14bSKonrad Rzeszutek Wilk 9330edc14bSKonrad Rzeszutek Wilk /* A write to obtain the length must happen as a 32-bit write. 9430edc14bSKonrad Rzeszutek Wilk * This does not (yet) support writing individual bytes 9530edc14bSKonrad Rzeszutek Wilk */ 9630edc14bSKonrad Rzeszutek Wilk if (value == ~PCI_ROM_ADDRESS_ENABLE) 9730edc14bSKonrad Rzeszutek Wilk bar->which = 1; 9830edc14bSKonrad Rzeszutek Wilk else { 9930edc14bSKonrad Rzeszutek Wilk u32 tmpval; 10030edc14bSKonrad Rzeszutek Wilk pci_read_config_dword(dev, offset, &tmpval); 10130edc14bSKonrad Rzeszutek Wilk if (tmpval != bar->val && value == bar->val) { 10230edc14bSKonrad Rzeszutek Wilk /* Allow restoration of bar value. */ 10330edc14bSKonrad Rzeszutek Wilk pci_write_config_dword(dev, offset, bar->val); 10430edc14bSKonrad Rzeszutek Wilk } 10530edc14bSKonrad Rzeszutek Wilk bar->which = 0; 10630edc14bSKonrad Rzeszutek Wilk } 10730edc14bSKonrad Rzeszutek Wilk 10830edc14bSKonrad Rzeszutek Wilk /* Do we need to support enabling/disabling the rom address here? */ 10930edc14bSKonrad Rzeszutek Wilk 11030edc14bSKonrad Rzeszutek Wilk return 0; 11130edc14bSKonrad Rzeszutek Wilk } 11230edc14bSKonrad Rzeszutek Wilk 11330edc14bSKonrad Rzeszutek Wilk /* For the BARs, only allow writes which write ~0 or 11430edc14bSKonrad Rzeszutek Wilk * the correct resource information 11530edc14bSKonrad Rzeszutek Wilk * (Needed for when the driver probes the resource usage) 11630edc14bSKonrad Rzeszutek Wilk */ 11730edc14bSKonrad Rzeszutek Wilk static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data) 11830edc14bSKonrad Rzeszutek Wilk { 11930edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 12030edc14bSKonrad Rzeszutek Wilk 12130edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 12230edc14bSKonrad Rzeszutek Wilk printk(KERN_WARNING "pciback: driver data not found for %s\n", 12330edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 12430edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 12530edc14bSKonrad Rzeszutek Wilk } 12630edc14bSKonrad Rzeszutek Wilk 12730edc14bSKonrad Rzeszutek Wilk /* A write to obtain the length must happen as a 32-bit write. 12830edc14bSKonrad Rzeszutek Wilk * This does not (yet) support writing individual bytes 12930edc14bSKonrad Rzeszutek Wilk */ 13030edc14bSKonrad Rzeszutek Wilk if (value == ~0) 13130edc14bSKonrad Rzeszutek Wilk bar->which = 1; 13230edc14bSKonrad Rzeszutek Wilk else { 13330edc14bSKonrad Rzeszutek Wilk u32 tmpval; 13430edc14bSKonrad Rzeszutek Wilk pci_read_config_dword(dev, offset, &tmpval); 13530edc14bSKonrad Rzeszutek Wilk if (tmpval != bar->val && value == bar->val) { 13630edc14bSKonrad Rzeszutek Wilk /* Allow restoration of bar value. */ 13730edc14bSKonrad Rzeszutek Wilk pci_write_config_dword(dev, offset, bar->val); 13830edc14bSKonrad Rzeszutek Wilk } 13930edc14bSKonrad Rzeszutek Wilk bar->which = 0; 14030edc14bSKonrad Rzeszutek Wilk } 14130edc14bSKonrad Rzeszutek Wilk 14230edc14bSKonrad Rzeszutek Wilk return 0; 14330edc14bSKonrad Rzeszutek Wilk } 14430edc14bSKonrad Rzeszutek Wilk 14530edc14bSKonrad Rzeszutek Wilk static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data) 14630edc14bSKonrad Rzeszutek Wilk { 14730edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 14830edc14bSKonrad Rzeszutek Wilk 14930edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 15030edc14bSKonrad Rzeszutek Wilk printk(KERN_WARNING "pciback: driver data not found for %s\n", 15130edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 15230edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 15330edc14bSKonrad Rzeszutek Wilk } 15430edc14bSKonrad Rzeszutek Wilk 15530edc14bSKonrad Rzeszutek Wilk *value = bar->which ? bar->len_val : bar->val; 15630edc14bSKonrad Rzeszutek Wilk 15730edc14bSKonrad Rzeszutek Wilk return 0; 15830edc14bSKonrad Rzeszutek Wilk } 15930edc14bSKonrad Rzeszutek Wilk 16030edc14bSKonrad Rzeszutek Wilk static inline void read_dev_bar(struct pci_dev *dev, 16130edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar_info, int offset, 16230edc14bSKonrad Rzeszutek Wilk u32 len_mask) 16330edc14bSKonrad Rzeszutek Wilk { 164*fd5b221bSZhao, Yu int pos; 165*fd5b221bSZhao, Yu struct resource *res = dev->resource; 166*fd5b221bSZhao, Yu 167*fd5b221bSZhao, Yu if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1) 168*fd5b221bSZhao, Yu pos = PCI_ROM_RESOURCE; 169*fd5b221bSZhao, Yu else { 170*fd5b221bSZhao, Yu pos = (offset - PCI_BASE_ADDRESS_0) / 4; 171*fd5b221bSZhao, Yu if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE | 172*fd5b221bSZhao, Yu PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == 173*fd5b221bSZhao, Yu (PCI_BASE_ADDRESS_SPACE_MEMORY | 174*fd5b221bSZhao, Yu PCI_BASE_ADDRESS_MEM_TYPE_64))) { 175*fd5b221bSZhao, Yu bar_info->val = res[pos - 1].start >> 32; 176*fd5b221bSZhao, Yu bar_info->len_val = res[pos - 1].end >> 32; 177*fd5b221bSZhao, Yu return; 178*fd5b221bSZhao, Yu } 179*fd5b221bSZhao, Yu } 180*fd5b221bSZhao, Yu 181*fd5b221bSZhao, Yu bar_info->val = res[pos].start | 182*fd5b221bSZhao, Yu (res[pos].flags & PCI_REGION_FLAG_MASK); 183*fd5b221bSZhao, Yu bar_info->len_val = res[pos].end - res[pos].start + 1; 18430edc14bSKonrad Rzeszutek Wilk } 18530edc14bSKonrad Rzeszutek Wilk 18630edc14bSKonrad Rzeszutek Wilk static void *bar_init(struct pci_dev *dev, int offset) 18730edc14bSKonrad Rzeszutek Wilk { 18830edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL); 18930edc14bSKonrad Rzeszutek Wilk 19030edc14bSKonrad Rzeszutek Wilk if (!bar) 19130edc14bSKonrad Rzeszutek Wilk return ERR_PTR(-ENOMEM); 19230edc14bSKonrad Rzeszutek Wilk 19330edc14bSKonrad Rzeszutek Wilk read_dev_bar(dev, bar, offset, ~0); 19430edc14bSKonrad Rzeszutek Wilk bar->which = 0; 19530edc14bSKonrad Rzeszutek Wilk 19630edc14bSKonrad Rzeszutek Wilk return bar; 19730edc14bSKonrad Rzeszutek Wilk } 19830edc14bSKonrad Rzeszutek Wilk 19930edc14bSKonrad Rzeszutek Wilk static void *rom_init(struct pci_dev *dev, int offset) 20030edc14bSKonrad Rzeszutek Wilk { 20130edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL); 20230edc14bSKonrad Rzeszutek Wilk 20330edc14bSKonrad Rzeszutek Wilk if (!bar) 20430edc14bSKonrad Rzeszutek Wilk return ERR_PTR(-ENOMEM); 20530edc14bSKonrad Rzeszutek Wilk 20630edc14bSKonrad Rzeszutek Wilk read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE); 20730edc14bSKonrad Rzeszutek Wilk bar->which = 0; 20830edc14bSKonrad Rzeszutek Wilk 20930edc14bSKonrad Rzeszutek Wilk return bar; 21030edc14bSKonrad Rzeszutek Wilk } 21130edc14bSKonrad Rzeszutek Wilk 21230edc14bSKonrad Rzeszutek Wilk static void bar_reset(struct pci_dev *dev, int offset, void *data) 21330edc14bSKonrad Rzeszutek Wilk { 21430edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 21530edc14bSKonrad Rzeszutek Wilk 21630edc14bSKonrad Rzeszutek Wilk bar->which = 0; 21730edc14bSKonrad Rzeszutek Wilk } 21830edc14bSKonrad Rzeszutek Wilk 21930edc14bSKonrad Rzeszutek Wilk static void bar_release(struct pci_dev *dev, int offset, void *data) 22030edc14bSKonrad Rzeszutek Wilk { 22130edc14bSKonrad Rzeszutek Wilk kfree(data); 22230edc14bSKonrad Rzeszutek Wilk } 22330edc14bSKonrad Rzeszutek Wilk 224*fd5b221bSZhao, Yu static int pciback_read_vendor(struct pci_dev *dev, int offset, 225*fd5b221bSZhao, Yu u16 *value, void *data) 226*fd5b221bSZhao, Yu { 227*fd5b221bSZhao, Yu *value = dev->vendor; 228*fd5b221bSZhao, Yu 229*fd5b221bSZhao, Yu return 0; 230*fd5b221bSZhao, Yu } 231*fd5b221bSZhao, Yu 232*fd5b221bSZhao, Yu static int pciback_read_device(struct pci_dev *dev, int offset, 233*fd5b221bSZhao, Yu u16 *value, void *data) 234*fd5b221bSZhao, Yu { 235*fd5b221bSZhao, Yu *value = dev->device; 236*fd5b221bSZhao, Yu 237*fd5b221bSZhao, Yu return 0; 238*fd5b221bSZhao, Yu } 239*fd5b221bSZhao, Yu 24030edc14bSKonrad Rzeszutek Wilk static int interrupt_read(struct pci_dev *dev, int offset, u8 * value, 24130edc14bSKonrad Rzeszutek Wilk void *data) 24230edc14bSKonrad Rzeszutek Wilk { 24330edc14bSKonrad Rzeszutek Wilk *value = (u8) dev->irq; 24430edc14bSKonrad Rzeszutek Wilk 24530edc14bSKonrad Rzeszutek Wilk return 0; 24630edc14bSKonrad Rzeszutek Wilk } 24730edc14bSKonrad Rzeszutek Wilk 24830edc14bSKonrad Rzeszutek Wilk static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data) 24930edc14bSKonrad Rzeszutek Wilk { 25030edc14bSKonrad Rzeszutek Wilk u8 cur_value; 25130edc14bSKonrad Rzeszutek Wilk int err; 25230edc14bSKonrad Rzeszutek Wilk 25330edc14bSKonrad Rzeszutek Wilk err = pci_read_config_byte(dev, offset, &cur_value); 25430edc14bSKonrad Rzeszutek Wilk if (err) 25530edc14bSKonrad Rzeszutek Wilk goto out; 25630edc14bSKonrad Rzeszutek Wilk 25730edc14bSKonrad Rzeszutek Wilk if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START) 25830edc14bSKonrad Rzeszutek Wilk || value == PCI_BIST_START) 25930edc14bSKonrad Rzeszutek Wilk err = pci_write_config_byte(dev, offset, value); 26030edc14bSKonrad Rzeszutek Wilk 26130edc14bSKonrad Rzeszutek Wilk out: 26230edc14bSKonrad Rzeszutek Wilk return err; 26330edc14bSKonrad Rzeszutek Wilk } 26430edc14bSKonrad Rzeszutek Wilk 26530edc14bSKonrad Rzeszutek Wilk static const struct config_field header_common[] = { 26630edc14bSKonrad Rzeszutek Wilk { 267*fd5b221bSZhao, Yu .offset = PCI_VENDOR_ID, 268*fd5b221bSZhao, Yu .size = 2, 269*fd5b221bSZhao, Yu .u.w.read = pciback_read_vendor, 270*fd5b221bSZhao, Yu }, 271*fd5b221bSZhao, Yu { 272*fd5b221bSZhao, Yu .offset = PCI_DEVICE_ID, 273*fd5b221bSZhao, Yu .size = 2, 274*fd5b221bSZhao, Yu .u.w.read = pciback_read_device, 275*fd5b221bSZhao, Yu }, 276*fd5b221bSZhao, Yu { 27730edc14bSKonrad Rzeszutek Wilk .offset = PCI_COMMAND, 27830edc14bSKonrad Rzeszutek Wilk .size = 2, 279*fd5b221bSZhao, Yu .u.w.read = command_read, 28030edc14bSKonrad Rzeszutek Wilk .u.w.write = command_write, 28130edc14bSKonrad Rzeszutek Wilk }, 28230edc14bSKonrad Rzeszutek Wilk { 28330edc14bSKonrad Rzeszutek Wilk .offset = PCI_INTERRUPT_LINE, 28430edc14bSKonrad Rzeszutek Wilk .size = 1, 28530edc14bSKonrad Rzeszutek Wilk .u.b.read = interrupt_read, 28630edc14bSKonrad Rzeszutek Wilk }, 28730edc14bSKonrad Rzeszutek Wilk { 28830edc14bSKonrad Rzeszutek Wilk .offset = PCI_INTERRUPT_PIN, 28930edc14bSKonrad Rzeszutek Wilk .size = 1, 29030edc14bSKonrad Rzeszutek Wilk .u.b.read = pciback_read_config_byte, 29130edc14bSKonrad Rzeszutek Wilk }, 29230edc14bSKonrad Rzeszutek Wilk { 29330edc14bSKonrad Rzeszutek Wilk /* Any side effects of letting driver domain control cache line? */ 29430edc14bSKonrad Rzeszutek Wilk .offset = PCI_CACHE_LINE_SIZE, 29530edc14bSKonrad Rzeszutek Wilk .size = 1, 29630edc14bSKonrad Rzeszutek Wilk .u.b.read = pciback_read_config_byte, 29730edc14bSKonrad Rzeszutek Wilk .u.b.write = pciback_write_config_byte, 29830edc14bSKonrad Rzeszutek Wilk }, 29930edc14bSKonrad Rzeszutek Wilk { 30030edc14bSKonrad Rzeszutek Wilk .offset = PCI_LATENCY_TIMER, 30130edc14bSKonrad Rzeszutek Wilk .size = 1, 30230edc14bSKonrad Rzeszutek Wilk .u.b.read = pciback_read_config_byte, 30330edc14bSKonrad Rzeszutek Wilk }, 30430edc14bSKonrad Rzeszutek Wilk { 30530edc14bSKonrad Rzeszutek Wilk .offset = PCI_BIST, 30630edc14bSKonrad Rzeszutek Wilk .size = 1, 30730edc14bSKonrad Rzeszutek Wilk .u.b.read = pciback_read_config_byte, 30830edc14bSKonrad Rzeszutek Wilk .u.b.write = bist_write, 30930edc14bSKonrad Rzeszutek Wilk }, 31030edc14bSKonrad Rzeszutek Wilk {} 31130edc14bSKonrad Rzeszutek Wilk }; 31230edc14bSKonrad Rzeszutek Wilk 31330edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_BAR(reg_offset) \ 31430edc14bSKonrad Rzeszutek Wilk { \ 31530edc14bSKonrad Rzeszutek Wilk .offset = reg_offset, \ 31630edc14bSKonrad Rzeszutek Wilk .size = 4, \ 31730edc14bSKonrad Rzeszutek Wilk .init = bar_init, \ 31830edc14bSKonrad Rzeszutek Wilk .reset = bar_reset, \ 31930edc14bSKonrad Rzeszutek Wilk .release = bar_release, \ 32030edc14bSKonrad Rzeszutek Wilk .u.dw.read = bar_read, \ 32130edc14bSKonrad Rzeszutek Wilk .u.dw.write = bar_write, \ 32230edc14bSKonrad Rzeszutek Wilk } 32330edc14bSKonrad Rzeszutek Wilk 32430edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_ROM(reg_offset) \ 32530edc14bSKonrad Rzeszutek Wilk { \ 32630edc14bSKonrad Rzeszutek Wilk .offset = reg_offset, \ 32730edc14bSKonrad Rzeszutek Wilk .size = 4, \ 32830edc14bSKonrad Rzeszutek Wilk .init = rom_init, \ 32930edc14bSKonrad Rzeszutek Wilk .reset = bar_reset, \ 33030edc14bSKonrad Rzeszutek Wilk .release = bar_release, \ 33130edc14bSKonrad Rzeszutek Wilk .u.dw.read = bar_read, \ 33230edc14bSKonrad Rzeszutek Wilk .u.dw.write = rom_write, \ 33330edc14bSKonrad Rzeszutek Wilk } 33430edc14bSKonrad Rzeszutek Wilk 33530edc14bSKonrad Rzeszutek Wilk static const struct config_field header_0[] = { 33630edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_0), 33730edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_1), 33830edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_2), 33930edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_3), 34030edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_4), 34130edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_5), 34230edc14bSKonrad Rzeszutek Wilk CFG_FIELD_ROM(PCI_ROM_ADDRESS), 34330edc14bSKonrad Rzeszutek Wilk {} 34430edc14bSKonrad Rzeszutek Wilk }; 34530edc14bSKonrad Rzeszutek Wilk 34630edc14bSKonrad Rzeszutek Wilk static const struct config_field header_1[] = { 34730edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_0), 34830edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_1), 34930edc14bSKonrad Rzeszutek Wilk CFG_FIELD_ROM(PCI_ROM_ADDRESS1), 35030edc14bSKonrad Rzeszutek Wilk {} 35130edc14bSKonrad Rzeszutek Wilk }; 35230edc14bSKonrad Rzeszutek Wilk 35330edc14bSKonrad Rzeszutek Wilk int pciback_config_header_add_fields(struct pci_dev *dev) 35430edc14bSKonrad Rzeszutek Wilk { 35530edc14bSKonrad Rzeszutek Wilk int err; 35630edc14bSKonrad Rzeszutek Wilk 35730edc14bSKonrad Rzeszutek Wilk err = pciback_config_add_fields(dev, header_common); 35830edc14bSKonrad Rzeszutek Wilk if (err) 35930edc14bSKonrad Rzeszutek Wilk goto out; 36030edc14bSKonrad Rzeszutek Wilk 36130edc14bSKonrad Rzeszutek Wilk switch (dev->hdr_type) { 36230edc14bSKonrad Rzeszutek Wilk case PCI_HEADER_TYPE_NORMAL: 36330edc14bSKonrad Rzeszutek Wilk err = pciback_config_add_fields(dev, header_0); 36430edc14bSKonrad Rzeszutek Wilk break; 36530edc14bSKonrad Rzeszutek Wilk 36630edc14bSKonrad Rzeszutek Wilk case PCI_HEADER_TYPE_BRIDGE: 36730edc14bSKonrad Rzeszutek Wilk err = pciback_config_add_fields(dev, header_1); 36830edc14bSKonrad Rzeszutek Wilk break; 36930edc14bSKonrad Rzeszutek Wilk 37030edc14bSKonrad Rzeszutek Wilk default: 37130edc14bSKonrad Rzeszutek Wilk err = -EINVAL; 37230edc14bSKonrad Rzeszutek Wilk printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n", 37330edc14bSKonrad Rzeszutek Wilk pci_name(dev), dev->hdr_type); 37430edc14bSKonrad Rzeszutek Wilk break; 37530edc14bSKonrad Rzeszutek Wilk } 37630edc14bSKonrad Rzeszutek Wilk 37730edc14bSKonrad Rzeszutek Wilk out: 37830edc14bSKonrad Rzeszutek Wilk return err; 37930edc14bSKonrad Rzeszutek Wilk } 380