diff options
author | Adam Jackson <ajax@nwnk.net> | 2005-04-22 17:45:14 +0000 |
---|---|---|
committer | Adam Jackson <ajax@nwnk.net> | 2005-04-22 17:45:14 +0000 |
commit | d450a70e00b50427ecb2065d3cc44f43d102cade (patch) | |
tree | 24bdaf1be787ceb6b3f1c092ce39e00ec1a87d72 | |
parent | 16c2499b8f5c2405e36c7d5a922bb0b150df1762 (diff) |
Bug #2373: SGI Altix platform support. (Shrijeet Mukherjee, Jesse Barnes,
Bjorn Helgaas, Egbert Eich.)
-rw-r--r-- | hw/xfree86/os-support/bus/altixPCI.c | 116 | ||||
-rw-r--r-- | hw/xfree86/os-support/bus/altixPCI.h | 16 |
2 files changed, 132 insertions, 0 deletions
diff --git a/hw/xfree86/os-support/bus/altixPCI.c b/hw/xfree86/os-support/bus/altixPCI.c new file mode 100644 index 000000000..c2c21d39f --- /dev/null +++ b/hw/xfree86/os-support/bus/altixPCI.c @@ -0,0 +1,116 @@ +/* + * This file contains the glue necessary for support of SGI's Altix chipset. + */ +#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; +} diff --git a/hw/xfree86/os-support/bus/altixPCI.h b/hw/xfree86/os-support/bus/altixPCI.h new file mode 100644 index 000000000..1d449d55b --- /dev/null +++ b/hw/xfree86/os-support/bus/altixPCI.h @@ -0,0 +1,16 @@ +#ifndef PCI_ALTIX_H +#define PCI_ALTIX_H 1 + +#include <X11/Xdefs.h> +#include <Pci.h> + +Bool xorgProbeAltix(scanpciWrapperOpt flags); +void xf86PreScanAltix(void); +void xf86PostScanAltix(void); + +/* Some defines for PCI */ +#define VENDOR_SGI 0x10A9 +#define CHIP_TIO_CA 0x1010 +#define CHIP_PIC_PCI 0x1011 + +#endif |