static int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { char __iomem *addr; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) return -EINVAL; addr = pci_dev_base(seg, bus, devfn); if (!addr) return pci_conf1_write(seg,bus,devfn,reg,len,value); switch (len) { case 1: writeb(value, addr + reg); break; case 2: writew(value, addr + reg); break; case 4: writel(value, addr + reg); break; } return 0; }
static int pci_mmcfg_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { char __iomem *addr; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { *value = -1; return -EINVAL; } addr = pci_dev_base(seg, bus, devfn); if (!addr) return pci_conf1_read(seg,bus,devfn,reg,len,value); switch (len) { case 1: *value = mmio_config_readb(addr + reg); break; case 2: *value = mmio_config_readw(addr + reg); break; case 4: *value = mmio_config_readl(addr + reg); break; } return 0; }
static int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { char __iomem *addr; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) return -EINVAL; rcu_read_lock(); addr = pci_dev_base(seg, bus, devfn); if (!addr) { rcu_read_unlock(); return -EINVAL; } switch (len) { case 1: mmio_config_writeb(addr + reg, value); break; case 2: mmio_config_writew(addr + reg, value); break; case 4: mmio_config_writel(addr + reg, value); break; } rcu_read_unlock(); return 0; }
/* K8 systems have some devices (typically in the builtin northbridge) that are only accessible using type1 Normally this can be expressed in the MCFG by not listing them and assigning suitable _SEGs, but this isn't implemented in some BIOS. Instead try to discover all devices on bus 0 that are unreachable using MM and fallback for them. We only do this for bus 0/seg 0 */ static __init void unreachable_devices(void) { int i; for (i = 0; i < 32; i++) { u32 val1; char __iomem *addr; pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); if (val1 == 0xffffffff) continue; addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); if (addr == NULL|| readl(addr) != val1) { set_bit(i, &fallback_slots); } } }
int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, unsigned int devfn) { return pci_dev_base(seg, bus, devfn) != NULL; }