1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| /* * 直接读硬件配置空间中的interrupt line and pin,然后写到pci_dev->line、pci_dev->irq中 */ pci_read_irq(dev)
/* 依次读取6个bar的内容,相关内容写入pci_dev下的struct resource resource[] */ pci_read_bases(dev, 6, PCI_ROM_ADDRESS); -->__pci_read_bases -->mask = type ? PCI_ROM_ADDRESS_MASK : ~0; /* 最初探测bar的大小,向bar空间写入全1 */ -->pci_write_config_dword(dev, pos, l | mask); /* 读出提示信息,写入sz缓存 */ -->pci_read_config_dword(dev, pos, &sz); /* 如果全1, 设备工作不正常,或是没有这个bar */ -->if (sz == 0xffffffff) sz = 0;
-->if (type == pci_bar_unknown) { /* 根据上面sz的值,得到是io/mem bar, 32/64bits, prefectch/ * non-prefectch。这些信息都会写入res->flags中的对应bit */ /* 如果l = 0, 解析的结果,kernel会认为这是一个32bit, * non-prefetchable, mem bar */ -->res->flags = decode_bar(dev, l); res->flags |= IORESOURCE_SIZEALIGN; if (res->flags & IORESOURCE_IO) { ... } else { /* 下面先把低32bits写到64bits变量的低32bits */ /* 如果l = 0, l64 = 0 */ l64 = l & PCI_BASE_ADDRESS_MEM_MASK; /* sz是写入全1后从bar中得到的值,如果是0xf000000f * sz64 = 0xf0000000 */ sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK; /* ul的变量是多少bits? */ /* 应该是0xfffffff0 */ mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK; } } else { ... }
if (res->flags & IORESOURCE_MEM_64) { pci_read_config_dword(dev, pos + 4, &l); pci_write_config_dword(dev, pos + 4, ~0); pci_read_config_dword(dev, pos + 4, &sz); pci_write_config_dword(dev, pos + 4, l);
l64 |= ((u64)l << 32); sz64 |= ((u64)sz << 32); mask64 |= ((u64)~0 << 32); } ... sz64 = pci_size(l64, sz64, mask64); /* size = 0xf000_0000 */ --> size = sz64 & mask64; /* size = 0x0fff_ffff, and return this */ --> size = (size & ~(size-1)) - 1;
/* struct pci_bus_region, local struct. indicate a bar's resource? */ region.start = l64; /* l64 = 0 */ region.end = l64 + sz64; /* 0x0fff_ffff */
pcibios_bus_to_resource(dev->bus, res, ®ion); /* 首先找到host中的对应资源 */ --> resource_list_for_each_entry(window, &bridge->windows) { --> if (resource_type(res) != resource_type(window->res)) /* 找到对应到pci域中的起始地址 */ --> bus_region.start = window->res->start - window->offset; --> bus_region.end = window->res->end - window->offset;
pcibios_resource_to_bus(dev->bus, &inverted_region, res);
|