对PCI 设备来讲,只能操作configuration space的256Byte
而PCIe 可以访问整个4096 Bytes 空间
整个配置空间如下图所示
而PCI 设备只能访问256 byte,这256 byte的,这个256 有分为type0 和 type 1,其中type1 是给桥设备用的,type0 是给普通的pci设备使用的.这里一type0 为例
配置空间在kernel中是通过pci_mcfg_lookup来找到
在pci_mcfg_lookup 中首先根据出入的root找到root->mcfg_addr的地址
list_for_each_entry(e, &pci_mcfg_list, list) {
if (e->segment == seg && e->bus_start == bus_res->start &&
e->bus_end >= bus_res->end) {
root->mcfg_addr = e->addr;
}
,如果root->mcfg_addr不为NULL。则对resource 结构提赋值
if (root->mcfg_addr) {
res.start = root->mcfg_addr + (bus_res->start << 20);
res.end = res.start + (resource_size(bus_res) << 20) - 1;
res.flags = IORESOURCE_MEM;
}
然后会调用pci_mcfg_match_quirks 来override 中的ops和resource 资源
static void pci_mcfg_match_quirks(struct acpi_pci_root *root,
struct resource *cfgres,
struct pci_ecam_ops **ecam_ops)
{
struct mcfg_fixup *f;
int i;
/*
* First match against PCI topology <domain:bus> then use OEM ID, OEM
* table ID, and OEM revision from MCFG table standard header.
*/
for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
if (f->seg == root->segment &&
resource_contains(&f->bus_range, &root->secondary) &&
!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
!memcmp(f->oem_table_id, mcfg_oem_table_id,
ACPI_OEM_TABLE_ID_SIZE) &&
f->oem_revision == mcfg_oem_revision) {
if (f->cfgres.start)
*cfgres = f->cfgres;
if (f->ops)
*ecam_ops = f->ops;
dev_info(&root->device->dev, "Applying PCI MCFG quirks for %s %s rev: %d\n",
f->oem_id, f->oem_table_id, f->oem_revision);
return;
}
}
}
在pci_mcfg_match_quirks 会根据bios传递过来的mcfg_oem_id/mcfg_oem_table_id/mcfg_oem_revision 来在mcfg_quirks 这个数组中找到ops和resource,来覆盖从pci_mcfg_list 得到的resource和ops
得到resource后,做ioremap后,就可以通过ops来访问这最大4k的空间
ops 举例如下:
/* ECAM ops */
struct pci_ecam_ops pci_generic_ecam_ops = {
.bus_shift = 20,
.pci_ops = {
.map_bus = pci_ecam_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
}
};
可见提供read/write 函数来操作pcie的配置空间.