pci: takes into account the 64bit address type

* when the 64bit address type is used, it means a BAR takes the size of two.
For the moment we just set the next base_registers to the high address
and skip to the next valid BAR. The struct is now zeroed on creation.
* the pci device information is more correct now, though it would be easier
to have BAR address and size with a 64bit types in the struct pci_info.
This commit is contained in:
Jérôme Duval
2013-06-19 21:04:36 +02:00
parent e2a87acacd
commit 343751a96c
2 changed files with 26 additions and 19 deletions
+24 -17
View File
@@ -1138,6 +1138,7 @@ PCI::_CreateDevice(PCIBus *parent, uint8 device, uint8 function)
newDev->bus = parent->bus;
newDev->device = device;
newDev->function = function;
memset(&newDev->info, 0, sizeof(newDev->info));
_ReadBasicInfo(newDev);
@@ -1172,9 +1173,9 @@ PCI::_BarSize(uint32 bits, uint32 mask)
}
void
size_t
PCI::_GetBarInfo(PCIDev *dev, uint8 offset, uint32 *_address, uint32 *_size,
uint8 *_flags)
uint8 *_flags, uint32 *_highAddress)
{
uint32 oldValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function,
offset, 4);
@@ -1186,14 +1187,20 @@ PCI::_GetBarInfo(PCIDev *dev, uint8 offset, uint32 *_address, uint32 *_size,
oldValue);
uint32 mask = PCI_address_memory_32_mask;
bool is64bit = (oldValue & PCI_address_type_64) != 0;
if ((oldValue & PCI_address_space) == PCI_address_space)
mask = PCI_address_io_mask;
else if (is64bit && _highAddress != NULL) {
*_highAddress = ReadConfig(dev->domain, dev->bus, dev->device,
dev->function, offset + 4, 4);
}
*_address = oldValue & mask;
if (_size != NULL)
*_size = _BarSize(newValue, mask);
if (_flags != NULL)
*_flags = newValue & ~mask;
*_flags = oldValue & ~mask;
return is64bit ? 2 : 1;
}
@@ -1274,11 +1281,15 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
// get BAR size infos
_GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci,
&dev->info.u.h0.rom_size);
for (int i = 0; i < 6; i++) {
_GetBarInfo(dev, PCI_base_registers + 4*i,
for (int i = 0; i < 6;) {
size_t barSize = _GetBarInfo(dev, PCI_base_registers + 4 * i,
&dev->info.u.h0.base_registers_pci[i],
&dev->info.u.h0.base_register_sizes[i],
&dev->info.u.h0.base_register_flags[i]);
&dev->info.u.h0.base_register_flags[i],
i < 5 ? &dev->info.u.h0.base_registers_pci[i + 1] : NULL);
dev->info.u.h0.base_registers[i] = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h0.base_registers_pci[i]);
i += barSize;
}
// restore PCI device address decoding
@@ -1287,10 +1298,6 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
dev->info.u.h0.rom_base = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h0.rom_base_pci);
for (int i = 0; i < 6; i++) {
dev->info.u.h0.base_registers[i] = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h0.base_registers_pci[i]);
}
dev->info.u.h0.cardbus_cis = ReadConfig(dev->domain, dev->bus,
dev->device, dev->function, PCI_cardbus_cis, 4);
@@ -1320,11 +1327,15 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
_GetRomBarInfo(dev, PCI_bridge_rom_base,
&dev->info.u.h1.rom_base_pci);
for (int i = 0; i < 2; i++) {
_GetBarInfo(dev, PCI_base_registers + 4*i,
for (int i = 0; i < 2;) {
size_t barSize = _GetBarInfo(dev, PCI_base_registers + 4 * i,
&dev->info.u.h1.base_registers_pci[i],
&dev->info.u.h1.base_register_sizes[i],
&dev->info.u.h1.base_register_flags[i]);
&dev->info.u.h1.base_register_flags[i],
i < 5 ? &dev->info.u.h1.base_registers_pci[i + 1] : NULL);
dev->info.u.h1.base_registers[i] = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h1.base_registers_pci[i]);
i += barSize;
}
// restore PCI device address decoding
@@ -1333,10 +1344,6 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
dev->info.u.h1.rom_base = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h1.rom_base_pci);
for (int i = 0; i < 2; i++) {
dev->info.u.h1.base_registers[i] = (addr_t)pci_ram_address(
(void *)(addr_t)dev->info.u.h1.base_registers_pci[i]);
}
dev->info.u.h1.primary_bus = ReadConfig(dev->domain, dev->bus,
dev->device, dev->function, PCI_primary_bus, 1);
+2 -2
View File
@@ -134,9 +134,9 @@ private:
void _RefreshDeviceInfo(PCIBus *bus);
uint32 _BarSize(uint32 bits, uint32 mask);
void _GetBarInfo(PCIDev *dev, uint8 offset,
size_t _GetBarInfo(PCIDev *dev, uint8 offset,
uint32 *address, uint32 *size = 0,
uint8 *flags = 0);
uint8 *flags = 0, uint32 *highAddress = 0);
void _GetRomBarInfo(PCIDev *dev, uint8 offset,
uint32 *address, uint32 *size = 0,
uint8 *flags = 0);