.write = pci_conf1_write, };
这个结构其实就是pci设备配置空间操作的接口.
五:pci设备的枚举过程 返回到pci_legacy_init()中 static int __init pci_legacy_init(void) {
……
printk(\ pci_root_bus = pcibios_scan_root(0); if (pci_root_bus)
pci_bus_add_devices(pci_root_bus); …… }
Pci设备的枚举过程是由pcibios_scan_root()完成的.在这里调用是以0为参数.说明是从根总线起开始枚举.
pcibios_scan_root()代码如下:
struct pci_bus * __devinit pcibios_scan_root(int busnum) {
struct pci_bus *bus = NULL; struct pci_sysdata *sd;
dmi_check_system(pciprobe_dmi_table);
while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ return bus; } }
/* Allocate per-root-bus (not per bus) arch-specific data. * TODO: leak; this memory is never freed. * It's arguable whether it's worth the trouble to care. */
sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (!sd) {
printk(KERN_ERR %um); return NULL; }
printk(KERN_DEBUG \
return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
5
}
先在pci_root_buses中判断是否存在这个根总线对应的总线号.如果存在,说明这条总线已经遍历过了,直接退出. Pci_root_ops这是定义的pci设备配置空间的操作.在没有选择CONFIG_PCI_MMCONFIG的情况下,它的操作都会转入我们在上面的分析的,ram_pci_ops中.这个过程非常简单,可以自行分析. 然后,流程转入pci_scan_bus_parented().代码如下:
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) {
struct pci_bus *b;
b = pci_create_bus(parent, bus, ops, sysdata); if (b)
b->subordinate = pci_scan_child_bus(b); return b; }
在pci_create_bus()中,为对应总线号构建pci_bus,然后将其挂入到pci_root_buses链表.该函数代码比较简单,请自行分析.然后,调用然后pci_scan_child_bus枚举该总线下的所有设备.pci_bus->subordinate表示下流总线的最大总线号.pci_sacn_child_bus()代码如下:
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) {
unsigned int devfn, pass, max = bus->secondary; struct pci_dev *dev;
pr_debug(\>number);
/* Go find them, Rover! */
//按功能号扫描设备号对应的pci 设备 for (devfn = 0; devfn < 0x100; devfn += 8) pci_scan_slot(bus, devfn); /*
* After performing arch-dependent fixup of the bus, look behind * all PCI-to-PCI bridges on this bus. */
pr_debug(%umber); pcibios_fixup_bus(bus); for (pass=0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
6
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) max = pci_scan_bridge(bus, dev, max, pass); } /*
* We've scanned the bus and so we know all about what's on * the other side of any bridges that may be on this bus plus * any devices. *
* Return how far we've got finding sub-buses. */
pr_debug(\ pci_domain_nr(bus), bus->number, max); return max; }
这节的难点就是在这个地方了,从我们之前分析的pci设备配置空间的读写方式可得知.对特定总线.下面最多个32个设备号.每个设备号又对应8 个功能号.我们可以将设备号和功能号放到一起,即占8~15位.在这面的代码中.对每个设备号调用pci_scan_slot()去扫描它下面的8个功能号对应的设备.总而言之,把该总线下面的所有设备都要枚举完.
pci_scan_slot()代码如下:
nt pci_scan_slot(struct pci_bus *bus, int devfn) {
int func, nr = 0; int scan_all_fns;
scan_all_fns = pcibios_scan_all_fns(bus, devfn);
for (func = 0; func < 8; func++, devfn++) { struct pci_dev *dev;
dev = pci_scan_single_device(bus, devfn); if (dev) { nr++;
/*
* If this is a single function device, * don't scan past the first function. */
if (!dev->multifunction) { if (func > 0) {
dev->multifunction = 1; } else { break;
7
} } } else {
if (func == 0 && !scan_all_fns) break; } } return nr; }
对其它的每个设备都会调用pci_scan_single_device().如果是单功能设备(dev->multifunction == 0).则只要判断它的第一个功能号可以了,不需要判断之后功能号对应的设备. Pci_scan_single_device()代码如下:
struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) {
struct pci_dev *dev;
dev = pci_scan_device(bus, devfn); if (!dev)
return NULL;
//将pci_dev加至pci_bus->devices pci_device_add(dev, bus);
return dev; }
对每个设备,都会调用pci_scan_device()执行扫描的过程,如果该设备存在,就会将该设备加入到所属总线的devices链表上.这是在pci_device_add()函数中完成的,这个函数比较简单.这里不做详细分析.我们把注意力集中到pci_scan_device(),这函数有点长,分段分析如下:
static struct pci_dev * __devinit
pci_scan_device(struct pci_bus *bus, int devfn) {
struct pci_dev *dev; u32 l; u8 hdr_type; int delay = 1;
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) return NULL;
/* some broken boards return 0 or ~0 if a slot is empty: */ if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) return NULL;
8