2121#include "pci-bridge-emul.h"
2222
2323#define PCI_BRIDGE_CONF_END PCI_STD_HEADER_SIZEOF
24+ #define PCI_CAP_SSID_SIZEOF (PCI_SSVID_DEVICE_ID + 2)
25+ #define PCI_CAP_SSID_START PCI_BRIDGE_CONF_END
26+ #define PCI_CAP_SSID_END (PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
2427#define PCI_CAP_PCIE_SIZEOF (PCI_EXP_SLTSTA2 + 2)
25- #define PCI_CAP_PCIE_START PCI_BRIDGE_CONF_END
28+ #define PCI_CAP_PCIE_START PCI_CAP_SSID_END
2629#define PCI_CAP_PCIE_END (PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
2730
2831/**
@@ -315,6 +318,25 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] =
315318 },
316319};
317320
321+ static pci_bridge_emul_read_status_t
322+ pci_bridge_emul_read_ssid (struct pci_bridge_emul * bridge , int reg , u32 * value )
323+ {
324+ switch (reg ) {
325+ case PCI_CAP_LIST_ID :
326+ * value = PCI_CAP_ID_SSVID |
327+ (bridge -> has_pcie ? (PCI_CAP_PCIE_START << 8 ) : 0 );
328+ return PCI_BRIDGE_EMUL_HANDLED ;
329+
330+ case PCI_SSVID_VENDOR_ID :
331+ * value = bridge -> subsystem_vendor_id |
332+ (bridge -> subsystem_id << 16 );
333+ return PCI_BRIDGE_EMUL_HANDLED ;
334+
335+ default :
336+ return PCI_BRIDGE_EMUL_NOT_HANDLED ;
337+ }
338+ }
339+
318340/*
319341 * Initialize a pci_bridge_emul structure to represent a fake PCI
320342 * bridge configuration space. The caller needs to have initialized
@@ -341,9 +363,17 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
341363 if (!bridge -> pci_regs_behavior )
342364 return - ENOMEM ;
343365
344- if (bridge -> has_pcie ) {
366+ if (bridge -> subsystem_vendor_id )
367+ bridge -> conf .capabilities_pointer = PCI_CAP_SSID_START ;
368+ else if (bridge -> has_pcie )
345369 bridge -> conf .capabilities_pointer = PCI_CAP_PCIE_START ;
370+ else
371+ bridge -> conf .capabilities_pointer = 0 ;
372+
373+ if (bridge -> conf .capabilities_pointer )
346374 bridge -> conf .status |= cpu_to_le16 (PCI_STATUS_CAP_LIST );
375+
376+ if (bridge -> has_pcie ) {
347377 bridge -> pcie_conf .cap_id = PCI_CAP_ID_EXP ;
348378 bridge -> pcie_conf .cap |= cpu_to_le16 (PCI_EXP_TYPE_ROOT_PORT << 4 );
349379 bridge -> pcie_cap_regs_behavior =
@@ -427,26 +457,28 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
427457 read_op = bridge -> ops -> read_base ;
428458 cfgspace = (__le32 * ) & bridge -> conf ;
429459 behavior = bridge -> pci_regs_behavior ;
430- } else if (!bridge -> has_pcie ) {
431- /* PCIe space is not implemented, and no PCI capabilities */
432- * value = 0 ;
433- return PCIBIOS_SUCCESSFUL ;
434- } else if (reg < PCI_CAP_PCIE_END ) {
460+ } else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge -> subsystem_vendor_id ) {
461+ /* Emulated PCI Bridge Subsystem Vendor ID capability */
462+ reg -= PCI_CAP_SSID_START ;
463+ read_op = pci_bridge_emul_read_ssid ;
464+ cfgspace = NULL ;
465+ behavior = NULL ;
466+ } else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge -> has_pcie ) {
435467 /* Our emulated PCIe capability */
436468 reg -= PCI_CAP_PCIE_START ;
437469 read_op = bridge -> ops -> read_pcie ;
438470 cfgspace = (__le32 * ) & bridge -> pcie_conf ;
439471 behavior = bridge -> pcie_cap_regs_behavior ;
440- } else if (reg < PCI_CFG_SPACE_SIZE ) {
441- /* Rest of PCI space not implemented */
442- * value = 0 ;
443- return PCIBIOS_SUCCESSFUL ;
444- } else {
472+ } else if (reg >= PCI_CFG_SPACE_SIZE && bridge -> has_pcie ) {
445473 /* PCIe extended capability space */
446474 reg -= PCI_CFG_SPACE_SIZE ;
447475 read_op = bridge -> ops -> read_ext ;
448476 cfgspace = NULL ;
449477 behavior = NULL ;
478+ } else {
479+ /* Not implemented */
480+ * value = 0 ;
481+ return PCIBIOS_SUCCESSFUL ;
450482 }
451483
452484 if (read_op )
@@ -504,24 +536,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
504536 write_op = bridge -> ops -> write_base ;
505537 cfgspace = (__le32 * ) & bridge -> conf ;
506538 behavior = bridge -> pci_regs_behavior ;
507- } else if (!bridge -> has_pcie ) {
508- /* PCIe space is not implemented, and no PCI capabilities */
509- return PCIBIOS_SUCCESSFUL ;
510- } else if (reg < PCI_CAP_PCIE_END ) {
539+ } else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge -> has_pcie ) {
511540 /* Our emulated PCIe capability */
512541 reg -= PCI_CAP_PCIE_START ;
513542 write_op = bridge -> ops -> write_pcie ;
514543 cfgspace = (__le32 * ) & bridge -> pcie_conf ;
515544 behavior = bridge -> pcie_cap_regs_behavior ;
516- } else if (reg < PCI_CFG_SPACE_SIZE ) {
517- /* Rest of PCI space not implemented */
518- return PCIBIOS_SUCCESSFUL ;
519- } else {
545+ } else if (reg >= PCI_CFG_SPACE_SIZE && bridge -> has_pcie ) {
520546 /* PCIe extended capability space */
521547 reg -= PCI_CFG_SPACE_SIZE ;
522548 write_op = bridge -> ops -> write_ext ;
523549 cfgspace = NULL ;
524550 behavior = NULL ;
551+ } else {
552+ /* Not implemented */
553+ return PCIBIOS_SUCCESSFUL ;
525554 }
526555
527556 shift = (where & 0x3 ) * 8 ;
0 commit comments