- 论坛徽章:
- 0
|
zzzzzzzzzs原帖由 zx_wing 于 2008-8-31 17:41 发表
实际上我觉得PCI spec对size的问题讲的不清楚,也可能是我读的不清楚。
flw2你指的PCI spec规定最大是2G是指al贴的那段文字吗?那么根据PCI spec规定如何获取size的方法得到的size最多就不是2G.
Sizing a 3 ...
first clearing encoding information bits
应该就是指 & ~0x0f
比如0xfff00004 & ~0x0f == 0xfff00000
~0xfff00000 == 0x000fffff
0x000fffff + 1 == 1M
这是按照你贴的那段话来计算的
但是不知道是不是因为标准版本的不同还是怎样
我看的例子都是找到最低的位置为1的位(0xfff00000中的最低位), 所以这么计算的话0x00100000计算出来的大小和0xfff00000应该是一样的,而如果按照你贴的方法计算就不对了,而代码做的也是前者的方法
/* Get the lowest of them to find the decode size, and
from that the extent. */
size = (size & ~(size-1)) - 1;
下面这个函数是2.6.26.3的
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
{
unsigned int pos, reg, next;
u32 l, sz;
struct resource *res;
for(pos=0; pos<howmany; pos = next) {
u64 l64;
u64 sz64;
u32 raw_sz;
next = pos+1;
res = &dev->resource[pos];
res->name = pci_name(dev);
reg = PCI_BASE_ADDRESS_0 + (pos << 2);
pci_read_config_dword(dev, reg, &l);
pci_write_config_dword(dev, reg, ~0);
pci_read_config_dword(dev, reg, &sz);
pci_write_config_dword(dev, reg, l);//write orig value
if (!sz || sz == 0xffffffff)
continue;
if (l == 0xffffffff)
l = 0;
raw_sz = sz;
if ((l & PCI_BASE_ADDRESS_SPACE) ==
PCI_BASE_ADDRESS_SPACE_MEMORY) {
sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
/*
* For 64bit prefetchable memory sz could be 0, if the
* real size is bigger than 4G, so we need to check
* szhi for that.
*/
if (!is_64bit_memory(l) && !sz)
continue;
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
} else {
sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
if (!sz)
continue;
res->start = l & PCI_BASE_ADDRESS_IO_MASK;
res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
}
res->end = res->start + (unsigned long) sz;
res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
if (is_64bit_memory(l)) {
u32 szhi, lhi;
pci_read_config_dword(dev, reg+4, &lhi);
pci_write_config_dword(dev, reg+4, ~0);
pci_read_config_dword(dev, reg+4, &szhi);
pci_write_config_dword(dev, reg+4, lhi);
sz64 = ((u64)szhi << 32) | raw_sz;
l64 = ((u64)lhi << 32) | l;
sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK);
next++;
#if BITS_PER_LONG == 64
if (!sz64) {
res->start = 0;
res->end = 0;
res->flags = 0;
continue;
}
res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK;
res->end = res->start + sz64;
#else
if (sz64 > 0x100000000ULL) {
printk(KERN_ERR "PCI: Unable to handle 64-bit "
"BAR for device %s\n", pci_name(dev));
res->start = 0;
res->flags = 0;
} else if (lhi) {
/* 64-bit wide address, treat as disabled */
pci_write_config_dword(dev, reg,
l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
pci_write_config_dword(dev, reg+4, 0);
res->start = 0;
res->end = sz;
}
#endif
}
}
if (rom) {
dev->rom_base_reg = rom;
res = &dev->resource[PCI_ROM_RESOURCE];
res->name = pci_name(dev);
pci_read_config_dword(dev, rom, &l);
pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE);
pci_read_config_dword(dev, rom, &sz);
pci_write_config_dword(dev, rom, l);
if (l == 0xffffffff)
l = 0;
if (sz && sz != 0xffffffff) {
sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
if (sz) {
res->flags = (l & IORESOURCE_ROM_ENABLE) |
IORESOURCE_MEM | IORESOURCE_PREFETCH |
IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
IORESOURCE_SIZEALIGN;
res->start = l & PCI_ROM_ADDRESS_MASK;
res->end = res->start + (unsigned long) sz;
}
}
}
}
|
|
|