diff options
Diffstat (limited to 'src/hardware/LMI_PCIDeviceProvider.c')
-rw-r--r-- | src/hardware/LMI_PCIDeviceProvider.c | 259 |
1 files changed, 217 insertions, 42 deletions
diff --git a/src/hardware/LMI_PCIDeviceProvider.c b/src/hardware/LMI_PCIDeviceProvider.c index e879484..2daf0a6 100644 --- a/src/hardware/LMI_PCIDeviceProvider.c +++ b/src/hardware/LMI_PCIDeviceProvider.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Red Hat, Inc. All rights reserved. + * 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 @@ -16,29 +16,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Tomas Smetana <tsmetana@redhat.com> - * + * Peter Schiffer <pschiffe@redhat.com> */ + #include <konkret/konkret.h> #include <pci/pci.h> - -#include "globals.h" #include "LMI_PCIDevice.h" +#include "LMI_Hardware.h" +#include "globals.h" -static const CMPIBroker* _cb = NULL; +#define NAME_BUF_SIZE 128 +#define PCI_DEVID_STR_SIZE 55 -static void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp) -{ - u8 htype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f; +void get_subid(struct pci_dev *d, u16 *subvp, u16 *subdp); +CMPIUint16 get_capability(const u16 pci_cap); - 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; -} +static const CMPIBroker* _cb = NULL; static void LMI_PCIDeviceInitialize() { @@ -61,8 +54,6 @@ static CMPIStatus LMI_PCIDeviceEnumInstanceNames( return KDefaultEnumerateInstanceNames(_cb, mi, cc, cr, cop); } -#define NAME_BUF_SIZE 128 -#define PCI_DEVID_STR_SIZE 9 static CMPIStatus LMI_PCIDeviceEnumInstances( CMPIInstanceMI* mi, const CMPIContext* cc, @@ -70,21 +61,26 @@ static CMPIStatus LMI_PCIDeviceEnumInstances( const CMPIObjectPath* cop, const char** properties) { + LMI_PCIDevice lmi_dev; + const char *ns = KNameSpace(cop); + int i; + CMPICount count; + CMPIUint16 pci_cap; + u8 rev, cache_line; + u16 svid, subid, status, command_reg; struct pci_access *acc; struct pci_dev *dev; struct pci_cap *cap; - int i; - u16 subid, svid; 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 device_id_str[PCI_DEVID_STR_SIZE]; - LMI_PCIDevice lmi_dev; - const char *ns = KNameSpace(cop); + char instance_id[INSTANCE_ID_LEN]; - if (!(acc = pci_alloc())) - KReturn2(_cb, ERR_FAILED, "Error accessing the PCI bus"); + if (!(acc = pci_alloc())) { + KReturn2(_cb, ERR_FAILED, "Can't access the PCI bus."); + } pci_init(acc); pci_scan_bus(acc); @@ -107,45 +103,163 @@ static CMPIStatus LMI_PCIDeviceEnumInstances( 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); + 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); + + 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_DEVICE_CLASS_NAME ":%s", device_id_str); LMI_PCIDevice_Init(&lmi_dev, _cb, ns); - LMI_PCIDevice_Set_CreationClassName(&lmi_dev, "LMI_PCIDevice"); + LMI_PCIDevice_Set_SystemCreationClassName(&lmi_dev, get_system_creation_class_name()); LMI_PCIDevice_Set_SystemName(&lmi_dev, get_system_name()); - snprintf((char *)&device_id_str, PCI_DEVID_STR_SIZE, "%d:%d.%d", - dev->bus, dev->dev, dev->func); + LMI_PCIDevice_Set_CreationClassName(&lmi_dev, + ORGID "_" PCI_DEVICE_CLASS_NAME); + LMI_PCIDevice_Set_Caption(&lmi_dev, + "This object represents one logical PCI device contained in system."); + + LMI_PCIDevice_Set_PrimaryStatus(&lmi_dev, + LMI_PCIDevice_PrimaryStatus_Unknown); + LMI_PCIDevice_Set_HealthState(&lmi_dev, + LMI_PCIDevice_HealthState_Unknown); + LMI_PCIDevice_Set_DeviceID(&lmi_dev, device_id_str); LMI_PCIDevice_Set_BusNumber(&lmi_dev, dev->bus); LMI_PCIDevice_Set_DeviceNumber(&lmi_dev, dev->dev); LMI_PCIDevice_Set_FunctionNumber(&lmi_dev, dev->func); + LMI_PCIDevice_Set_Name(&lmi_dev, device_name); + LMI_PCIDevice_Set_ElementName(&lmi_dev, device_name); + LMI_PCIDevice_Set_VendorID(&lmi_dev, dev->vendor_id); LMI_PCIDevice_Set_PCIDeviceID(&lmi_dev, dev->device_id); LMI_PCIDevice_Set_PCIDeviceName(&lmi_dev, device_name); - LMI_PCIDevice_Set_SubsystemID(&lmi_dev, subid); - LMI_PCIDevice_Set_SubsystemVendorID(&lmi_dev, svid); + if (vendor_name) { + LMI_PCIDevice_Set_VendorName(&lmi_dev, vendor_name); + } + if (svid > 0 && svid < 65535) { + LMI_PCIDevice_Set_SubsystemVendorID(&lmi_dev, svid); + if (svendor_name) { + LMI_PCIDevice_Set_SubsystemVendorName(&lmi_dev, svendor_name); + } + } + if (subid > 0 && subid < 65535) { + LMI_PCIDevice_Set_SubsystemID(&lmi_dev, subid); + if (subsys_name) { + LMI_PCIDevice_Set_SubsystemName(&lmi_dev, subsys_name); + } + } + + if (rev) { + LMI_PCIDevice_Set_RevisionID(&lmi_dev, rev); + } + if (cache_line) { + LMI_PCIDevice_Set_CacheLineSize(&lmi_dev, cache_line); + } + if (command_reg) { + LMI_PCIDevice_Set_CommandRegister(&lmi_dev, command_reg); + } + /* Throw away the lower 8 bits denoting the subclass */ LMI_PCIDevice_Set_ClassCode(&lmi_dev, ((dev->device_class) >> 8)); - if (dev->rom_base_addr) + + 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) { LMI_PCIDevice_Set_ExpansionROMBaseAddress(&lmi_dev, dev->rom_base_addr); - if (vendor_name) - LMI_PCIDevice_Set_VendorName(&lmi_dev, vendor_name); - if (subsys_name) - LMI_PCIDevice_Set_SubsystemName(&lmi_dev, subsys_name); - if (svendor_name) - LMI_PCIDevice_Set_SubsystemVendorName(&lmi_dev, svendor_name); - for (i = 0; i < 6; i++) + } + + LMI_PCIDevice_Set_InstanceID(&lmi_dev, instance_id); + LMI_PCIDevice_Set_InterruptPin(&lmi_dev, + pci_read_byte(dev, PCI_INTERRUPT_PIN)); + LMI_PCIDevice_Set_LatencyTimer(&lmi_dev, + pci_read_byte(dev, PCI_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_PCIDevice_Init_BaseAddress64(&lmi_dev, count); +#else + LMI_PCIDevice_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_PCIDevice_Set_BaseAddress64(&lmi_dev, i, dev->base_addr[i]); + LMI_PCIDevice_Set_BaseAddress64(&lmi_dev, count++, + dev->base_addr[i]); #else - LMI_PCIDevice_Set_BaseAddress(&lmi_dev, i, dev->base_addr[i]); + LMI_PCIDevice_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_PCIDevice_Init_Capabilities(&lmi_dev, count); + count = 0; + if (status & PCI_STATUS_66MHZ) { + LMI_PCIDevice_Set_Capabilities(&lmi_dev, count++, + LMI_PCIDevice_Capabilities_Supports_66MHz); + } + if (status & PCI_STATUS_UDF) { + LMI_PCIDevice_Set_Capabilities(&lmi_dev, count++, + LMI_PCIDevice_Capabilities_Supports_User_Definable_Features); + } + if (status & PCI_STATUS_FAST_BACK) { + LMI_PCIDevice_Set_Capabilities(&lmi_dev, count++, + LMI_PCIDevice_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_PCIDevice_Set_Capabilities(&lmi_dev, count++, pci_cap); + } } - for (cap = dev->first_cap, i = 0; cap; cap = cap->next, i++) { - LMI_PCIDevice_Set_Capabilities(&lmi_dev, i, cap->type); } + KReturnInstance(cr, lmi_dev); } @@ -364,6 +478,67 @@ 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", |