Revision 929176c3 hw/pci.c
b/hw/pci.c | ||
---|---|---|
1540 | 1540 |
} |
1541 | 1541 |
} |
1542 | 1542 |
|
1543 |
/* Whether a given bus number is in range of the secondary |
|
1544 |
* bus of the given bridge device. */ |
|
1545 |
static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num) |
|
1546 |
{ |
|
1547 |
return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) & |
|
1548 |
PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ && |
|
1549 |
dev->config[PCI_SECONDARY_BUS] < bus_num && |
|
1550 |
bus_num <= dev->config[PCI_SUBORDINATE_BUS]; |
|
1551 |
} |
|
1552 |
|
|
1543 | 1553 |
PCIBus *pci_find_bus(PCIBus *bus, int bus_num) |
1544 | 1554 |
{ |
1545 | 1555 |
PCIBus *sec; |
... | ... | |
1552 | 1562 |
return bus; |
1553 | 1563 |
} |
1554 | 1564 |
|
1565 |
/* Consider all bus numbers in range for the host pci bridge. */ |
|
1566 |
if (bus->parent_dev && |
|
1567 |
!pci_secondary_bus_in_range(bus->parent_dev, bus_num)) { |
|
1568 |
return NULL; |
|
1569 |
} |
|
1570 |
|
|
1555 | 1571 |
/* try child bus */ |
1556 |
if (!bus->parent_dev /* host pci bridge */ || |
|
1557 |
(bus->parent_dev->config[PCI_SECONDARY_BUS] < bus_num && |
|
1558 |
bus_num <= bus->parent_dev->config[PCI_SUBORDINATE_BUS])) { |
|
1559 |
for (; bus; bus = sec) { |
|
1560 |
QLIST_FOREACH(sec, &bus->child, sibling) { |
|
1561 |
assert(sec->parent_dev); |
|
1562 |
if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) { |
|
1563 |
return sec; |
|
1564 |
} |
|
1565 |
if (sec->parent_dev->config[PCI_SECONDARY_BUS] < bus_num && |
|
1566 |
bus_num <= sec->parent_dev->config[PCI_SUBORDINATE_BUS]) { |
|
1567 |
break; |
|
1568 |
} |
|
1572 |
for (; bus; bus = sec) { |
|
1573 |
QLIST_FOREACH(sec, &bus->child, sibling) { |
|
1574 |
assert(sec->parent_dev); |
|
1575 |
if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) { |
|
1576 |
return sec; |
|
1577 |
} |
|
1578 |
if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) { |
|
1579 |
break; |
|
1569 | 1580 |
} |
1570 | 1581 |
} |
1571 | 1582 |
} |
Also available in: Unified diff