aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c')
-rw-r--r--nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c
new file mode 100644
index 000000000..010f6619a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/bus/altixPCI.c
@@ -0,0 +1,120 @@
+/*
+ * This file contains the glue necessary for support of SGI's Altix chipset.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include "altixPCI.h"
+#include "xf86.h"
+#include "Pci.h"
+
+/*
+ * get_dev_on_bus - Return the first device we find on segnum, busnum
+ *
+ * Walk all the PCI devices and return the first one found on segnum, busnum.
+ * There may be a better way to do this in some xf86* function I don't know
+ * about.
+ */
+static pciDevice *get_dev_on_bus(unsigned int segnum, unsigned int busnum)
+{
+ pciDevice **pdev = xf86scanpci(0);
+ int i;
+
+ for (i = 0; pdev[i] != NULL; i++)
+ if (PCI_DOM_FROM_TAG(pdev[i]->tag) == segnum &&
+ pdev[i]->busnum == busnum)
+ return pdev[i];
+ /* Should never get here... */
+ ErrorF("No PCI device found on %04x:%02x??", segnum, busnum);
+ return NULL;
+}
+
+/*
+ * get_bridge_info - fill in the bridge info for bus_info based on pdev
+ *
+ * Find the parent bus for pdev if it exists, otherwise assume pdev *is*
+ * the parent bus. We need this on Altix because our bridges are transparent.
+ */
+static void get_bridge_info(pciBusInfo_t *bus_info, pciDevice *pdev)
+{
+ unsigned int parent_segnum, segnum = PCI_DOM_FROM_TAG(pdev->tag);
+ unsigned int parent_busnum, busnum = pdev->busnum;
+ char bridge_path[] = "/sys/class/pci_bus/0000:00/bridge";
+ char bridge_target[] = "../../../devices/pci0000:00";
+
+ /* Path to this device's bridge */
+ sprintf(bridge_path, "/sys/class/pci_bus/%04x:%02x/bridge", segnum,
+ busnum);
+
+ if (readlink(bridge_path, bridge_target, strlen(bridge_target)) < 0) {
+ perror("failed to dereference bridge link");
+ ErrorF("failed to dereference bridge link, aborting\n");
+ exit(-1);
+ }
+
+ sscanf(bridge_target, "../../../devices/pci%04x:%02x", &parent_segnum,
+ &parent_busnum);
+
+ /*
+ * If there's no bridge or the bridge points to the device, use
+ * pdev as the bridge
+ */
+ if (segnum == parent_segnum && busnum == parent_busnum) {
+ bus_info->bridge = pdev;
+ bus_info->secondary = FALSE;
+ bus_info->primary_bus = busnum;
+ } else {
+ bus_info->bridge = get_dev_on_bus(parent_segnum,
+ parent_busnum);
+ bus_info->secondary = TRUE;
+ bus_info->primary_bus = parent_busnum;
+ }
+ pdev->businfo = bus_info;
+ pdev->pci_base_class = PCI_CLASS_DISPLAY;
+ pdev->pci_sub_class = PCI_SUBCLASS_PREHISTORIC_VGA;
+}
+
+void xf86PreScanAltix(void)
+{
+ /* Nothing to see here... */
+}
+
+void xf86PostScanAltix(void)
+{
+ pciConfigPtr *pdev;
+ pciBusInfo_t *bus_info;
+ int prevBusNum, curBusNum, idx;
+
+ /*
+ * Altix PCI bridges are invisible to userspace, so we make each device
+ * look like it's its own bridge unless it actually has a parent (as in
+ * the case of PCI to PCI bridges).
+ */
+ bus_info = pciBusInfo[0];
+ pdev = xf86scanpci(0);
+ prevBusNum = curBusNum = pdev[0]->busnum;
+ bus_info = pciBusInfo[curBusNum];
+ bus_info->bridge = pdev[0];
+ bus_info->secondary = FALSE;
+ bus_info->primary_bus = curBusNum;
+
+ /* Walk all the PCI devices, assigning their bridge info */
+ for (idx = 0; pdev[idx] != NULL; idx++) {
+ if (pdev[idx]->busnum == prevBusNum)
+ continue; /* Already fixed up this bus */
+
+ curBusNum = pdev[idx]->busnum;
+ bus_info = pciBusInfo[curBusNum];
+
+ /*
+ * Fill in bus_info for pdev. The bridge field will either
+ * be pdev[idx] or a device on the parent bus.
+ */
+ get_bridge_info(bus_info, pdev[idx]);
+ prevBusNum = curBusNum;
+ }
+ return;
+}