diff options
Diffstat (limited to 'src/hardware')
-rw-r--r-- | src/hardware/90_LMI_Hardware_Profile_DMTF.mof | 26 | ||||
-rw-r--r-- | src/hardware/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/hardware/LMI_Hardware.h | 4 | ||||
-rw-r--r-- | src/hardware/LMI_PCIBridgeProvider.c | 620 | ||||
-rw-r--r-- | src/hardware/LMI_PCIBridgeSystemDeviceProvider.c | 280 | ||||
-rw-r--r-- | src/hardware/LMI_PCIDeviceProvider.c | 96 | ||||
-rw-r--r-- | src/hardware/LMI_PCIDeviceSystemDeviceProvider.c | 10 | ||||
-rw-r--r-- | src/hardware/PCIDev.c | 77 | ||||
-rw-r--r-- | src/hardware/PCIDev.h | 44 |
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_ */ |