summaryrefslogtreecommitdiff
path: root/hw/xfree86/scanpci/xf86ScanPci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/scanpci/xf86ScanPci.c')
-rw-r--r--hw/xfree86/scanpci/xf86ScanPci.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/hw/xfree86/scanpci/xf86ScanPci.c b/hw/xfree86/scanpci/xf86ScanPci.c
new file mode 100644
index 000000000..0370a6e5f
--- /dev/null
+++ b/hw/xfree86/scanpci/xf86ScanPci.c
@@ -0,0 +1,389 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/scanpci/xf86ScanPci.c,v 1.12 2002/07/15 20:46:04 dawes Exp $ */
+/*
+ * Display the Subsystem Vendor Id and Subsystem Id in order to identify
+ * the cards installed in this computer
+ *
+ * Copyright 1995-2002 by The XFree86 Project, Inc.
+ *
+ * A lot of this comes from Robin Cutshaw's scanpci
+ *
+ */
+
+
+/*
+ * This file is used to build both the scanpci and pcidata modules.
+ * The interfaces have changed compared with XFree86 4.2.0 and earlier.
+ * The data is no longer exported directly. Lookup functions are provided.
+ * This means that the data format can change in the future without affecting
+ * the exported interfaces.
+ *
+ * The namespaces for pcidata and scanpci clash, so both modules can't be
+ * loaded at the same time. The X server should only load the scanpci module
+ * when run with the '-scanpci' flag. The main difference between the
+ * two modules is size. pcidata only holds the subset of data that is
+ * "interesting" to the X server. "Interesting" is determined by the
+ * PCI_VENDOR_* defines in ../common/xf86PciInfo.h.
+ */
+
+
+/* XXX This is including a lot of stuff that modules should not include! */
+
+#include "X.h"
+#include "os.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Pci.h"
+#include "xf86_OSproc.h"
+
+#ifndef IN_MODULE
+#include <ctype.h>
+#include <stdlib.h>
+#else
+#include <xf86_ansic.h>
+#endif
+
+#ifndef PCIDATA
+#define VENDOR_INCLUDE_NONVIDEO
+#endif
+#define INIT_SUBSYS_INFO
+#define INIT_VENDOR_SUBSYS_INFO
+
+#include "xf86PciStr.h"
+#include "xf86PciIds.h"
+#include "xf86ScanPci.h"
+
+/*
+ * PCI classes that have messages printed always. The others are only
+ * have a message printed when the vendor/dev IDs are recognised.
+ */
+#define PCIALWAYSPRINTCLASSES(b,s) \
+ (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \
+ ((b) == PCI_CLASS_DISPLAY) || \
+ ((b) == PCI_CLASS_MULTIMEDIA && (s) == PCI_SUBCLASS_MULTIMEDIA_VIDEO))
+
+
+#ifdef XFree86LOADER
+
+#include "xf86Module.h"
+
+#ifdef PCIDATA
+
+static XF86ModuleVersionInfo pciDataVersRec = {
+ "pcidata",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ NULL,
+ {0, 0, 0, 0}
+};
+
+XF86ModuleData pcidataModuleData = { &pciDataVersRec, NULL, NULL };
+
+#else
+
+static XF86ModuleVersionInfo scanPciVersRec = {
+ "scanpci",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ NULL,
+ {0, 0, 0, 0}
+};
+
+XF86ModuleData scanpciModuleData = { &scanPciVersRec, NULL, NULL };
+
+#endif /* PCIDATA */
+
+#endif /* XFree86LOADER */
+
+/* Initialisation/Close hooks, in case they're ever needed. */
+Bool
+ScanPciSetupPciIds(void)
+{
+ return TRUE;
+}
+
+void
+ScanPciClosePciIds(void)
+{
+ return;
+}
+
+/*
+ * The return value is the number of strings found, or -1 for an error.
+ * Requested strings that aren't found are set to NULL.
+ */
+
+int
+ScanPciFindPciNamesByDevice(unsigned short vendor, unsigned short device,
+ unsigned short svendor, unsigned short subsys,
+ const char **vname, const char **dname,
+ const char **svname, const char **sname)
+{
+ int i, j, k;
+ const pciDeviceInfo **pDev;
+ const pciSubsystemInfo **pSub;
+
+ /* It's an error to not provide the Vendor */
+ if (vendor == NOVENDOR)
+ return -1;
+
+ /* Initialise returns requested/provided to NULL */
+ if (vname)
+ *vname = NULL;
+ if (device != NODEVICE && dname)
+ *dname = NULL;
+ if (svendor != NOVENDOR && svname)
+ *svname = NULL;
+ if (subsys != NOSUBSYS && sname)
+ *sname = NULL;
+
+ for (i = 0; pciVendorInfoList[i].VendorName; i++) {
+ if (vendor == pciVendorInfoList[i].VendorID) {
+ if (vname) {
+ *vname = pciVendorInfoList[i].VendorName;
+ }
+ if (device == NODEVICE) {
+ return 1;
+ }
+ pDev = pciVendorInfoList[i].Device;
+ if (!pDev) {
+ return 1;
+ }
+ for (j = 0; pDev[j]; j++) {
+ if (device == pDev[j]->DeviceID) {
+ if (dname) {
+ *dname = pDev[j]->DeviceName;
+ }
+ if (svendor == NOVENDOR) {
+ return 2;
+ }
+ for (k = 0; pciVendorInfoList[k].VendorName; k++) {
+ if (svendor == pciVendorInfoList[k].VendorID) {
+ if (svname) {
+ *svname = pciVendorInfoList[k].VendorName;
+ }
+ if (subsys == NOSUBSYS) {
+ return 3;
+ }
+ break;
+ }
+ }
+ if (!pciVendorInfoList[k].VendorName) {
+ return 2;
+ }
+ pSub = pDev[j]->Subsystem;
+ if (!pSub) {
+ return 3;
+ }
+ for (k = 0; pSub[k]; k++) {
+ if (svendor == pSub[k]->VendorID &&
+ subsys == pSub[k]->SubsystemID) {
+ if (sname)
+ *sname = pSub[k]->SubsystemName;
+ return 4;
+ }
+ }
+ /* No vendor/subsys match */
+ return 3;
+ }
+ }
+ /* No device match */
+ return 1;
+ }
+ }
+ /* No vendor match */
+ return 0;
+}
+
+Bool
+ScanPciFindPciNamesBySubsys(unsigned short svendor, unsigned short subsys,
+ const char **svname, const char **sname)
+{
+ int i, j;
+ const pciSubsystemInfo **pSub;
+
+ /* It's an error to not provide the Vendor */
+ if (svendor == NOVENDOR)
+ return -1;
+
+ /* Initialise returns requested/provided to NULL */
+ if (svname)
+ *svname = NULL;
+ if (subsys != NOSUBSYS && sname)
+ *sname = NULL;
+
+ for (i = 0; pciVendorSubsysInfoList[i].VendorName; i++) {
+ if (svendor == pciVendorSubsysInfoList[i].VendorID) {
+ if (svname) {
+ *svname = pciVendorSubsysInfoList[i].VendorName;
+ }
+ if (subsys == NOSUBSYS) {
+ return 1;
+ }
+ pSub = pciVendorSubsysInfoList[i].Subsystem;
+ if (!pSub) {
+ return 1;
+ }
+ for (j = 0; pSub[j]; j++) {
+ if (subsys == pSub[j]->SubsystemID) {
+ if (sname) {
+ *sname = pSub[j]->SubsystemName;
+ }
+ }
+ }
+ /* No subsys match */
+ return 1;
+ }
+ }
+ /* No vendor match */
+ return 0;
+}
+
+CARD32
+ScanPciFindPciClassBySubsys(unsigned short vendor, unsigned short subsys)
+{
+ int i, j;
+ const pciSubsystemInfo **pSub;
+
+ if (vendor == NOVENDOR || subsys == NOSUBSYS)
+ return 0;
+
+ for (i = 0; pciVendorSubsysInfoList[i].VendorName; i++) {
+ if (vendor == pciVendorSubsysInfoList[i].VendorID) {
+ pSub = pciVendorSubsysInfoList[i].Subsystem;
+ if (!pSub) {
+ return 0;
+ }
+ for (j = 0; pSub[j]; j++) {
+ if (subsys == pSub[j]->SubsystemID) {
+ return pSub[j]->class;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+CARD32
+ScanPciFindPciClassByDevice(unsigned short vendor, unsigned short device)
+{
+ int i, j;
+ const pciDeviceInfo **pDev;
+
+ if (vendor == NOVENDOR || device == NODEVICE)
+ return 0;
+
+ for (i = 0; pciVendorInfoList[i].VendorName; i++) {
+ if (vendor == pciVendorInfoList[i].VendorID) {
+ pDev = pciVendorInfoList[i].Device;
+ if (!pDev) {
+ return 0;
+ }
+ for (j = 0; pDev[j]; j++) {
+ if (device == pDev[j]->DeviceID) {
+ return pDev[j]->class;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+#ifndef PCIDATA
+void
+ScanPciDisplayPCICardInfo(int verbosity)
+{
+ pciConfigPtr pcrp, *pcrpp;
+ int i;
+
+ xf86EnableIO();
+ pcrpp = xf86scanpci(0);
+
+ if (pcrpp == NULL) {
+ xf86MsgVerb(X_NONE,0,"No PCI info available\n");
+ return;
+ }
+ xf86MsgVerb(X_NONE,0,"Probing for PCI devices (Bus:Device:Function)\n\n");
+ for (i = 0; (pcrp = pcrpp[i]); i++) {
+ const char *svendorname = NULL, *subsysname = NULL;
+ const char *vendorname = NULL, *devicename = NULL;
+ Bool noCard = FALSE;
+ const char *prefix1 = "", *prefix2 = "";
+
+ xf86MsgVerb(X_NONE, -verbosity, "(%d:%d:%d) ",
+ pcrp->busnum, pcrp->devnum, pcrp->funcnum);
+
+ /*
+ * Lookup as much as we can about the device.
+ */
+ if (pcrp->pci_subsys_vendor || pcrp->pci_subsys_card) {
+ ScanPciFindPciNamesByDevice(pcrp->pci_vendor, pcrp->pci_device,
+ NOVENDOR, NOSUBSYS,
+ &vendorname, &devicename, NULL, NULL);
+ } else {
+ ScanPciFindPciNamesByDevice(pcrp->pci_vendor, pcrp->pci_device,
+ pcrp->pci_subsys_vendor,
+ pcrp->pci_subsys_card,
+ &vendorname, &devicename,
+ &svendorname, &subsysname);
+ }
+
+ if (svendorname)
+ xf86MsgVerb(X_NONE, -verbosity, "%s ", svendorname);
+ if (subsysname)
+ xf86MsgVerb(X_NONE, -verbosity, "%s ", subsysname);
+ if (svendorname && !subsysname) {
+ if (pcrp->pci_subsys_card && pcrp->pci_subsys_card != NOSUBSYS) {
+ xf86MsgVerb(X_NONE, -verbosity, "unknown card (0x%04x) ",
+ pcrp->pci_subsys_card);
+ } else {
+ xf86MsgVerb(X_NONE, -verbosity, "card ");
+ }
+ }
+ if (!svendorname && !subsysname) {
+ /*
+ * We didn't find a text representation of the information
+ * about the card.
+ */
+ if (pcrp->pci_subsys_vendor || pcrp->pci_subsys_card) {
+ /*
+ * If there was information and we just couldn't interpret
+ * it, print it out as unknown, anyway.
+ */
+ xf86MsgVerb(X_NONE, -verbosity,
+ "unknown card (0x%04x/0x%04x) ",
+ pcrp->pci_subsys_vendor, pcrp->pci_subsys_card);
+ } else
+ noCard = TRUE;
+ }
+ if (!noCard) {
+ prefix1 = "using a ";
+ prefix2 = "using an ";
+ }
+ if (vendorname && devicename) {
+ xf86MsgVerb(X_NONE, -verbosity,"%s%s %s\n", prefix1, vendorname,
+ devicename);
+ } else if (vendorname) {
+ xf86MsgVerb(X_NONE, -verbosity,
+ "%sunknown chip (DeviceId 0x%04x) from %s\n",
+ prefix2, pcrp->pci_device, vendorname);
+ } else {
+ xf86MsgVerb(X_NONE, -verbosity,
+ "%sunknown chipset(0x%04x/0x%04x)\n",
+ prefix2, pcrp->pci_vendor, pcrp->pci_device);
+ }
+ }
+}
+#endif
+