summaryrefslogtreecommitdiffstats
path: root/src/hardware/LMI_PCIDeviceProvider.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hardware/LMI_PCIDeviceProvider.c')
-rw-r--r--src/hardware/LMI_PCIDeviceProvider.c259
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",