summaryrefslogtreecommitdiffstats
path: root/src/hardware
diff options
context:
space:
mode:
Diffstat (limited to 'src/hardware')
-rw-r--r--src/hardware/90_LMI_Hardware_Profile_DMTF.mof26
-rw-r--r--src/hardware/CMakeLists.txt1
-rw-r--r--src/hardware/LMI_Hardware.h4
-rw-r--r--src/hardware/LMI_PCIBridgeProvider.c620
-rw-r--r--src/hardware/LMI_PCIBridgeSystemDeviceProvider.c280
-rw-r--r--src/hardware/LMI_PCIDeviceProvider.c96
-rw-r--r--src/hardware/LMI_PCIDeviceSystemDeviceProvider.c10
-rw-r--r--src/hardware/PCIDev.c77
-rw-r--r--src/hardware/PCIDev.h44
9 files changed, 1077 insertions, 81 deletions
diff --git a/src/hardware/90_LMI_Hardware_Profile_DMTF.mof b/src/hardware/90_LMI_Hardware_Profile_DMTF.mof
index 777fa90..81e5b2c 100644
--- a/src/hardware/90_LMI_Hardware_Profile_DMTF.mof
+++ b/src/hardware/90_LMI_Hardware_Profile_DMTF.mof
@@ -97,3 +97,29 @@ instance of PG_ProviderProfileCapabilities
"LMI_PCIDevice"
};
};
+
+instance of PG_ProviderProfileCapabilities
+{
+ CapabilityID = "LMI_PCIBridge_DMTF";
+
+ ProviderModuleName = "cmpiLMI_Hardware";
+
+ ProviderName = "LMI_PCIBridge";
+
+ RegisteredProfile = 507;
+
+ ProfileVersion = "1.0.2";
+
+ RegisteredSubprofiles = {
+ 3038
+ };
+
+ SubprofileVersions = {
+ "1.0.0"
+ };
+
+ ConformingElements = {
+ "LMI_PCIBridge"
+ };
+};
+
diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt
index 8089a08..8ccf649 100644
--- a/src/hardware/CMakeLists.txt
+++ b/src/hardware/CMakeLists.txt
@@ -9,6 +9,7 @@ set(provider_SRCS
lscpu.c
procfs.c
sysfs.c
+ PCIDev.c
)
konkretcmpi_generate(${MOF}
diff --git a/src/hardware/LMI_Hardware.h b/src/hardware/LMI_Hardware.h
index e72536a..7f94055 100644
--- a/src/hardware/LMI_Hardware.h
+++ b/src/hardware/LMI_Hardware.h
@@ -40,8 +40,6 @@
#define BATTERY_CLASS_NAME "Battery"
#define BATTERY_PHYS_PKG_CLASS_NAME "BatteryPhysicalPackage"
#define PCI_DEVICE_CLASS_NAME "PCIDevice"
-
-/* PCIDevices */
-#define PCI_DEVID_STR_SIZE 55
+#define PCI_BRIDGE_CLASS_NAME "PCIBridge"
#endif /* LMI_HARDWARE_H_ */
diff --git a/src/hardware/LMI_PCIBridgeProvider.c b/src/hardware/LMI_PCIBridgeProvider.c
new file mode 100644
index 0000000..3392772
--- /dev/null
+++ b/src/hardware/LMI_PCIBridgeProvider.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include <konkret/konkret.h>
+#include "LMI_PCIBridge.h"
+#include "LMI_Hardware.h"
+#include "PCIDev.h"
+#include "globals.h"
+
+CMPIUint16 get_bridge_type(const char *bridge_type);
+
+static const CMPIBroker* _cb = NULL;
+
+static void LMI_PCIBridgeInitialize()
+{
+}
+
+static CMPIStatus LMI_PCIBridgeCleanup(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeEnumInstanceNames(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ return KDefaultEnumerateInstanceNames(
+ _cb, mi, cc, cr, cop);
+}
+
+static CMPIStatus LMI_PCIBridgeEnumInstances(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ LMI_PCIBridge lmi_dev;
+ const char *ns = KNameSpace(cop);
+ int i;
+ CMPICount count;
+ CMPIUint16 pci_cap;
+ u8 rev, cache_line, subordinate_bus, secondary_bus, primary_bus;
+ u16 svid, subid, status, command_reg, sec_status;
+ u32 io_base, io_limit, io_type, mem_base, mem_limit, mem_type, pref_base,
+ pref_limit, pref_type, pref_base_upper = 0, pref_limit_upper = 0;
+ struct pci_access *acc;
+ struct pci_dev *dev;
+ struct pci_cap *cap;
+ char vendor_buf[NAME_BUF_SIZE], *vendor_name;
+ char device_buf[NAME_BUF_SIZE], *device_name;
+ char subsys_buf[NAME_BUF_SIZE], *subsys_name;
+ char svendor_buf[NAME_BUF_SIZE], *svendor_name;
+ char class_buf[NAME_BUF_SIZE], *class;
+ char device_id_str[PCI_DEVID_STR_SIZE];
+ char instance_id[INSTANCE_ID_LEN];
+
+ if (!(acc = pci_alloc())) {
+ KReturn2(_cb, ERR_FAILED, "Cannot access the PCI bus.");
+ }
+ pci_init(acc);
+ pci_scan_bus(acc);
+
+ for (dev = acc->devices; dev; dev = dev->next) {
+ pci_fill_info(dev,
+ PCI_FILL_IDENT
+ | PCI_FILL_IRQ
+ | PCI_FILL_BASES
+ | PCI_FILL_ROM_BASE
+ | PCI_FILL_CLASS
+ | PCI_FILL_CAPS);
+
+ /* Use only PCI Bridges */
+ /* Throw away the lower 8 bits denoting the subclass */
+ if (((dev->device_class) >> 8) != LMI_PCIBridge_ClassCode_Bridge) {
+ continue;
+ }
+
+ vendor_name = pci_lookup_name(acc, vendor_buf, NAME_BUF_SIZE,
+ PCI_LOOKUP_VENDOR, dev->vendor_id);
+ device_name = pci_lookup_name(acc, device_buf, NAME_BUF_SIZE,
+ PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
+ get_subid(dev, &svid, &subid);
+ subsys_name = pci_lookup_name(acc, subsys_buf, NAME_BUF_SIZE,
+ PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM,
+ dev->vendor_id, dev->device_id, svid, subid);
+ svendor_name = pci_lookup_name(acc, svendor_buf, NAME_BUF_SIZE,
+ PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM, svid);
+ class = pci_lookup_name(acc, class_buf, NAME_BUF_SIZE,
+ PCI_LOOKUP_CLASS, dev->device_class);
+ status = pci_read_word(dev, PCI_STATUS);
+ rev = pci_read_byte(dev, PCI_REVISION_ID);
+ cache_line = pci_read_byte(dev, PCI_CACHE_LINE_SIZE);
+ command_reg = pci_read_word(dev, PCI_COMMAND);
+ subordinate_bus = pci_read_byte(dev, PCI_SUBORDINATE_BUS);
+ secondary_bus = pci_read_byte(dev, PCI_SECONDARY_BUS);
+ primary_bus = pci_read_byte(dev, PCI_PRIMARY_BUS);
+ io_base = pci_read_byte(dev, PCI_IO_BASE);
+ io_limit = pci_read_byte(dev, PCI_IO_LIMIT);
+ io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
+ mem_base = pci_read_word(dev, PCI_MEMORY_BASE);
+ mem_limit = pci_read_word(dev, PCI_MEMORY_LIMIT);
+ mem_type = mem_base & PCI_MEMORY_RANGE_TYPE_MASK;
+ pref_base = pci_read_word(dev, PCI_PREF_MEMORY_BASE);
+ pref_limit = pci_read_word(dev, PCI_PREF_MEMORY_LIMIT);
+ pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
+ sec_status = pci_read_word(dev, PCI_SEC_STATUS);
+
+ snprintf(device_id_str, PCI_DEVID_STR_SIZE, "%02x:%02x.%u",
+ dev->bus, dev->dev, dev->func);
+ snprintf(instance_id, INSTANCE_ID_LEN,
+ ORGID ":" ORGID "_" PCI_BRIDGE_CLASS_NAME ":%s", device_id_str);
+
+ LMI_PCIBridge_Init(&lmi_dev, _cb, ns);
+
+ LMI_PCIBridge_Set_SystemCreationClassName(&lmi_dev,
+ get_system_creation_class_name());
+ LMI_PCIBridge_Set_SystemName(&lmi_dev, get_system_name());
+ LMI_PCIBridge_Set_CreationClassName(&lmi_dev,
+ ORGID "_" PCI_BRIDGE_CLASS_NAME);
+ LMI_PCIBridge_Set_Caption(&lmi_dev,
+ "This object represents one PCI bridge contained in system.");
+
+ LMI_PCIBridge_Set_PrimaryStatus(&lmi_dev,
+ LMI_PCIBridge_PrimaryStatus_Unknown);
+ LMI_PCIBridge_Set_HealthState(&lmi_dev,
+ LMI_PCIBridge_HealthState_Unknown);
+
+ LMI_PCIBridge_Set_DeviceID(&lmi_dev, device_id_str);
+ LMI_PCIBridge_Set_BusNumber(&lmi_dev, dev->bus);
+ LMI_PCIBridge_Set_DeviceNumber(&lmi_dev, dev->dev);
+ LMI_PCIBridge_Set_FunctionNumber(&lmi_dev, dev->func);
+ LMI_PCIBridge_Set_Name(&lmi_dev, device_name);
+ LMI_PCIBridge_Set_ElementName(&lmi_dev, device_name);
+
+ LMI_PCIBridge_Set_VendorID(&lmi_dev, dev->vendor_id);
+ LMI_PCIBridge_Set_PCIDeviceID(&lmi_dev, dev->device_id);
+ LMI_PCIBridge_Set_PCIDeviceName(&lmi_dev, device_name);
+ if (vendor_name) {
+ LMI_PCIBridge_Set_VendorName(&lmi_dev, vendor_name);
+ }
+ if (svid > 0 && svid < 65535) {
+ LMI_PCIBridge_Set_SubsystemVendorID(&lmi_dev, svid);
+ if (svendor_name) {
+ LMI_PCIBridge_Set_SubsystemVendorName(&lmi_dev, svendor_name);
+ }
+ }
+ if (subid > 0 && subid < 65535) {
+ LMI_PCIBridge_Set_SubsystemID(&lmi_dev, subid);
+ if (subsys_name) {
+ LMI_PCIBridge_Set_SubsystemName(&lmi_dev, subsys_name);
+ }
+ }
+ if (class) {
+ LMI_PCIBridge_Set_BridgeType(&lmi_dev, get_bridge_type(class));
+ } else {
+ LMI_PCIBridge_Set_BridgeType(&lmi_dev,
+ LMI_PCIBridge_BridgeType_Other);
+ }
+
+ if (rev) {
+ LMI_PCIBridge_Set_RevisionID(&lmi_dev, rev);
+ }
+ if (cache_line) {
+ LMI_PCIBridge_Set_CacheLineSize(&lmi_dev, cache_line);
+ }
+ if (command_reg) {
+ LMI_PCIBridge_Set_CommandRegister(&lmi_dev, command_reg);
+ }
+ if (subordinate_bus) {
+ LMI_PCIBridge_Set_SubordinateBusNumber(&lmi_dev, subordinate_bus);
+ }
+ if (secondary_bus) {
+ LMI_PCIBridge_Set_SecondayBusNumber(&lmi_dev, secondary_bus);
+ }
+ LMI_PCIBridge_Set_PrimaryBusNumber(&lmi_dev, primary_bus);
+
+ /* Throw away the lower 8 bits denoting the subclass */
+ LMI_PCIBridge_Set_ClassCode(&lmi_dev, ((dev->device_class) >> 8));
+
+ if (status) {
+ if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) {
+ LMI_PCIBridge_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_DeviceSelectTiming_Slow);
+ } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) {
+ LMI_PCIBridge_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_DeviceSelectTiming_Medium);
+ } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) {
+ LMI_PCIBridge_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_DeviceSelectTiming_Fast);
+ }
+ }
+ if (sec_status) {
+ LMI_PCIBridge_Set_SecondaryStatusRegister(&lmi_dev, sec_status);
+ if ((sec_status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) {
+ LMI_PCIBridge_Set_SecondaryBusDeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_SecondaryBusDeviceSelectTiming_Slow);
+ } else if ((sec_status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) {
+ LMI_PCIBridge_Set_SecondaryBusDeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_SecondaryBusDeviceSelectTiming_Medium);
+ } else if ((sec_status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) {
+ LMI_PCIBridge_Set_SecondaryBusDeviceSelectTiming(&lmi_dev,
+ LMI_PCIBridge_SecondaryBusDeviceSelectTiming_Fast);
+ }
+ }
+
+ if (dev->rom_base_addr) {
+ LMI_PCIBridge_Set_ExpansionROMBaseAddress(&lmi_dev,
+ dev->rom_base_addr);
+ }
+
+ LMI_PCIBridge_Set_InstanceID(&lmi_dev, instance_id);
+ LMI_PCIBridge_Set_InterruptPin(&lmi_dev,
+ pci_read_byte(dev, PCI_INTERRUPT_PIN));
+ LMI_PCIBridge_Set_LatencyTimer(&lmi_dev,
+ pci_read_byte(dev, PCI_LATENCY_TIMER));
+ LMI_PCIBridge_Set_SecondaryLatencyTimer(&lmi_dev,
+ pci_read_byte(dev, PCI_SEC_LATENCY_TIMER));
+
+ /* PCI Base Addresses */
+ /* Count them */
+ count = 0;
+ for (i = 0; i < 6; i++) {
+ if (dev->base_addr[i]) {
+ count++;
+ }
+ }
+ /* Set PCI Base Addresses */
+ if (count > 0) {
+#ifdef PCI_HAVE_64BIT_ADDRESS
+ LMI_PCIBridge_Init_BaseAddress64(&lmi_dev, count);
+#else
+ LMI_PCIBridge_Init_BaseAddress(&lmi_dev, count);
+#endif
+ count = 0;
+ for (i = 0; i < 6; i++) {
+ if (dev->base_addr[i]) {
+#ifdef PCI_HAVE_64BIT_ADDRESS
+ LMI_PCIBridge_Set_BaseAddress64(&lmi_dev, count++,
+ dev->base_addr[i]);
+#else
+ LMI_PCIBridge_Set_BaseAddress(&lmi_dev, count++,
+ dev->base_addr[i]);
+#endif
+ }
+ }
+ }
+
+ /* PCI Capabilities */
+ /* Count PCI Capabilities */
+ count = 0;
+ if (status & PCI_STATUS_66MHZ) {
+ count++;
+ }
+ if (status & PCI_STATUS_UDF) {
+ count++;
+ }
+ if (status & PCI_STATUS_FAST_BACK) {
+ count++;
+ }
+ for (cap = dev->first_cap; cap; cap = cap->next) {
+ pci_cap = get_capability(cap->id);
+ if (pci_cap > 1) {
+ count++;
+ }
+ }
+ /* Get PCI Capabilities */
+ if (count > 0) {
+ LMI_PCIBridge_Init_Capabilities(&lmi_dev, count);
+ count = 0;
+ if (status & PCI_STATUS_66MHZ) {
+ LMI_PCIBridge_Set_Capabilities(&lmi_dev, count++,
+ LMI_PCIBridge_Capabilities_Supports_66MHz);
+ }
+ if (status & PCI_STATUS_UDF) {
+ LMI_PCIBridge_Set_Capabilities(&lmi_dev, count++,
+ LMI_PCIBridge_Capabilities_Supports_User_Definable_Features);
+ }
+ if (status & PCI_STATUS_FAST_BACK) {
+ LMI_PCIBridge_Set_Capabilities(&lmi_dev, count++,
+ LMI_PCIBridge_Capabilities_Supports_Fast_Back_to_Back_Transactions);
+ }
+ for (cap = dev->first_cap; cap; cap = cap->next) {
+ pci_cap = get_capability(cap->id);
+ if (pci_cap > 1) {
+ LMI_PCIBridge_Set_Capabilities(&lmi_dev, count++, pci_cap);
+ }
+ }
+ }
+
+ /* IO base and limit addresses */
+ if (io_type == (io_limit & PCI_IO_RANGE_TYPE_MASK)
+ && (io_type == PCI_IO_RANGE_TYPE_16 || io_type == PCI_IO_RANGE_TYPE_32)) {
+ io_base = (io_base & PCI_IO_RANGE_MASK) << 8;
+ io_limit = (io_limit & PCI_IO_RANGE_MASK) << 8;
+ if (io_type == PCI_IO_RANGE_TYPE_32) {
+ io_base |= (pci_read_word(dev, PCI_IO_BASE_UPPER16) << 16);
+ io_limit |= (pci_read_word(dev, PCI_IO_LIMIT_UPPER16) << 16);
+ if (io_base <= io_limit && io_base > 0 && io_limit > 0) {
+ LMI_PCIBridge_Set_IOBaseUpper16(&lmi_dev, io_base >> 16);
+ LMI_PCIBridge_Set_IOLimitUpper16(&lmi_dev, io_limit >> 16);
+ }
+ } else if (io_base <= io_limit && io_base > 0 && io_limit > 0) {
+ LMI_PCIBridge_Set_IOBase(&lmi_dev, io_base >> 12);
+ LMI_PCIBridge_Set_IOLimit(&lmi_dev, io_limit >> 12);
+ }
+ }
+
+ /* Memory base and limit addresses behind the bridge */
+ if (mem_type == (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) && !mem_type) {
+ mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16;
+ mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16;
+ if (mem_base <= mem_limit && mem_base > 0 && mem_limit > 0) {
+ LMI_PCIBridge_Set_MemoryBase(&lmi_dev, mem_base >> 20);
+ LMI_PCIBridge_Set_MemoryLimit(&lmi_dev, mem_limit >> 20);
+ }
+ }
+
+ /* Prefetchable memory base and limit addresses behind the bridge */
+ if (pref_type == (pref_limit & PCI_PREF_RANGE_TYPE_MASK)
+ && (pref_type == PCI_PREF_RANGE_TYPE_32 || pref_type == PCI_PREF_RANGE_TYPE_64)) {
+ if (pref_type == PCI_PREF_RANGE_TYPE_64) {
+ pref_base_upper = pci_read_long(dev, PCI_PREF_BASE_UPPER32);
+ pref_limit_upper = pci_read_long(dev, PCI_PREF_LIMIT_UPPER32);
+ if (pref_base_upper <= pref_limit_upper
+ && pref_base_upper > 0 && pref_limit_upper > 0) {
+ LMI_PCIBridge_Set_PrefetchBaseUpper32(&lmi_dev, pref_base_upper);
+ LMI_PCIBridge_Set_PrefetchLimitUpper32(&lmi_dev, pref_limit_upper);
+ }
+ }
+ if ((pref_type == PCI_PREF_RANGE_TYPE_64 && pref_base_upper == 0 && pref_limit_upper == 0)
+ || pref_type == PCI_PREF_RANGE_TYPE_32) {
+ pref_base = (pref_base & PCI_PREF_RANGE_MASK) << 16;
+ pref_limit = (pref_limit & PCI_PREF_RANGE_MASK) << 16;
+ if (pref_base <= pref_limit && pref_base > 0 && pref_limit > 0) {
+ LMI_PCIBridge_Set_PrefetchMemoryBase(&lmi_dev, pref_base >> 20);
+ LMI_PCIBridge_Set_PrefetchMemoryLimit(&lmi_dev, pref_limit >> 20);
+ }
+ }
+ }
+
+ KReturnInstance(cr, lmi_dev);
+ }
+
+ pci_cleanup(acc);
+
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeGetInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ return KDefaultGetInstance(
+ _cb, mi, cc, cr, cop, properties);
+}
+
+static CMPIStatus LMI_PCIBridgeCreateInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeModifyInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci,
+ const char** properties)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeDeleteInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeExecQuery(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* lang,
+ const char* query)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+CMInstanceMIStub(
+ LMI_PCIBridge,
+ LMI_PCIBridge,
+ _cb,
+ LMI_PCIBridgeInitialize())
+
+static CMPIStatus LMI_PCIBridgeMethodCleanup(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeInvokeMethod(
+ CMPIMethodMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* meth,
+ const CMPIArgs* in,
+ CMPIArgs* out)
+{
+ return LMI_PCIBridge_DispatchMethod(
+ _cb, mi, cc, cr, cop, meth, in, out);
+}
+
+CMMethodMIStub(
+ LMI_PCIBridge,
+ LMI_PCIBridge,
+ _cb,
+ LMI_PCIBridgeInitialize())
+
+KUint32 LMI_PCIBridge_RequestStateChange(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ const KUint16* RequestedState,
+ KRef* Job,
+ const KDateTime* TimeoutPeriod,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_SetPowerState(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ const KUint16* PowerState,
+ const KDateTime* Time,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_Reset(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_EnableDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ const KBoolean* Enabled,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_OnlineDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ const KBoolean* Online,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_QuiesceDevice(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ const KBoolean* Quiesce,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_SaveProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint32 LMI_PCIBridge_RestoreProperties(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ CMPIStatus* status)
+{
+ KUint32 result = KUINT32_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+KUint8 LMI_PCIBridge_BISTExecution(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_PCIBridgeRef* self,
+ CMPIStatus* status)
+{
+ KUint8 result = KUINT8_INIT;
+
+ KSetStatus(status, ERR_NOT_SUPPORTED);
+ return result;
+}
+
+CMPIUint16 get_bridge_type(const char *bridge_type)
+{
+ static struct {
+ CMPIUint16 cim_val; /* CIM value */
+ char *bridge_type; /* bridge type */
+ } values[] = {
+ {0, "Host bridge"},
+ {1, "ISA bridge"},
+ {2, "EISA bridge"},
+ {3, "MicroChannel bridge"},
+ {4, "PCI bridge"},
+ {5, "PCMCIA bridge"},
+ {6, "NuBus bridge"},
+ {7, "CardBus bridge"},
+ {8, "RACEway bridge"},
+ /*
+ {9, "AGP"},
+ {10, "PCIe"},
+ {11, "PCIe-to-PCI"},
+ */
+ {128, "Other"},
+ };
+
+ size_t i, val_length = sizeof(values) / sizeof(values[0]);
+
+ for (i = 0; i < val_length; i++) {
+ if (strcmp(bridge_type, values[i].bridge_type) == 0) {
+ return values[i].cim_val;
+ }
+ }
+
+ return 128; /* Other */
+}
+
+KONKRET_REGISTRATION(
+ "root/cimv2",
+ "LMI_PCIBridge",
+ "LMI_PCIBridge",
+ "instance method")
diff --git a/src/hardware/LMI_PCIBridgeSystemDeviceProvider.c b/src/hardware/LMI_PCIBridgeSystemDeviceProvider.c
new file mode 100644
index 0000000..2151dd5
--- /dev/null
+++ b/src/hardware/LMI_PCIBridgeSystemDeviceProvider.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include <konkret/konkret.h>
+#include "LMI_PCIBridgeSystemDevice.h"
+#include "LMI_Hardware.h"
+#include "PCIDev.h"
+#include "globals.h"
+
+static const CMPIBroker* _cb;
+
+static void LMI_PCIBridgeSystemDeviceInitialize()
+{
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceCleanup(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceEnumInstanceNames(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ return KDefaultEnumerateInstanceNames(
+ _cb, mi, cc, cr, cop);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceEnumInstances(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ LMI_PCIBridgeSystemDevice lmi_pci_sys_device;
+ CIM_ComputerSystemRef cim_cs;
+ LMI_PCIBridgeRef lmi_dev;
+ CMPIObjectPath *o;
+ CMPIStatus st;
+ const char *ns = KNameSpace(cop);
+ struct pci_access *acc;
+ struct pci_dev *dev;
+ char device_id_str[PCI_DEVID_STR_SIZE];
+
+ CIM_ComputerSystemRef_Init(&cim_cs, _cb, ns);
+ CIM_ComputerSystemRef_Set_Name(&cim_cs, get_system_name());
+ CIM_ComputerSystemRef_Set_CreationClassName(&cim_cs,
+ get_system_creation_class_name());
+ o = CIM_ComputerSystemRef_ToObjectPath(&cim_cs, &st);
+ CMSetClassName(o, get_system_creation_class_name());
+
+ if (!(acc = pci_alloc())) {
+ KReturn2(_cb, ERR_FAILED, "Can't access the PCI bus.");
+ }
+ pci_init(acc);
+ pci_scan_bus(acc);
+
+ for (dev = acc->devices; dev; dev = dev->next) {
+ pci_fill_info(dev, PCI_FILL_CLASS);
+
+ /* Use only PCI Bridges */
+ /* Throw away the lower 8 bits denoting the subclass */
+ if (((dev->device_class) >> 8) != LMI_PCIBridge_ClassCode_Bridge) {
+ continue;
+ }
+
+ LMI_PCIBridgeSystemDevice_Init(&lmi_pci_sys_device, _cb, ns);
+
+ snprintf(device_id_str, PCI_DEVID_STR_SIZE, "%02x:%02x.%u",
+ dev->bus, dev->dev, dev->func);
+
+ LMI_PCIBridgeRef_Init(&lmi_dev, _cb, ns);
+ LMI_PCIBridgeRef_Set_SystemCreationClassName(&lmi_dev,
+ get_system_creation_class_name());
+ LMI_PCIBridgeRef_Set_SystemName(&lmi_dev, get_system_name());
+ LMI_PCIBridgeRef_Set_CreationClassName(&lmi_dev,
+ ORGID "_" PCI_BRIDGE_CLASS_NAME);
+ LMI_PCIBridgeRef_Set_DeviceID(&lmi_dev, device_id_str);
+
+ LMI_PCIBridgeSystemDevice_SetObjectPath_GroupComponent(
+ &lmi_pci_sys_device, o);
+ LMI_PCIBridgeSystemDevice_Set_PartComponent(&lmi_pci_sys_device,
+ &lmi_dev);
+
+ KReturnInstance(cr, lmi_pci_sys_device);
+ }
+
+ pci_cleanup(acc);
+
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceGetInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char** properties)
+{
+ return KDefaultGetInstance(
+ _cb, mi, cc, cr, cop, properties);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceCreateInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceModifyInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const CMPIInstance* ci,
+ const char**properties)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceDeleteInstance(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceExecQuery(
+ CMPIInstanceMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* lang,
+ const char* query)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceAssociationCleanup(
+ CMPIAssociationMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceAssociators(
+ CMPIAssociationMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* assocClass,
+ const char* resultClass,
+ const char* role,
+ const char* resultRole,
+ const char** properties)
+{
+ return KDefaultAssociators(
+ _cb,
+ mi,
+ cc,
+ cr,
+ cop,
+ LMI_PCIBridgeSystemDevice_ClassName,
+ assocClass,
+ resultClass,
+ role,
+ resultRole,
+ properties);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceAssociatorNames(
+ CMPIAssociationMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* assocClass,
+ const char* resultClass,
+ const char* role,
+ const char* resultRole)
+{
+ return KDefaultAssociatorNames(
+ _cb,
+ mi,
+ cc,
+ cr,
+ cop,
+ LMI_PCIBridgeSystemDevice_ClassName,
+ assocClass,
+ resultClass,
+ role,
+ resultRole);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceReferences(
+ CMPIAssociationMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* assocClass,
+ const char* role,
+ const char** properties)
+{
+ return KDefaultReferences(
+ _cb,
+ mi,
+ cc,
+ cr,
+ cop,
+ LMI_PCIBridgeSystemDevice_ClassName,
+ assocClass,
+ role,
+ properties);
+}
+
+static CMPIStatus LMI_PCIBridgeSystemDeviceReferenceNames(
+ CMPIAssociationMI* mi,
+ const CMPIContext* cc,
+ const CMPIResult* cr,
+ const CMPIObjectPath* cop,
+ const char* assocClass,
+ const char* role)
+{
+ return KDefaultReferenceNames(
+ _cb,
+ mi,
+ cc,
+ cr,
+ cop,
+ LMI_PCIBridgeSystemDevice_ClassName,
+ assocClass,
+ role);
+}
+
+CMInstanceMIStub(
+ LMI_PCIBridgeSystemDevice,
+ LMI_PCIBridgeSystemDevice,
+ _cb,
+ LMI_PCIBridgeSystemDeviceInitialize())
+
+CMAssociationMIStub(
+ LMI_PCIBridgeSystemDevice,
+ LMI_PCIBridgeSystemDevice,
+ _cb,
+ LMI_PCIBridgeSystemDeviceInitialize())
+
+KONKRET_REGISTRATION(
+ "root/cimv2",
+ "LMI_PCIBridgeSystemDevice",
+ "LMI_PCIBridgeSystemDevice",
+ "instance association")
diff --git a/src/hardware/LMI_PCIDeviceProvider.c b/src/hardware/LMI_PCIDeviceProvider.c
index a88f9cd..cc6adc8 100644
--- a/src/hardware/LMI_PCIDeviceProvider.c
+++ b/src/hardware/LMI_PCIDeviceProvider.c
@@ -20,16 +20,11 @@
*/
#include <konkret/konkret.h>
-#include <pci/pci.h>
#include "LMI_PCIDevice.h"
#include "LMI_Hardware.h"
+#include "PCIDev.h"
#include "globals.h"
-#define NAME_BUF_SIZE 128
-
-void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp);
-CMPIUint16 get_capability(const u16 pci_cap);
-
static const CMPIBroker* _cb = NULL;
static void LMI_PCIDeviceInitialize()
@@ -78,7 +73,7 @@ static CMPIStatus LMI_PCIDeviceEnumInstances(
char instance_id[INSTANCE_ID_LEN];
if (!(acc = pci_alloc())) {
- KReturn2(_cb, ERR_FAILED, "Can't access the PCI bus.");
+ KReturn2(_cb, ERR_FAILED, "Cannot access the PCI bus.");
}
pci_init(acc);
pci_scan_bus(acc);
@@ -92,6 +87,12 @@ static CMPIStatus LMI_PCIDeviceEnumInstances(
| PCI_FILL_CLASS
| PCI_FILL_CAPS);
+ /* Ignore PCI Bridges */
+ /* Throw away the lower 8 bits denoting the subclass */
+ if (((dev->device_class) >> 8) == LMI_PCIDevice_ClassCode_Bridge) {
+ continue;
+ }
+
vendor_name = pci_lookup_name(acc, vendor_buf, NAME_BUF_SIZE,
PCI_LOOKUP_VENDOR, dev->vendor_id);
device_name = pci_lookup_name(acc, device_buf, NAME_BUF_SIZE,
@@ -166,15 +167,17 @@ static CMPIStatus LMI_PCIDeviceEnumInstances(
/* Throw away the lower 8 bits denoting the subclass */
LMI_PCIDevice_Set_ClassCode(&lmi_dev, ((dev->device_class) >> 8));
- if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) {
- LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
- LMI_PCIDevice_DeviceSelectTiming_Slow);
- } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) {
- LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
- LMI_PCIDevice_DeviceSelectTiming_Medium);
- } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) {
- LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
- LMI_PCIDevice_DeviceSelectTiming_Fast);
+ if (status) {
+ if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) {
+ LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIDevice_DeviceSelectTiming_Slow);
+ } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) {
+ LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIDevice_DeviceSelectTiming_Medium);
+ } else if ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) {
+ LMI_PCIDevice_Set_DeviceSelectTiming(&lmi_dev,
+ LMI_PCIDevice_DeviceSelectTiming_Fast);
+ }
}
if (dev->rom_base_addr) {
@@ -477,67 +480,6 @@ KUint8 LMI_PCIDevice_BISTExecution(
return result;
}
-void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp)
-{
- u8 htype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
-
- if (htype == PCI_HEADER_TYPE_NORMAL) {
- *subvp = pci_read_word(d, PCI_SUBSYSTEM_VENDOR_ID);
- *subdp = pci_read_word(d, PCI_SUBSYSTEM_ID);
- } else if (htype == PCI_HEADER_TYPE_CARDBUS) {
- *subvp = pci_read_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
- *subdp = pci_read_word(d, PCI_CB_SUBSYSTEM_ID);
- } else {
- *subvp = *subdp = 0xffff;
- }
-}
-
-/*
- * Get pci capability according to the pci lib.
- * @param pci_cap from pci lib
- * @return CIM id of pci capability
- */
-CMPIUint16 get_capability(const u16 pci_cap)
-{
- static struct {
- CMPIUint16 cim_val; /* CIM value */
- u16 pci_cap; /* pci value */
- } values[] = {
- /*
- {0, "Unknown"},
- {1, "Other"},
- {2, "Supports 66MHz"},
- {3, "Supports User Definable Features"},
- {4, "Supports Fast Back-to-Back Transactions"},
- */
- {5, PCI_CAP_ID_PCIX},
- {6, PCI_CAP_ID_PM},
- {7, PCI_CAP_ID_MSI},
- /*
- {8, "Parity Error Recovery Capable"},
- */
- {9, PCI_CAP_ID_AGP},
- {10, PCI_CAP_ID_VPD},
- {11, PCI_CAP_ID_SLOTID},
- {12, PCI_CAP_ID_HOTPLUG},
- {13, PCI_CAP_ID_EXP},
- /*
- {14, "Supports PCIe Gen 2"},
- {15, "Supports PCIe Gen 3"},
- */
- };
-
- size_t i, val_length = sizeof(values) / sizeof(values[0]);
-
- for (i = 0; i < val_length; i++) {
- if (pci_cap == values[i].pci_cap) {
- return values[i].cim_val;
- }
- }
-
- return 1; /* Other */
-}
-
KONKRET_REGISTRATION(
"root/cimv2",
"LMI_PCIDevice",
diff --git a/src/hardware/LMI_PCIDeviceSystemDeviceProvider.c b/src/hardware/LMI_PCIDeviceSystemDeviceProvider.c
index e473ddf..897f7bc 100644
--- a/src/hardware/LMI_PCIDeviceSystemDeviceProvider.c
+++ b/src/hardware/LMI_PCIDeviceSystemDeviceProvider.c
@@ -19,9 +19,9 @@
*/
#include <konkret/konkret.h>
-#include <pci/pci.h>
#include "LMI_PCIDeviceSystemDevice.h"
#include "LMI_Hardware.h"
+#include "PCIDev.h"
#include "globals.h"
static const CMPIBroker* _cb;
@@ -79,6 +79,14 @@ static CMPIStatus LMI_PCIDeviceSystemDeviceEnumInstances(
pci_scan_bus(acc);
for (dev = acc->devices; dev; dev = dev->next) {
+ pci_fill_info(dev, PCI_FILL_CLASS);
+
+ /* Ignore PCI Bridges */
+ /* Throw away the lower 8 bits denoting the subclass */
+ if (((dev->device_class) >> 8) == LMI_PCIDevice_ClassCode_Bridge) {
+ continue;
+ }
+
LMI_PCIDeviceSystemDevice_Init(&lmi_pci_sys_device, _cb, ns);
snprintf(device_id_str, PCI_DEVID_STR_SIZE, "%02x:%02x.%u",
diff --git a/src/hardware/PCIDev.c b/src/hardware/PCIDev.c
new file mode 100644
index 0000000..40051b3
--- /dev/null
+++ b/src/hardware/PCIDev.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#include "PCIDev.h"
+
+void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp)
+{
+ u8 htype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
+
+ if (htype == PCI_HEADER_TYPE_NORMAL) {
+ *subvp = pci_read_word(d, PCI_SUBSYSTEM_VENDOR_ID);
+ *subdp = pci_read_word(d, PCI_SUBSYSTEM_ID);
+ } else if (htype == PCI_HEADER_TYPE_CARDBUS) {
+ *subvp = pci_read_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
+ *subdp = pci_read_word(d, PCI_CB_SUBSYSTEM_ID);
+ } else {
+ *subvp = *subdp = 0xffff;
+ }
+}
+
+unsigned short get_capability(const u16 pci_cap)
+{
+ static struct {
+ unsigned short cim_val; /* CIM value */
+ u16 pci_cap; /* pci value */
+ } values[] = {
+ /*
+ {0, "Unknown"},
+ {1, "Other"},
+ {2, "Supports 66MHz"},
+ {3, "Supports User Definable Features"},
+ {4, "Supports Fast Back-to-Back Transactions"},
+ */
+ {5, PCI_CAP_ID_PCIX},
+ {6, PCI_CAP_ID_PM},
+ {7, PCI_CAP_ID_MSI},
+ /*
+ {8, "Parity Error Recovery Capable"},
+ */
+ {9, PCI_CAP_ID_AGP},
+ {10, PCI_CAP_ID_VPD},
+ {11, PCI_CAP_ID_SLOTID},
+ {12, PCI_CAP_ID_HOTPLUG},
+ {13, PCI_CAP_ID_EXP},
+ /*
+ {14, "Supports PCIe Gen 2"},
+ {15, "Supports PCIe Gen 3"},
+ */
+ };
+
+ size_t i, val_length = sizeof(values) / sizeof(values[0]);
+
+ for (i = 0; i < val_length; i++) {
+ if (pci_cap == values[i].pci_cap) {
+ return values[i].cim_val;
+ }
+ }
+
+ return 1; /* Other */
+}
diff --git a/src/hardware/PCIDev.h b/src/hardware/PCIDev.h
new file mode 100644
index 0000000..7e4cf0d
--- /dev/null
+++ b/src/hardware/PCIDev.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Peter Schiffer <pschiffe@redhat.com>
+ */
+
+#ifndef PCIDEV_H_
+#define PCIDEV_H_
+
+#include <pci/pci.h>
+
+#define PCI_DEVID_STR_SIZE 55
+#define NAME_BUF_SIZE 128
+
+/*
+ * Get subsystem IDs of pci device.
+ * @param d pci device
+ * @param subvp subsystem vendor id
+ * @param subdp subsystem id
+ */
+void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp);
+
+/*
+ * Get pci capability according to the pci lib.
+ * @param pci_cap from pci lib
+ * @return CIM id of pci capability
+ */
+unsigned short get_capability(const u16 pci_cap);
+
+#endif /* PCIDEV_H_ */