#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
+static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
+{
+ int i;
+ int ret;
+
+ ret = pciback_read_config_word(dev, offset, value, data);
+ /*if (!atomic_read(&dev->enable_cnt))
+ return ret;*/
+
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ *value |= PCI_COMMAND_IO;
+ if (dev->resource[i].flags & IORESOURCE_MEM)
+ *value |= PCI_COMMAND_MEMORY;
+ }
+
+ return ret;
+}
+
static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
{
int err;
/* A write to obtain the length must happen as a 32-bit write.
* This does not (yet) support writing individual bytes
*/
- bar->which = (value == ~PCI_ROM_ADDRESS_ENABLE);
+ if (value == ~PCI_ROM_ADDRESS_ENABLE)
+ bar->which = 1;
+ else {
+ u32 tmpval;
+ pci_read_config_dword(dev, offset, &tmpval);
+ if (tmpval != bar->val && value == bar->val) {
+ /* Allow restoration of bar value. */
+ pci_write_config_dword(dev, offset, bar->val);
+ }
+ bar->which = 0;
+ }
/* Do we need to support enabling/disabling the rom address here? */
/* A write to obtain the length must happen as a 32-bit write.
* This does not (yet) support writing individual bytes
*/
- bar->which = (value == ~0);
+ if (value == ~0)
+ bar->which = 1;
+ else {
+ u32 tmpval;
+ pci_read_config_dword(dev, offset, &tmpval);
+ if (tmpval != bar->val && value == bar->val) {
+ /* Allow restoration of bar value. */
+ pci_write_config_dword(dev, offset, bar->val);
+ }
+ bar->which = 0;
+ }
return 0;
}
static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
{
struct pci_bar_info *bar = data;
- int idx = (offset - 0x10) >> 2;
-
- if (idx > PCI_STD_RESOURCE_END )
- idx = PCI_ROM_RESOURCE;
if (unlikely(!bar)) {
printk(KERN_WARNING "pciback: driver data not found for %s\n",
return XEN_PCI_ERR_op_failed;
}
- *value = bar->which ? ~(pci_resource_len(dev, idx)-1) : pci_resource_start(dev, idx);
- *value |= pci_resource_flags(dev, idx) & 0xf;
+ *value = bar->which ? bar->len_val : bar->val;
return 0;
}
struct pci_bar_info *bar_info, int offset,
u32 len_mask)
{
- pci_read_config_dword(dev, offset, &bar_info->val);
- pci_write_config_dword(dev, offset, len_mask);
- pci_read_config_dword(dev, offset, &bar_info->len_val);
- pci_write_config_dword(dev, offset, bar_info->val);
+ int pos;
+ struct resource *res = dev->resource;
+
+ if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
+ pos = PCI_ROM_RESOURCE;
+ else {
+ pos = (offset - PCI_BASE_ADDRESS_0) / 4;
+ if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
+ PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
+ (PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64))) {
+ bar_info->val = res[pos - 1].start >> 32;
+ bar_info->len_val = res[pos - 1].end >> 32;
+ return;
+ }
+ }
+
+ bar_info->val = res[pos].start |
+ (res[pos].flags & PCI_REGION_FLAG_MASK);
+ bar_info->len_val = res[pos].end - res[pos].start + 1;
}
static void *bar_init(struct pci_dev *dev, int offset)
kfree(data);
}
-static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
- void *data)
+static int pciback_read_vendor(struct pci_dev *dev, int offset,
+ u16 *value, void *data)
{
- *value = (u8) dev->irq;
+ *value = dev->vendor;
return 0;
}
-static int vendor_read(struct pci_dev *dev, int offset, u16 * value,
- void *data)
+static int pciback_read_device(struct pci_dev *dev, int offset,
+ u16 *value, void *data)
{
- *value = dev->vendor;
+ *value = dev->device;
return 0;
}
-static int device_read(struct pci_dev *dev, int offset, u16 * value,
- void *data)
+static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
+ void *data)
{
- *value = dev->device;
+ *value = (u8) dev->irq;
return 0;
}
{
.offset = PCI_VENDOR_ID,
.size = 2,
- .u.w.read = vendor_read
+ .u.w.read = pciback_read_vendor,
},
{
.offset = PCI_DEVICE_ID,
.size = 2,
- .u.w.read = device_read
+ .u.w.read = pciback_read_device,
},
{
.offset = PCI_COMMAND,
.size = 2,
- .u.w.read = pciback_read_config_word,
+ .u.w.read = command_read,
.u.w.write = command_write,
},
{