diff --git a/src/device/pci_device.c b/src/device/pci_device.c index fbe9d9691b..5f908d2f68 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -734,11 +734,31 @@ void pci_bus_reset(struct bus *bus) void pci_dev_set_subsystem(struct device *dev, unsigned int vendor, unsigned int device) { + uint8_t offset; + + /* Header type */ + switch (dev->hdr_type & 0x7f) { + case PCI_HEADER_TYPE_NORMAL: + offset = PCI_SUBSYSTEM_VENDOR_ID; + break; + case PCI_HEADER_TYPE_BRIDGE: + offset = pci_find_capability(dev, PCI_CAP_ID_SSVID); + if (!offset) + return; + offset += 4; /* Vendor ID at offset 4 */ + break; + case PCI_HEADER_TYPE_CARDBUS: + offset = PCI_CB_SUBSYSTEM_VENDOR_ID; + break; + default: + return; + } + if (!vendor || !device) { - pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_write_config32(dev, offset, pci_read_config32(dev, PCI_VENDOR_ID)); } else { - pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_write_config32(dev, offset, ((device & 0xffff) << 16) | (vendor & 0xffff)); } } diff --git a/src/include/device/pci_def.h b/src/include/device/pci_def.h index f9ce1a6382..bc5bc79e28 100644 --- a/src/include/device/pci_def.h +++ b/src/include/device/pci_def.h @@ -198,6 +198,7 @@ #define PCI_CAP_ID_HT 0x08 /* Hypertransport */ #define PCI_CAP_ID_EHCI_DEBUG 0x0A /* EHCI debug port */ #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ +#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ #define PCI_CAP_ID_PCIE 0x10 /* PCI Express */ #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */