mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 19:02:51 +00:00
807 lines
56 KiB
C++
807 lines
56 KiB
C++
/* Retrieve information about PCI subsystem through libpci library from
|
|
pciutils package. This should be possible on Linux, BSD and AIX.
|
|
|
|
This code is based on example.c, lspci.c and pci.ids from pciutils.
|
|
|
|
Device classes, subclasses and programming interfaces are hardcoded
|
|
here, since there are only few of them, and they are important and
|
|
should their names be translated.
|
|
|
|
Author: Konrad Rzepecki <hannibal@megapolis.pl>
|
|
*/
|
|
#include "kpci_private.h"
|
|
|
|
//extern "C" is needed to proper linking with libpci
|
|
extern "C" {
|
|
#include <pci/pci.h>
|
|
}
|
|
#include <unistd.h>
|
|
#include <sys/types.h> //getuid
|
|
#include <ctype.h> //isxdigit
|
|
#include <string.h> //memcpy
|
|
#include <QTreeWidget>
|
|
#include <QtGui/qtreewidget.h>
|
|
#include <QFile>
|
|
|
|
static const QString& getNameById(const id2name *const table, int id) {
|
|
for (int i=0;; i++) {
|
|
if ((table[i].id==id)||(table[i].id==-1)) {
|
|
return table[i].name;
|
|
}//if
|
|
}//while
|
|
}//getNameById
|
|
|
|
static const QString& getNameBy2Id(const id3name *const table, int id, int id2) {
|
|
for (int i=0;; i++) {
|
|
if (((table[i].id==id)&&(table[i].id2==id2))|| ((table[i].id==id)&&(table[i].id2==-1))|| (table[i].id==-1)) {
|
|
return table[i].name;
|
|
}//if
|
|
}//while
|
|
}//getNameBy2Id
|
|
|
|
static const QString& getNameBy3Id(const id4name *const table, int id, int id2, int id3) {
|
|
for (int i=0;; i++) {
|
|
if (((table[i].id==id)&&(table[i].id2==id2)&&(table[i].id3==id3))|| ((table[i].id==id)&&(table[i].id2==id2)&&(table[i].id3==-1))|| ((table[i].id==id)&&(table[i].id2==-1))|| (table[i].id==-1)) {
|
|
return table[i].name;
|
|
}//if
|
|
}//while
|
|
}//getNameBy3Id
|
|
|
|
static QTreeWidgetItem* create(QTreeWidgetItem* parent, const QString& title, const QString& value) {
|
|
QStringList list;
|
|
list << title << value;
|
|
return new QTreeWidgetItem(parent, list);
|
|
}
|
|
|
|
static QTreeWidgetItem* createTitle(QTreeWidgetItem* parent, const QString& title) {
|
|
QStringList list;
|
|
list << title;
|
|
return new QTreeWidgetItem(parent, list);
|
|
}
|
|
|
|
static QTreeWidgetItem* addDeviceClass(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QString value;
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
after=create(parent, i18n("Device Class"), getNameById(devClass, info->cooked.devClass)+value.sprintf(" (0x%02X)", info->cooked.devClass));
|
|
after=create(parent, i18n("Device Subclass"), getNameBy2Id(devSubclass, info->cooked.devClass, info->cooked.devSubClass)+value.sprintf(" (0x%02X)", info->cooked.devSubClass));
|
|
after=create(parent, i18n("Device Programming Interface"), getNameBy3Id(devInterface, info->cooked.devClass, info->cooked.devSubClass, info->cooked.devProgIface.devProgIface)+value.sprintf(" (0x%02X)", info->cooked.devProgIface.devProgIface));
|
|
if ((info->cooked.devClass==0x01)&&(info->cooked.devSubClass==0x01)) { //programming interface for IDE
|
|
localAfter=create(after, i18n("Master IDE Device"), (info->cooked.devProgIface.devProgIface_bits.progIdeMaster ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Secondary programmable indicator"), (info->cooked.devProgIface.devProgIface_bits.progSecProgInd ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Secondary operating mode"), (info->cooked.devProgIface.devProgIface_bits.progSecOperMode ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Primary programmable indicator"), (info->cooked.devProgIface.devProgIface_bits.progPriProgInd ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Primary operating mode"), (info->cooked.devProgIface.devProgIface_bits.progPriOperMode ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
}//if
|
|
return after;
|
|
}//addDeviceClass
|
|
|
|
static QTreeWidgetItem* addVendor(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, pci_access *PCIAccess) {
|
|
char nameBuffer[NAME_BUFFER_SIZE];
|
|
QString line, value, topname;
|
|
short int subvendor=0, subdevice=0;
|
|
bool isVendor=false, isDevice=false, isSub=false;
|
|
|
|
memset((void*)nameBuffer, 0, NAME_BUFFER_SIZE);
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS) {
|
|
subvendor=info->cooked.header.header2.cbSubVendor;
|
|
subdevice=info->cooked.header.header2.cbSubDevice;
|
|
}//if
|
|
else {
|
|
subvendor=info->cooked.header.header0.subVendor;
|
|
subdevice=info->cooked.header.header0.subDevice;
|
|
}//else
|
|
|
|
//WARNING all pci_lookup_name calls should have 4 extra args for compatibility with older pcilib !
|
|
if (pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_VENDOR, info->cooked.vendor, 0, 0, 0)!=NULL) {
|
|
//line.setAscii(nameBuffer); //not work, workaround below
|
|
line = QString::fromAscii(pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_VENDOR, info->cooked.vendor, 0, 0, 0));
|
|
if (line.contains("Unknown")==0) {
|
|
isVendor=true;
|
|
topname=line;
|
|
after=create(parent, i18n("Vendor"), line+value.sprintf(" (0x%04X)", info->cooked.vendor));
|
|
if (pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_DEVICE, info->cooked.vendor, info->cooked.device, 0, 0)!=NULL) {
|
|
// line.setAscii(nameBuffer); //not work, workaround below
|
|
line = QString::fromAscii(pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_DEVICE, info->cooked.vendor, info->cooked.device, 0, 0));
|
|
if (line.contains("Unknown")==0) {
|
|
isDevice=true;
|
|
topname+=QString(" ")+line;
|
|
after=create(parent, i18n("Device"), line+value.sprintf(" (0x%04X)", info->cooked.device));
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE) {
|
|
isSub=true;
|
|
}//if
|
|
else if (pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_DEVICE|PCI_LOOKUP_SUBSYSTEM, info->cooked.vendor, info->cooked.device, subvendor, subdevice)!=NULL) {
|
|
//line.setAscii(nameBuffer); //not work, workaround below
|
|
line = QString::fromAscii(pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_DEVICE|PCI_LOOKUP_SUBSYSTEM, info->cooked.vendor, info->cooked.device, subvendor, subdevice));
|
|
if (line.contains("Unknown")==0) {
|
|
isSub=true;
|
|
after=create(parent, i18n("Subsystem"), line+value.sprintf(" (0x%04X:0x%04X)", subvendor, subdevice));
|
|
}//if
|
|
}//eliif
|
|
}//if
|
|
}//iif
|
|
}//if
|
|
}//if
|
|
if (!isVendor) {
|
|
after=create(parent, i18n("Vendor"), i18nc(strCtxt, strUnknown)+value.sprintf(" (0x%04X)", info->cooked.vendor));
|
|
if (!isDevice) {
|
|
after=create(parent, i18n("Device"), i18nc(strCtxt, strUnknown)+value.sprintf(" (0x%04X)", info->cooked.device));
|
|
}//if
|
|
topname=i18nc(strCtxt, strUnknown);
|
|
}//if
|
|
if ((!isSub)&&(info->cooked.headerType.headerType_bits.headerType!=PCI_HEADER_TYPE_BRIDGE)) { //if entire subsytem was not found, search at least for subvendor
|
|
if (pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_VENDOR, subvendor, 0, 0, 0)!=NULL) {
|
|
//line.setAscii(nameBuffer); //not work, workaround below
|
|
line = QString::fromAscii(pci_lookup_name(PCIAccess, nameBuffer, NAME_BUFFER_SIZE, PCI_LOOKUP_VENDOR, subvendor, 0, 0, 0));
|
|
if (line.contains("Unknown")==0) {
|
|
after=create(parent, i18n("Subsystem"), line+i18n(" - device:")+value.sprintf(" 0x%04X (0x%04X:0x%04X)", subdevice, subvendor, subdevice));
|
|
}//if
|
|
else {
|
|
after=create(parent, i18n("Subsystem"), i18nc(strCtxt, strUnknown)+value.sprintf(" (0x%04X:0x%04X)", subvendor, subdevice));
|
|
}//else
|
|
}//if
|
|
else {
|
|
after=create(parent, i18n("Subsystem"), i18nc(strCtxt, strUnknown)+value.sprintf(" (0x%04X:0x%04X)", subvendor, subdevice));
|
|
}//else
|
|
}//if
|
|
parent->setText(1, topname);
|
|
return after;
|
|
}//addVendor
|
|
|
|
static QTreeWidgetItem* addInterrupt(QTreeWidgetItem *parent, QTreeWidgetItem *after, int irq, int pin) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if ((irq!=0)||(pin!=0)) {
|
|
after=createTitle(parent, i18n("Interrupt"));
|
|
localAfter=create(after, i18n("IRQ"), value.sprintf("%i", irq));
|
|
localAfter=create(after, i18n("Pin"), value.sprintf("%c", (pin==0 ? '?' : 'A'-1+pin)));
|
|
}//if
|
|
return after;
|
|
}//addInterrupt
|
|
|
|
static QTreeWidgetItem* addControl(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
after=create(parent, i18n("Control"), value.sprintf("0x%04X", info->cooked.command.command));
|
|
localAfter=create(after, i18n("Response in I/O space"), (info->cooked.command.command_bits.comIo ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Response in memory space"), (info->cooked.command.command_bits.comMemory ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Bus mastering"), (info->cooked.command.command_bits.comMaster ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Response to special cycles"), (info->cooked.command.command_bits.comSpecial ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Memory write and invalidate"), (info->cooked.command.command_bits.comInvalidate ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Palette snooping"), (info->cooked.command.command_bits.comVgaPalette ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Parity checking"), (info->cooked.command.command_bits.comParity ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Address/data stepping"), (info->cooked.command.command_bits.comWait ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("System error"), (info->cooked.command.command_bits.comSerr ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Back-to-back writes"), (info->cooked.command.command_bits.comFastBack ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Interrupt"), (info->cooked.command.command_bits.comInterrupt ? i18nc(strCtxt, strDisabled) : i18nc(strCtxt, strEnabled))); //reverse order is intentional
|
|
return after;
|
|
}//addControl
|
|
|
|
static QTreeWidgetItem* addStatus(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
after=create(parent, i18n("Status"), value.sprintf("0x%04X", info->cooked.status.status));
|
|
localAfter=create(after, i18n("Interrupt status"), (info->cooked.status.status_bits.statCapList ? i18nc(strCtxt, strEnabled) : i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Capability list"), (info->cooked.status.status_bits.statCapList ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("66 MHz PCI 2.1 bus"), (info->cooked.status.status_bits.stat66MHz ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("User-definable features"), (info->cooked.status.status_bits.statUdf ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Accept fast back-to-back"), (info->cooked.status.status_bits.statFastBack ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Data parity error"), (info->cooked.status.status_bits.statParity ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Device selection timing"), getNameById(devSel, info->cooked.status.status_bits.statDevsel));
|
|
localAfter=create(after, i18n("Signaled target abort"), (info->cooked.status.status_bits.statSigTargetAbort ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received target abort"), (info->cooked.status.status_bits.statRecTargetAbort ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received master abort"), (info->cooked.status.status_bits.statRecMasterAbort ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Signaled system error"), (info->cooked.status.status_bits.statSigSystemError ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Parity error"), (info->cooked.status.status_bits.statDetectedParity ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
return after;
|
|
}//addStatus
|
|
|
|
static QTreeWidgetItem* addLatency(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
after=create(parent, i18n("Latency"), value.sprintf("%u", info->cooked.latencyTimer));
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_NORMAL) {
|
|
if (info->cooked.header.header0.minGnt==0) {
|
|
localAfter=create(after, i18n("MIN_GNT"), i18n("No major requirements (0x00)"));
|
|
}//if
|
|
else {
|
|
localAfter=create(after, i18n("MIN_GNT"), value.sprintf("%u ns (0x%02X)", info->cooked.header.header0.minGnt*250, info->cooked.header.header0.minGnt));
|
|
}//else
|
|
if (info->cooked.header.header0.maxLat==0) {
|
|
localAfter=create(after, i18n("MAX_LAT"), i18n("No major requirements (0x00)"));
|
|
}//if
|
|
else {
|
|
localAfter=create(after, i18n("MAX_LAT"), value.sprintf("%u ns (0x%02X)", info->cooked.header.header0.maxLat*250, info->cooked.header.header0.maxLat));
|
|
}//else
|
|
}//if
|
|
return after;
|
|
}//addLatency
|
|
|
|
static QTreeWidgetItem* addHeaderType(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
after=create(parent, i18n("Header"),value.sprintf("0x%02X",info->cooked.headerType.headerTypeFull));
|
|
localAfter=create(after, i18n("Type"),getNameById(headerType,info->cooked.headerType.headerType_bits.headerType)+value.sprintf(" (0x%02X)",info->cooked.headerType.headerType_bits.headerType));
|
|
localAfter=create(after, i18n("Multifunctional"),(info->cooked.headerType.headerType_bits.multifunctional?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
return after;
|
|
}//addHeaderType
|
|
|
|
static QTreeWidgetItem* addBist(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
after=create(parent, i18n("Build-in self test"), value.sprintf("0x%02X", info->cooked.bist.bist));
|
|
localAfter=create(after, i18n("BIST Capable"), (info->cooked.bist.bist_bits.bistCapable ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
if (info->cooked.bist.bist_bits.bistCapable==1) {
|
|
localAfter=create(after, i18n("BIST Start"), (info->cooked.bist.bist_bits.bistStart ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Completion code"), value.sprintf("0x%01X", info->cooked.bist.bist_bits.bistCode));
|
|
}//if
|
|
return after;
|
|
}//addBist
|
|
|
|
static QTreeWidgetItem* addSize(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciaddr_t size) {
|
|
if (size<0x400) {
|
|
after=create(parent, i18n("Size"), QString("%1 B").arg(static_cast<unsigned long>(size)));
|
|
}//if
|
|
else if (size<0x100000) {
|
|
after=create(parent, i18n("Size"), QString("%1 kiB").arg(static_cast<unsigned long>(size/0x400)));
|
|
}//elif
|
|
else if (size<0x40000000) {
|
|
after=create(parent, i18n("Size"), QString("%1 MiB").arg(static_cast<unsigned long>(size/0x100000)));
|
|
}//elif
|
|
|
|
#ifdef HAVE_PCIADDR_T64
|
|
|
|
else if (size<0x10000000000LL) {
|
|
after=create(parent, i18n("Size"),QString("%1 GiB").arg(static_cast<unsigned long>(size/0x40000000)));
|
|
}//elif
|
|
else if (size<0x4000000000000LL) {
|
|
after=create(parent, i18n("Size"),QString("%1 PiB").arg(static_cast<unsigned long>(size/0x10000000000LL)));
|
|
}//elif
|
|
else if (size<0x1000000000000000LL) {
|
|
after=create(parent, i18n("Size"),QString("%1 EiB").arg(static_cast<unsigned long>(size/0x4000000000000LL)));
|
|
}//elif
|
|
|
|
#else //HAVE_PCIADDR_T64
|
|
else {
|
|
after=create(parent, i18n("Size"), QString("%1 GiB").arg(static_cast<unsigned long>(size/0x40000000)));
|
|
}//else
|
|
|
|
#endif //HAVE_PCIADDR_T64
|
|
return after;
|
|
}//addSize
|
|
|
|
static QTreeWidgetItem* addMapping(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, pci_dev* PCIDevice) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QTreeWidgetItem *topLocalAfter=NULL;
|
|
QString value;
|
|
bool is64b=false;
|
|
after=createTitle(parent, i18n("Address mappings"));
|
|
for (int i=0; i<6; i++) {
|
|
if (((info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE)&&(i>1))||((info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS)&&(i>0))) {
|
|
break;
|
|
}//if
|
|
if (is64b) { //skip one range
|
|
continue;
|
|
}//if
|
|
topLocalAfter=createTitle(after, i18n("Mapping %1", i));
|
|
localAfter=create(topLocalAfter, i18n("Space"), (info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? i18n("I/O") : i18n("Memory")));
|
|
if (info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap==0) { //memory only
|
|
localAfter=create(topLocalAfter, i18n("Type"), getNameById(mappingType, info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressType));
|
|
localAfter=create(topLocalAfter, i18n("Prefetchable"), (info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressPref ? i18nc(strCtxt, strYes) : i18nc(strCtxt, strNo)));
|
|
}//if
|
|
if (is64b) { //there is no long long support in Qt so we need compose value
|
|
topLocalAfter->setText(1, value.sprintf("0x%08X%08X", info->cooked.header.header0.mapping[i+1].baseAddress, info->cooked.header.header0.mapping[i].baseAddress));
|
|
if (info->cooked.header.header0.mapping[i+1].baseAddress==0) { //no top 4 bytes
|
|
if ((info->cooked.header.header0.mapping[i].baseAddress&(~(info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? 0x3 : 0xF)))==0) { //no address at all
|
|
localAfter=create(topLocalAfter, i18n("Address"), i18nc("unassigned address", "Unassigned"));
|
|
localAfter=create(topLocalAfter, i18n("Size"), i18nc("unassigned size", "Unassigned"));
|
|
}//if
|
|
else {
|
|
localAfter=create(topLocalAfter, i18n("Address"), value.sprintf("0x%X", (info->cooked.header.header0.mapping[i].baseAddress&(~(info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? 0x3 : 0xF)))));
|
|
localAfter=addSize(topLocalAfter, localAfter, PCIDevice->size[i]);
|
|
}//else
|
|
}//if
|
|
else {
|
|
localAfter=create(topLocalAfter, i18n("Address"), value.sprintf("0x%X%08X", info->cooked.header.header0.mapping[i+1].baseAddress, (~(info->cooked.header.header0.mapping[i].baseAddress&(info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? 0x3 : 0xF)))));
|
|
localAfter=addSize(topLocalAfter, localAfter, PCIDevice->size[i]);
|
|
}//else
|
|
}//if
|
|
else {
|
|
topLocalAfter->setText(1, value.sprintf("0x%08X", info->cooked.header.header0.mapping[i].baseAddress));
|
|
if ((info->cooked.header.header0.mapping[i].baseAddress&(~(info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? 0x3 : 0xF)))==0) { //no address at all
|
|
localAfter=create(topLocalAfter, i18n("Address"), i18nc("unassigned address", "Unassigned"));
|
|
localAfter=create(topLocalAfter, i18n("Size"), i18nc("unassigned size", "Unassigned"));
|
|
}//if
|
|
else {
|
|
localAfter=create(topLocalAfter, i18n("Address"), value.sprintf("0x%X", (info->cooked.header.header0.mapping[i].baseAddress&(~(info->cooked.header.header0.mapping[i].baseAddress_bits.baseAddressMap ? 0x3 : 0xF)))));
|
|
localAfter=addSize(topLocalAfter, localAfter, PCIDevice->size[i]);
|
|
}//else
|
|
}//else
|
|
}//for
|
|
return after;
|
|
}//addMapping
|
|
|
|
static QTreeWidgetItem* addBus(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE) {
|
|
after=createTitle(parent, i18n("Bus"));
|
|
localAfter=create(after, i18n("Primary bus number"), value.sprintf("0x%02X", info->cooked.header.header1.primaryBus));
|
|
localAfter=create(after, i18n("Secondary bus number"), value.sprintf("0x%02X", info->cooked.header.header1.secondaryBus));
|
|
localAfter=create(after, i18n("Subordinate bus number"), value.sprintf("0x%02X", info->cooked.header.header1.subordinateBus));
|
|
localAfter=create(after, i18n("Secondary latency timer"), value.sprintf("0x%02X", info->cooked.header.header1.secLatencyTimer));
|
|
}//if
|
|
else if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS) { //should be checked
|
|
after=createTitle(parent, i18n("Bus"));
|
|
localAfter=create(after, i18n("Primary bus number"), value.sprintf("0x%02X", info->cooked.header.header2.cbPrimaryBus));
|
|
localAfter=create(after, i18n("CardBus number"), value.sprintf("0x%02X", info->cooked.header.header2.cbCardBus));
|
|
localAfter=create(after, i18n("Subordinate bus number"), value.sprintf("0x%02X", info->cooked.header.header2.cbSubordinateBus));
|
|
localAfter=create(after, i18n("CardBus latency timer"), value.sprintf("0x%02X", info->cooked.header.header2.cbLatencyTimer));
|
|
}//elif
|
|
return after;
|
|
}//addBus
|
|
|
|
static QTreeWidgetItem* addSecStatus(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE) {
|
|
after=create(parent, i18n("Secondary status"), value.sprintf("0x%04X", info->cooked.header.header1.secStatus.secStatus));
|
|
localAfter=create(after, i18n("Interrupt status"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatCapList?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Capability list"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatCapList?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("66 MHz PCI 2.1 bus"),(info->cooked.header.header1.secStatus.secStatus_bits.secStat66MHz?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("User-definable features"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatUdf?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Accept fast back-to-back"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatFastBack?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Data parity error"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatParity?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Device selection timing"),getNameById(devSel,info->cooked.header.header1.secStatus.secStatus_bits.secStatDevsel));
|
|
localAfter=create(after, i18n("Signaled target abort"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatSigTargetAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received target abort"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatRecTargetAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received master abort"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatRecMasterAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Signaled system error"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatSigSystemError?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Parity error"),(info->cooked.header.header1.secStatus.secStatus_bits.secStatDetectedParity?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
}//if
|
|
else if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS) { //should be checked
|
|
after=create(parent,i18n("Secondary status"),value.sprintf("0x%04X",info->cooked.header.header2.cbSecStatus.cbSecStatus));
|
|
localAfter=create(after, i18n("Interrupt status"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatCapList?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Capability list"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatCapList?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("66 MHz PCI 2.1 bus"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStat66MHz?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("User-definable features"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatUdf?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Accept fast back-to-back"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatFastBack?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Data parity error"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatParity?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Device selection timing"),getNameById(devSel,info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatDevsel));
|
|
localAfter=create(after, i18n("Signaled target abort"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatSigTargetAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received target abort"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatRecTargetAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Received master abort"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatRecMasterAbort?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Signaled system error"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatSigSystemError?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Parity error"),(info->cooked.header.header2.cbSecStatus.cbSecStatus_bits.cbSecStatDetectedParity?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
}//elif
|
|
return after;
|
|
}//addSecStatus
|
|
|
|
static QTreeWidgetItem* addBridgeBehind(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE) {
|
|
after=createTitle(parent, i18n("I/O behind bridge"));
|
|
localAfter=create(after, i18n("32-bit"),(info->cooked.header.header1.ioBase.ioBase_bits.ioBaseType?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
if (info->cooked.header.header1.ioBase.ioBase_bits.ioBaseType==0) {
|
|
localAfter=create(after, i18n("Base"),value.sprintf("0x%04X",info->cooked.header.header1.ioBase.ioBase&0xFFF0));
|
|
localAfter=create(after, i18n("Limit"),value.sprintf("0x%04X",info->cooked.header.header1.ioLimit|0x0F));
|
|
}//if
|
|
else {
|
|
localAfter=create(after, i18n("Base"),value.sprintf("0x%04X%04X",info->cooked.header.header1.ioBaseUpper16,info->cooked.header.header1.ioBase.ioBase&0xFFF0));
|
|
localAfter=create(after, i18n("Limit"),value.sprintf("0x%04X%04X",info->cooked.header.header1.ioLimitUpper16,info->cooked.header.header1.ioLimit|0x0F));
|
|
}//else
|
|
after=createTitle(parent, i18n("Memory behind bridge"));
|
|
localAfter=create(after, i18n("Base"),value.sprintf("0x%08X",(info->cooked.header.header1.memoryBase.memoryBase<<16)&0xFFFFFFF0));
|
|
localAfter=create(after, i18n("Limit"),value.sprintf("0x%08X",(info->cooked.header.header1.memoryLimit<<16)|0x0FFFFF));
|
|
after=createTitle(parent, i18n("Prefetchable memory behind bridge"));
|
|
localAfter=create(after, i18n("64-bit"),(info->cooked.header.header1.ioBase.ioBase_bits.ioBaseType?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
if (info->cooked.header.header1.ioBase.ioBase_bits.ioBaseType==0) {
|
|
localAfter=create(after, i18n("Base"),value.sprintf("0x%08X",(info->cooked.header.header1.prefMemoryBase.prefMemoryBase<<16)&0xFFFFFFF0));
|
|
localAfter=create(after, i18n("Limit"),value.sprintf("0x%08X",(info->cooked.header.header1.prefMemoryLimit<<16)|0x0FFFFF));
|
|
}//if
|
|
else {
|
|
localAfter=create(after, i18n("Base"),value.sprintf("0x%08X%08X",info->cooked.header.header1.prefBaseUpper32,(info->cooked.header.header1.prefMemoryBase.prefMemoryBase<<16)&0xFFFFFFF0));
|
|
localAfter=create(after, i18n("Limit"),value.sprintf("0x%0x8X%08X",info->cooked.header.header1.prefLimitUpper32,(info->cooked.header.header1.prefMemoryLimit<<16)|0x0FFFFF));
|
|
}//else
|
|
}//if
|
|
return after;
|
|
}//addBridgeBechind
|
|
|
|
static QTreeWidgetItem* addBridgeControl(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE) {
|
|
after=create(parent, i18n("Bridge control"),value.sprintf("0x%04X",info->cooked.header.header1.bridgeControl.bridgeControl));
|
|
localAfter=create(after, i18n("Secondary parity checking"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlParity?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Secondary system error"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlSerr?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("ISA ports forwarding"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlIsa?i18nc(strCtxt, strDisabled):i18nc(strCtxt, strEnabled))); //reverse order is intentional
|
|
localAfter=create(after, i18n("VGA forwarding"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlVga?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Master abort"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlMasterAbort?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Secondary bus reset"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlBusReset?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Secondary back-to-back writes"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlFastBack?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Primary discard timer counts"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlPriDisTim?i18n("2e10 PCI clocks"):i18n("2e15 PCI clocks")));
|
|
localAfter=create(after, i18n("Secondary discard timer counts"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlSecDisTim?i18n("2e10 PCI clocks"):i18n("2e15 PCI clocks")));
|
|
localAfter=create(after, i18n("Discard timer error"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlDisTimStat?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Discard timer system error"),(info->cooked.header.header1.bridgeControl.bridgeControl_bits.bridgeControlDisTimeSerr?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
return after;
|
|
}//addBridgeControl
|
|
|
|
static QTreeWidgetItem* addRom(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, pci_dev* PCIDevice) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if ((info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_NORMAL)||(info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE)) {
|
|
after=createTitle(parent, i18n("Expansion ROM"));
|
|
localAfter=create(after, i18n("Status"),(info->cooked.header.header0.romAddress.romAddress_bits.romEnabled?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if (PCIDevice->rom_base_addr==0) { //no address at all
|
|
localAfter=create(after, i18n("Address"),i18nc("unassigned address", "Unassigned"));
|
|
localAfter=create(after, i18n("Size"),i18nc("unassigned size", "Unassigned"));
|
|
}//if
|
|
else {
|
|
localAfter=create(after, i18n("Address"),value.sprintf("0x%X",static_cast<unsigned>(PCIDevice->rom_base_addr)));
|
|
localAfter=addSize(after, localAfter, PCIDevice->rom_size);
|
|
}//else
|
|
}//if
|
|
return after;
|
|
}//addRom
|
|
|
|
static QTreeWidgetItem* addCardbusResource(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QTreeWidgetItem *topLocalAfter=NULL;
|
|
QString value;
|
|
int pref=0;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS) {
|
|
after=createTitle(parent, i18n("Memory windows"));
|
|
for (int i=0; i<2; i++) {
|
|
pref=(i ? info->cooked.header.header2.cbControl.cbControl_bits.cbControlPref1 : info->cooked.header.header2.cbControl.cbControl_bits.cbControlPref0);
|
|
topLocalAfter=createTitle(after, i18n("Window %1", i));
|
|
localAfter=create(topLocalAfter, i18n("Prefetchable"),(pref?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(topLocalAfter, i18n("Base"),value.sprintf("0x%08X",info->cooked.header.header2.cbMemory[i].cbMemoryBase));
|
|
localAfter=create(topLocalAfter, i18n("Limit"),value.sprintf("0x%08X",info->cooked.header.header2.cbMemory[i].cbMemoryLimit));
|
|
}//for
|
|
after=createTitle(parent, i18n("I/O windows"));
|
|
for (int i=0; i<2; i++) {
|
|
topLocalAfter=createTitle(after, i18n("Window %1", i));
|
|
localAfter=create(topLocalAfter, i18n("Type"),(info->cooked.header.header2.cbIo[i].cbIoBase.cbIoBase_bits.cbIoBaseType?i18n("32-bit"):i18n("16-bit")));
|
|
if (info->cooked.header.header2.cbIo[i].cbIoBase.cbIoBase_bits.cbIoBaseType==1) {
|
|
localAfter=create(topLocalAfter, i18n("Base"),value.sprintf("0x%08X",info->cooked.header.header2.cbIo[i].cbIoBase.cbIoBase&0xFFFFFFFC));
|
|
localAfter=create(topLocalAfter, i18n("Limit"),value.sprintf("0x%08X",info->cooked.header.header2.cbIo[i].cbIoLimit|0x03));
|
|
}//if
|
|
else {
|
|
localAfter=create(topLocalAfter, i18n("Base"),value.sprintf("0x%04X",info->cooked.header.header2.cbIo[i].cbIoBase.cbIoBase&0xFFFC));
|
|
localAfter=create(topLocalAfter, i18n("Limit"),value.sprintf("0x%04X",(info->cooked.header.header2.cbIo[i].cbIoLimit&0xFFFF)|0x03));
|
|
}//else
|
|
}//for
|
|
after=create(parent, i18n("16-bit legacy interface ports"),value.sprintf("0x%04X",info->cooked.header.header2.cbLegacyModeBase));
|
|
}//if
|
|
return after;
|
|
}//addCardbusResource
|
|
|
|
static QTreeWidgetItem* addCardbusControl(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
if (info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_CARDBUS) {
|
|
after=create(parent, i18n("CardBus control"),value.sprintf("0x%04X",info->cooked.header.header2.cbControl.cbControl));
|
|
localAfter=create(after, i18n("Secondary parity checking"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlParity?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Secondary system error"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlSerr?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("ISA ports forwarding"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlIsa?i18nc(strCtxt, strDisabled):i18nc(strCtxt, strEnabled))); //reverse order is intentional
|
|
localAfter=create(after, i18n("VGA forwarding"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlVga?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Master abort"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlMasterAbort?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Interrupts for 16-bit cards"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControl16Int?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Window 0 prefetchable memory"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlPref0?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Window 1 prefetchable memory"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlPref1?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Post writes"),(info->cooked.header.header2.cbControl.cbControl_bits.cbControlPostWrites?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
return after;
|
|
}//addCardbusControl
|
|
|
|
static QTreeWidgetItem* addRaw(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value, temp;
|
|
after=createTitle(parent, i18n("Raw PCI config space"));
|
|
for (int i=0; i<(getuid()==0 ? 16 : 4); i++) {
|
|
for (int j=0; j<16; j++) {
|
|
if (j!=0) {
|
|
value+=temp.sprintf(" %02X", info->raw[i*16+j]);
|
|
}//if
|
|
else {
|
|
value.sprintf("%02X", info->raw[i*16+j]);
|
|
}//if
|
|
}//for
|
|
localAfter=create(after, temp.sprintf("0x%02X:",i*16),value);
|
|
}//for
|
|
return after;
|
|
}//addRaw
|
|
|
|
static QTreeWidgetItem* addCapsPm(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, int offset) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QTreeWidgetItem *subLocalAfter=NULL;
|
|
QString value;
|
|
pmInfo infoPm;
|
|
if ((offset+2+sizeof(pmInfo))<256) {
|
|
memcpy(reinterpret_cast<void*>(&infoPm.raw[0]), reinterpret_cast<void*>(&info->raw[offset+2]), sizeof(pmInfo));
|
|
after=create(parent, i18n("Capabilities"),value.sprintf("0x%04X",infoPm.cooked.caps.caps));
|
|
localAfter=create(after, i18n("Version"),QString::number(infoPm.cooked.caps.caps_bits.capsVer));
|
|
localAfter=create(after, i18n("Clock required for PME generation"),(infoPm.cooked.caps.caps_bits.capsClock?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Device-specific initialization required"),(infoPm.cooked.caps.caps_bits.capsDsi?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
localAfter=create(after, i18n("Maximum auxiliary current required in D3 cold"),getNameById(auxCur,infoPm.cooked.caps.caps_bits.capsAuxCur));
|
|
localAfter=create(after, i18n("D1 support"),(infoPm.cooked.caps.caps_bits.capsD1Supp?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("D2 support"),(infoPm.cooked.caps.caps_bits.capsD2Supp?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=createTitle(after, i18n("Power management events"));
|
|
subLocalAfter=create(localAfter, i18n("D0"),(infoPm.cooked.caps.caps_bits.capsPmeD0?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
subLocalAfter=create(localAfter, i18n("D1"),(infoPm.cooked.caps.caps_bits.capsPmeD1?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
subLocalAfter=create(localAfter, i18n("D2"),(infoPm.cooked.caps.caps_bits.capsPmeD2?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
subLocalAfter=create(localAfter, i18n("D3 hot"),(infoPm.cooked.caps.caps_bits.capsPmeD3hot?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
subLocalAfter=create(localAfter, i18n("D3 cold"),(infoPm.cooked.caps.caps_bits.capsPmeD3cold?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=NULL;
|
|
after=create(parent, i18n("Status"),value.sprintf("0x%04X",infoPm.cooked.status.status));
|
|
localAfter=create(after, i18n("Power state"),getNameById(powerState,infoPm.cooked.status.status_bits.statPower));
|
|
localAfter=create(after, i18n("Power management"),(infoPm.cooked.status.status_bits.statPme?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Data select"),QString::number(infoPm.cooked.status.status_bits.statDataSelect));
|
|
localAfter=create(after, i18n("Data scale"),QString::number(infoPm.cooked.status.status_bits.statDataScale));
|
|
localAfter=create(after, i18n("Power management status"),(infoPm.cooked.status.status_bits.statPmeStat?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if ((info->cooked.devClass==0x06)&&(info->cooked.devSubClass==0x04)) { //PCI bridge
|
|
subLocalAfter=NULL;
|
|
localAfter=create(after, i18n("Bridge status"),value.sprintf("0x%02X",infoPm.cooked.statusBridge.statusBridge));
|
|
subLocalAfter=create(localAfter, i18n("Secondary bus state in D3 hot"),(infoPm.cooked.statusBridge.statusBridge_bits.statBridgeBx?i18n("B2"):i18n("B3")));
|
|
subLocalAfter=create(localAfter, i18n("Secondary bus power & clock control"),(infoPm.cooked.statusBridge.statusBridge_bits.statBridgeClock?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
}//if
|
|
after=create(parent, i18n("Data"),value.sprintf("0x%02X",infoPm.cooked.data));
|
|
return after;
|
|
}//addCapsPm
|
|
|
|
static QTreeWidgetItem* addCapsAgp(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, int offset) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
agpInfo infoAgp;
|
|
int i, cycleSize;
|
|
if ((offset+2+sizeof(agpInfo))<256) {
|
|
memcpy(reinterpret_cast<void*>(&infoAgp.raw[0]), reinterpret_cast<void*>(&info->raw[offset+2]), sizeof(agpInfo));
|
|
// after=create(parent, i18n("Revision"),value.sprintf("%i.%i",infoAgp.revMaior,infoAgp.revMinor));
|
|
after=create(parent, i18n("Revision"),QString("%1.%2").arg(infoAgp.cooked.revision.revMaior).arg(infoAgp.cooked.revision.revMinor));
|
|
after=create(parent, i18n("Status"),value.sprintf("0x%08X",infoAgp.cooked.status.status));
|
|
localAfter=create(after, i18n("Rate"),getNameById(agpRate,infoAgp.cooked.status.status_bits0.statusEnhRate));
|
|
localAfter=create(after, i18n("AGP 3.0 mode"),(infoAgp.cooked.status.status_bits1.statusMode?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Fast Writes"),(infoAgp.cooked.status.status_bits1.statusFastWrite?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Address over 4 GiB"),(infoAgp.cooked.status.status_bits1.statusOver4gb?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if (infoAgp.cooked.status.status_bits1.statusMode==1) {
|
|
localAfter=create(after, i18n("Translation of host processor access"),(infoAgp.cooked.status.status_bits1.statusHtrans?i18nc(strCtxt, strDisabled):i18nc(strCtxt, strEnabled))); //reverse order is intentional
|
|
localAfter=create(after, i18n("64-bit GART"),(infoAgp.cooked.status.status_bits1.statusGart64b?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Cache Coherency"),(infoAgp.cooked.status.status_bits1.statusItaCoh?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
localAfter=create(after, i18n("Side-band addressing"),(infoAgp.cooked.status.status_bits1.statusSba?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if (infoAgp.cooked.status.status_bits1.statusMode==1) {
|
|
localAfter=create(after, i18n("Calibrating cycle"),getNameById(calCycle,infoAgp.cooked.status.status_bits1.statusCalCycle));
|
|
for (i=0, cycleSize=1; i<(infoAgp.cooked.status.status_bits1.statusOptReqSize+4); i++) {
|
|
cycleSize*=2;
|
|
}//for
|
|
localAfter=create(after, i18n("Optimum asynchronous request size"),value.sprintf("%i (0x%02X)",cycleSize,infoAgp.cooked.status.status_bits1.statusOptReqSize));
|
|
localAfter=create(after, i18n("Isochronous transactions"),(infoAgp.cooked.status.status_bits1.statusIsochSupp?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
localAfter=create(after, i18n("Maximum number of AGP command"),value.sprintf("%i (0x%02X)",infoAgp.cooked.status.status_bits1.statusReq+1,infoAgp.cooked.status.status_bits1.statusReq));
|
|
localAfter=NULL;
|
|
after=create(parent, i18n("Configuration"),value.sprintf("0x%08X",infoAgp.cooked.config.config));
|
|
localAfter=create(after, i18n("Rate"),getNameById(agpRate,infoAgp.cooked.config.config_bits0.configEnhRate));
|
|
localAfter=create(after, i18n("Fast Writes"),(infoAgp.cooked.config.config_bits1.configFastWrite?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if (infoAgp.cooked.status.status_bits1.statusMode==1) {
|
|
localAfter=create(after, i18n("Address over 4 GiB"),(infoAgp.cooked.config.config_bits1.configOver4gb?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("64-bit GART"),(infoAgp.cooked.config.config_bits1.configGart64b?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
}//if
|
|
localAfter=create(after, i18n("AGP"),(infoAgp.cooked.config.config_bits1.configAgp?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Side-band addressing"),(infoAgp.cooked.config.config_bits1.configSba?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
if (infoAgp.cooked.status.status_bits1.statusMode==1) {
|
|
localAfter=create(after, i18n("Calibrating cycle"),getNameById(calCycle,infoAgp.cooked.config.config_bits1.configCalCycle));
|
|
for (i=0, cycleSize=1; i<(infoAgp.cooked.config.config_bits1.configOptReqSize+4); i++) {
|
|
cycleSize*=2;
|
|
}//for
|
|
localAfter=create(after, i18n("Optimum asynchronous request size"),value.sprintf("%i (0x%02X)",cycleSize,infoAgp.cooked.config.config_bits1.configOptReqSize));
|
|
}//if
|
|
localAfter=create(after, i18n("Maximum number of AGP command"),value.sprintf("%i (0x%02X)",infoAgp.cooked.config.config_bits1.configReq+1,infoAgp.cooked.config.config_bits1.configReq));
|
|
}//if
|
|
return after;
|
|
}//addCapsAgp
|
|
|
|
static QTreeWidgetItem* addCapsVpd(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, int offset) {
|
|
QString value;
|
|
vpdInfo infoVpd;
|
|
if ((offset+2+sizeof(vpdInfo))<256) {
|
|
memcpy(reinterpret_cast<void*>(&infoVpd.raw[0]), reinterpret_cast<void*>(&info->raw[offset+2]), sizeof(vpdInfo));
|
|
after=create(parent, i18n("Data address"),value.sprintf("0x%04X",infoVpd.cooked.vpdAddress));
|
|
after=create(parent, i18n("Transfer completed"),(infoVpd.cooked.vpdTransfer?i18nc(strCtxt, strYes):i18nc(strCtxt, strNo)));
|
|
after=create(parent, i18n("Data"),value.sprintf("0x%08X",infoVpd.cooked.vpdData));
|
|
}//if
|
|
return after;
|
|
}//addCapsVpd
|
|
|
|
static QTreeWidgetItem* addCapsMsi(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, int offset) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QString value;
|
|
msiInfo infoMsi;
|
|
int size=10;
|
|
if ((offset+4)<256) { //copy control only (for now)
|
|
memcpy(reinterpret_cast<void*>(&infoMsi.raw[0]), reinterpret_cast<void*>(&info->raw[offset+2]), 2);
|
|
after=create(parent, i18n("Message control"),value.sprintf("0x%04X",infoMsi.cooked.msiControl.msiControl));
|
|
localAfter=create(after, i18n("Message signaled interrupts"),(infoMsi.cooked.msiControl.msiControl_bits.msiEnable?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Multiple message capable"),getNameById(multipleMessage,infoMsi.cooked.msiControl.msiControl_bits.msiMmCapable));
|
|
localAfter=create(after, i18n("Multiple message enable"),getNameById(multipleMessage,infoMsi.cooked.msiControl.msiControl_bits.msiMmEnable));
|
|
localAfter=create(after, i18n("64-bit address"),(infoMsi.cooked.msiControl.msiControl_bits.msi64bit?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
localAfter=create(after, i18n("Per vector masking"),(infoMsi.cooked.msiControl.msiControl_bits.msiPerVector?i18nc(strCtxt, strEnabled):i18nc(strCtxt, strDisabled)));
|
|
size+=(infoMsi.cooked.msiControl.msiControl_bits.msi64bit ? 4 : 0)+(infoMsi.cooked.msiControl.msiControl_bits.msiPerVector ? 8 : 0);
|
|
if ((offset+size)<256) { //copy all MSI data
|
|
memcpy(reinterpret_cast<void*>(&infoMsi.raw[0]), reinterpret_cast<void*>(&info->raw[offset+size]), 2);
|
|
if (infoMsi.cooked.msiControl.msiControl_bits.msi64bit==1) {
|
|
after=create(parent, i18n("Address"),value.sprintf("0x%08X%08X",infoMsi.cooked.payload.address.msiUpperAddress,infoMsi.cooked.msiAddress));
|
|
after=create(parent, i18n("Data"),value.sprintf("0x%04X",infoMsi.cooked.payload.address.msiData64));
|
|
if (infoMsi.cooked.msiControl.msiControl_bits.msiPerVector==1) {
|
|
after=create(parent, i18n("Mask"),value.sprintf("0x%08X",infoMsi.cooked.payload.address.msiMask64));
|
|
after=create(parent, i18n("Pending"),value.sprintf("0x%08X",infoMsi.cooked.payload.address.msiPending64));
|
|
}//if
|
|
}//if
|
|
else {
|
|
after=create(parent, i18n("Address"),value.sprintf("0x%08X",infoMsi.cooked.msiAddress));
|
|
after=create(parent, i18n("Data"),value.sprintf("0x%04X",infoMsi.cooked.payload.data.msiData));
|
|
if (infoMsi.cooked.msiControl.msiControl_bits.msiPerVector==1) {
|
|
after=create(parent, i18n("Mask"),value.sprintf("0x%08X",infoMsi.cooked.payload.data.msiMask));
|
|
after=create(parent, i18n("Pending"),value.sprintf("0x%08X",infoMsi.cooked.payload.data.msiPending));
|
|
}//if
|
|
}//else
|
|
}//if
|
|
}//if
|
|
return after;
|
|
}//addCapsMsi
|
|
|
|
static QTreeWidgetItem* addCapsVendor(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info, int offset) {
|
|
QString value, temp;
|
|
after=create(parent, i18n("Length"),value.sprintf("0x%02X",info->raw[offset+2]));
|
|
if ((offset+3)<256) { //check partial size
|
|
if (info->raw[offset+2]<=2) {
|
|
after=create(parent, i18n("Data"),i18nc("no data", "None"));
|
|
}//if
|
|
else {
|
|
if ((offset+info->raw[offset+2])<256) { //check full size
|
|
for (int i=3; i<(info->raw[offset+2]); i++) {
|
|
if (i!=3) {
|
|
value+=temp.sprintf(" 0x%02X", info->raw[offset+i]);
|
|
}//if
|
|
else {
|
|
value.sprintf("0x%02X", info->raw[offset+i]);
|
|
}//if
|
|
}//for
|
|
after=create(parent, i18n("Data"),value);
|
|
}//if
|
|
}//else
|
|
}//if
|
|
return after;
|
|
}//addCapsVendor
|
|
|
|
static QTreeWidgetItem* addCaps(QTreeWidgetItem *parent, QTreeWidgetItem *after, pciInfo *info) {
|
|
QTreeWidgetItem *localAfter=NULL;
|
|
QTreeWidgetItem *topLocalAfter=NULL;
|
|
QString value;
|
|
unsigned char offset;
|
|
if ((info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_NORMAL)||(info->cooked.headerType.headerType_bits.headerType==PCI_HEADER_TYPE_BRIDGE)) {
|
|
if ((info->cooked.header.header0.capabilityList!=0)&&(info->cooked.status.status_bits.statCapList!=0)) {
|
|
after=create(parent, i18n("Capabilities"),value.sprintf("0x%02X",info->cooked.header.header0.capabilityList));
|
|
if (getuid()==0) {
|
|
for (offset=info->cooked.header.header0.capabilityList; offset!=0; offset=info->raw[offset+1]) {
|
|
topLocalAfter=create(after, getNameById(capNames,info->raw[offset]),value.sprintf("0x%02X",info->raw[offset]));
|
|
localAfter=create(topLocalAfter, i18n("Next"),(info->raw[offset+1]==0?i18n("0x00 (None)"):value.sprintf("0x%02X",info->raw[offset+1])));
|
|
switch (info->raw[offset]) {
|
|
case 0x01: //Power Managemet
|
|
addCapsPm(topLocalAfter, localAfter, info, offset);
|
|
break;
|
|
case 0x02: //AGP
|
|
addCapsAgp(topLocalAfter, localAfter, info, offset);
|
|
break;
|
|
case 0x03: //VPD
|
|
addCapsVpd(topLocalAfter, localAfter, info, offset);
|
|
break;
|
|
case 0x05: //MSI
|
|
addCapsMsi(topLocalAfter, localAfter, info, offset);
|
|
break;
|
|
case 0x09: //vendor specific
|
|
addCapsVendor(topLocalAfter, localAfter, info, offset);
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch
|
|
}//for
|
|
}//if
|
|
else {
|
|
topLocalAfter=createTitle(after, i18n("Root only"));
|
|
}//else
|
|
}//if
|
|
else {
|
|
after=create(parent, i18n("Capabilities"),i18n("0x00 (None)"));
|
|
}//else
|
|
}//if
|
|
return after;
|
|
}//addCaps
|
|
|
|
bool GetInfo_PCIUtils(QTreeWidget* tree) {
|
|
QStringList headers;
|
|
headers << i18n("Information") << i18n("Value");
|
|
tree->setHeaderLabels(headers);
|
|
tree->setRootIsDecorated(true);
|
|
|
|
pci_access *PCIAccess=NULL;
|
|
pci_dev *PCIDevice=NULL;
|
|
|
|
//init libpci
|
|
PCIAccess=pci_alloc();
|
|
if (PCIAccess==NULL) {
|
|
return false;
|
|
}//if
|
|
|
|
pci_init(PCIAccess);
|
|
pci_scan_bus(PCIAccess);
|
|
|
|
QTreeWidgetItem *DeviceName=NULL, *after=NULL;
|
|
QString value;
|
|
pciInfo info;
|
|
|
|
//proces all devices
|
|
for (PCIDevice=PCIAccess->devices; PCIDevice; PCIDevice=PCIDevice->next) {
|
|
//get PCI data
|
|
pci_fill_info(PCIDevice, PCI_FILL_IDENT|PCI_FILL_IRQ|PCI_FILL_BASES|PCI_FILL_ROM_BASE|PCI_FILL_SIZES);
|
|
if (getuid()==0) {
|
|
pci_read_block(PCIDevice, 0, info.raw, 256);
|
|
}//if
|
|
else {
|
|
pci_read_block(PCIDevice, 0, info.raw, 64);
|
|
}//else
|
|
|
|
QStringList deviceList;
|
|
deviceList << value.sprintf("%02X:%02X.%d", PCIDevice->bus, PCIDevice->dev, PCIDevice->func);
|
|
//create device tree
|
|
DeviceName=new QTreeWidgetItem(tree, deviceList);
|
|
//adding class, subclass and programming interface info
|
|
after=addDeviceClass(DeviceName, NULL, &info);
|
|
|
|
//adding revision
|
|
after=create(DeviceName, i18n("Revision"), value.sprintf("0x%02X", info.cooked.revision));
|
|
//adding vendor, device, and subvendor/sudevice info
|
|
after=addVendor(DeviceName, after, &info, PCIAccess);
|
|
//adding control
|
|
after=addControl(DeviceName, after, &info);
|
|
//adding status
|
|
after=addStatus(DeviceName, after, &info);
|
|
|
|
//adding cache line size
|
|
after=create(DeviceName, i18n("Cache line size"), value.sprintf("0x%02X", info.cooked.cacheLineSize));
|
|
//adding latency
|
|
after=addLatency(DeviceName, after, &info);
|
|
//adding header type
|
|
after=addHeaderType(DeviceName, after, &info);
|
|
//adding BIST
|
|
after=addBist(DeviceName, after, &info);
|
|
//adding address mapping
|
|
after=addMapping(DeviceName, after, &info, PCIDevice);
|
|
//adding bus info
|
|
after=addBus(DeviceName, after, &info);
|
|
//adding secondary status
|
|
after=addSecStatus(DeviceName, after, &info);
|
|
//adding resourece behind bridge
|
|
after=addBridgeBehind(DeviceName, after, &info);
|
|
//adding bridge control
|
|
after=addBridgeControl(DeviceName, after, &info);
|
|
//adding cardbus resource
|
|
after=addCardbusResource(DeviceName, after, &info);
|
|
//adding cardbus control
|
|
after=addCardbusControl(DeviceName, after, &info);
|
|
//adding ROM
|
|
after=addRom(DeviceName, after, &info, PCIDevice);
|
|
//adding capabilities
|
|
after=addCaps(DeviceName, after, &info);
|
|
|
|
//adding interrupt info (IRQ, pin)
|
|
after=addInterrupt(DeviceName, after, PCIDevice->irq, info.cooked.header.header0.interruptPin); //PCI data have wrong IRQ ?!?
|
|
//add raw PCI config data
|
|
after=addRaw(DeviceName, after, &info);
|
|
}//for
|
|
|
|
pci_cleanup(PCIAccess);
|
|
return true;
|
|
} //GetInfo_PCIUtils
|
|
|