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:
@@ -1138,6 +1138,7 @@ PCI::_CreateDevice(PCIBus *parent, uint8 device, uint8 function)
|
|||||||
newDev->bus = parent->bus;
|
newDev->bus = parent->bus;
|
||||||
newDev->device = device;
|
newDev->device = device;
|
||||||
newDev->function = function;
|
newDev->function = function;
|
||||||
|
memset(&newDev->info, 0, sizeof(newDev->info));
|
||||||
|
|
||||||
_ReadBasicInfo(newDev);
|
_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,
|
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,
|
uint32 oldValue = ReadConfig(dev->domain, dev->bus, dev->device, dev->function,
|
||||||
offset, 4);
|
offset, 4);
|
||||||
@@ -1186,14 +1187,20 @@ PCI::_GetBarInfo(PCIDev *dev, uint8 offset, uint32 *_address, uint32 *_size,
|
|||||||
oldValue);
|
oldValue);
|
||||||
|
|
||||||
uint32 mask = PCI_address_memory_32_mask;
|
uint32 mask = PCI_address_memory_32_mask;
|
||||||
|
bool is64bit = (oldValue & PCI_address_type_64) != 0;
|
||||||
if ((oldValue & PCI_address_space) == PCI_address_space)
|
if ((oldValue & PCI_address_space) == PCI_address_space)
|
||||||
mask = PCI_address_io_mask;
|
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;
|
*_address = oldValue & mask;
|
||||||
if (_size != NULL)
|
if (_size != NULL)
|
||||||
*_size = _BarSize(newValue, mask);
|
*_size = _BarSize(newValue, mask);
|
||||||
if (_flags != NULL)
|
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
|
// get BAR size infos
|
||||||
_GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci,
|
_GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci,
|
||||||
&dev->info.u.h0.rom_size);
|
&dev->info.u.h0.rom_size);
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6;) {
|
||||||
_GetBarInfo(dev, PCI_base_registers + 4*i,
|
size_t barSize = _GetBarInfo(dev, PCI_base_registers + 4 * i,
|
||||||
&dev->info.u.h0.base_registers_pci[i],
|
&dev->info.u.h0.base_registers_pci[i],
|
||||||
&dev->info.u.h0.base_register_sizes[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
|
// restore PCI device address decoding
|
||||||
@@ -1287,10 +1298,6 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
|
|||||||
|
|
||||||
dev->info.u.h0.rom_base = (addr_t)pci_ram_address(
|
dev->info.u.h0.rom_base = (addr_t)pci_ram_address(
|
||||||
(void *)(addr_t)dev->info.u.h0.rom_base_pci);
|
(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->info.u.h0.cardbus_cis = ReadConfig(dev->domain, dev->bus,
|
||||||
dev->device, dev->function, PCI_cardbus_cis, 4);
|
dev->device, dev->function, PCI_cardbus_cis, 4);
|
||||||
@@ -1320,11 +1327,15 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
|
|||||||
|
|
||||||
_GetRomBarInfo(dev, PCI_bridge_rom_base,
|
_GetRomBarInfo(dev, PCI_bridge_rom_base,
|
||||||
&dev->info.u.h1.rom_base_pci);
|
&dev->info.u.h1.rom_base_pci);
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2;) {
|
||||||
_GetBarInfo(dev, PCI_base_registers + 4*i,
|
size_t barSize = _GetBarInfo(dev, PCI_base_registers + 4 * i,
|
||||||
&dev->info.u.h1.base_registers_pci[i],
|
&dev->info.u.h1.base_registers_pci[i],
|
||||||
&dev->info.u.h1.base_register_sizes[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
|
// restore PCI device address decoding
|
||||||
@@ -1333,10 +1344,6 @@ PCI::_ReadHeaderInfo(PCIDev *dev)
|
|||||||
|
|
||||||
dev->info.u.h1.rom_base = (addr_t)pci_ram_address(
|
dev->info.u.h1.rom_base = (addr_t)pci_ram_address(
|
||||||
(void *)(addr_t)dev->info.u.h1.rom_base_pci);
|
(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->info.u.h1.primary_bus = ReadConfig(dev->domain, dev->bus,
|
||||||
dev->device, dev->function, PCI_primary_bus, 1);
|
dev->device, dev->function, PCI_primary_bus, 1);
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ private:
|
|||||||
void _RefreshDeviceInfo(PCIBus *bus);
|
void _RefreshDeviceInfo(PCIBus *bus);
|
||||||
|
|
||||||
uint32 _BarSize(uint32 bits, uint32 mask);
|
uint32 _BarSize(uint32 bits, uint32 mask);
|
||||||
void _GetBarInfo(PCIDev *dev, uint8 offset,
|
size_t _GetBarInfo(PCIDev *dev, uint8 offset,
|
||||||
uint32 *address, uint32 *size = 0,
|
uint32 *address, uint32 *size = 0,
|
||||||
uint8 *flags = 0);
|
uint8 *flags = 0, uint32 *highAddress = 0);
|
||||||
void _GetRomBarInfo(PCIDev *dev, uint8 offset,
|
void _GetRomBarInfo(PCIDev *dev, uint8 offset,
|
||||||
uint32 *address, uint32 *size = 0,
|
uint32 *address, uint32 *size = 0,
|
||||||
uint8 *flags = 0);
|
uint8 *flags = 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user