驱动工程师最关心就是如何编写PCI设备驱动了.
经过前面的处理,所有设备及其信息都已经遍历出来了.在深入分析PCI驱动架构之前,我们来回顾一下前面遍历PCI设备时,对pci_dev->dev的一些重要成员的赋值.以及各结构在sysfs中的视图
8.1:pci架构在sysfs中视图
1:对于pci_dev
pci_dev->dev的所属bus,parent和name的赋值:
在pci_scan_child_bus() --> pci_scan_slot()--> pci_scan_single_device()-->pci_scan_device():
……
dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type;
……
pci_scan_child_bus()-->pci_scan_slot()-->pci_scan_single_device()-->pci_scan_device()-->pci_setup_device()
……
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
……
由此可见.对于所有的pci_dev.它的所属bus全为pci_bus_type.它的name部份由四个部份组成:所属的总线域(根据代码 看,好像总线域一直都是0.不知道是x86平台是样子,还是我忽略掉了很多东西?),总线号,设备号和功能号.它的parent为 bus->bridge.
既然看一下bus->bridge的赋值:
对于根总线:
pci_scan_bus_parented()-->pci_create_bus():
……
memset(dev, 0, sizeof(*dev));
dev->parent = parent;
dev->release = pci_release_bus_bridge_dev;
sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
error = device_register(dev);
if (error)
goto dev_reg_err;
b->bridge = get_device(dev);
……
从上面的代码片段可以看出.根总线的bridge的赋值情况.对于第一根根总线.对于根总线的name:由pci+两部份组成.分别是总线域和根总线号.
对于下层总线:
pci_scan_bridge()-->pci_add_new_bus()àpci_alloc_child_bus():
……
child->self = bridge;
child->parent = parent;
child->ops = parent->ops;
child->sysdata = parent->sysdata;
child->bus_flags = parent->bus_flags;
child->bridge = get_device(&bridge->dev);
……
从上面的代码看到.下层总线的bridge对应于它的pci-pci bridge.
我们到/sys下面看看,来论证我们的分析:
[root@localhost /]# cd /sys/device
[root@localhost devices]# ls
isa LNXSYSTM:00 pci0000:00 platform pnp0 pnp1 system
可以看到,在/sys/device下有一个名为pci0000:00的结点.根据上面的分析,这就是第一条根总线.另外,也看可以看到,我的机器上只有一条根总线.
[root@localhost devices]# cd pci0000\:00/
[root@localhost pci0000:00]# ls
0000:00:00.0 0000:00:07.0 0000:00:07.2 0000:00:0f.0 0000:00:11.0 pci_bus:0000:00 uevent
0000:00:01.0 0000:00:07.1 0000:00:07.3 0000:00:10.0 0000:00:12.0 power
下面以0000开头的,对应了根总线下的所有设备.其它的文件是在pci_bus_add_device()生成的.我们暂且不要管它们.
再来看一看,下面有没有pci-pci bridge.
[root@localhost pci0000:00]# tree
.
|-- 0000:00:00.0
| |-- broken_parity_status
| |-- bus -> ../../../bus/pci
| |-- class
| |-- config
| |-- device
| |-- driver -> ../../../bus/pci/drivers/agpgart-intel
| |-- enable
| |-- irq
| |-- local_cpus
| |-- modalias
| |-- msi_bus
| |-- power
| | `-- wakeup
| |-- resource
| |-- resource0
| |-- subsystem -> ../../../bus/pci
| |-- subsystem_device
| |-- subsystem_vendor
| |-- uevent
| `-- vendor
|-- 0000:00:01.0
| |-- broken_parity_status
| |-- bus -> ../../../bus/pci
| |-- class
| |-- config
| |-- device
| |-- enable
| |-- irq
| |-- local_cpus
| |-- modalias
| |-- msi_bus
| |-- pci_bus:0000:01 -> ../../../class/pci_bus/0000:01
| |-- power
| | `-- wakeup
| |-- resource
| |-- subsystem -> ../../../bus/pci
| |-- subsystem_device
| |-- subsystem_vendor
| |-- uevent