|
Lines 11-85
Link Here
|
| 11 |
#include "xf86.h" |
11 |
#include "xf86.h" |
| 12 |
#include "Pci.h" |
12 |
#include "Pci.h" |
| 13 |
|
13 |
|
| 14 |
/* |
|
|
| 15 |
* get_dev_on_bus - Return the first device we find on segnum, busnum |
| 16 |
* |
| 17 |
* Walk all the PCI devices and return the first one found on segnum, busnum. |
| 18 |
* There may be a better way to do this in some xf86* function I don't know |
| 19 |
* about. |
| 20 |
*/ |
| 21 |
static pciDevice *get_dev_on_bus(unsigned int segnum, unsigned int busnum) |
| 22 |
{ |
| 23 |
pciDevice **pdev = xf86scanpci(0); |
| 24 |
int i; |
| 25 |
|
| 26 |
for (i = 0; pdev[i] != NULL; i++) |
| 27 |
if (PCI_DOM_FROM_TAG(pdev[i]->tag) == segnum && |
| 28 |
pdev[i]->busnum == busnum) |
| 29 |
return pdev[i]; |
| 30 |
/* Should never get here... */ |
| 31 |
ErrorF("No PCI device found on %04x:%02x??", segnum, busnum); |
| 32 |
return NULL; |
| 33 |
} |
| 34 |
|
| 35 |
/* |
| 36 |
* get_bridge_info - fill in the bridge info for bus_info based on pdev |
| 37 |
* |
| 38 |
* Find the parent bus for pdev if it exists, otherwise assume pdev *is* |
| 39 |
* the parent bus. We need this on Altix because our bridges are transparent. |
| 40 |
*/ |
| 41 |
static void get_bridge_info(pciBusInfo_t *bus_info, pciDevice *pdev) |
| 42 |
{ |
| 43 |
unsigned int parent_segnum, segnum = PCI_DOM_FROM_TAG(pdev->tag); |
| 44 |
unsigned int parent_busnum, parent_nodombus, busnum = pdev->busnum; |
| 45 |
unsigned int nodombus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(pdev->tag)); |
| 46 |
char bridge_path[] = "/sys/class/pci_bus/0000:00/bridge"; |
| 47 |
char bridge_target[] = "../../../devices/pci0000:00"; |
| 48 |
|
| 49 |
/* Path to this device's bridge */ |
| 50 |
sprintf(bridge_path, "/sys/class/pci_bus/%04x:%02x/bridge", segnum, |
| 51 |
nodombus); |
| 52 |
|
| 53 |
if (readlink(bridge_path, bridge_target, strlen(bridge_target)) < 0) { |
| 54 |
perror("failed to dereference bridge link"); |
| 55 |
ErrorF("failed to dereference bridge link, aborting\n"); |
| 56 |
exit(-1); |
| 57 |
} |
| 58 |
|
| 59 |
sscanf(bridge_target, "../../../devices/pci%04x:%02x", &parent_segnum, |
| 60 |
&parent_nodombus); |
| 61 |
|
| 62 |
parent_busnum = PCI_MAKE_BUS(parent_segnum, parent_nodombus); |
| 63 |
|
| 64 |
/* |
| 65 |
* If there's no bridge or the bridge points to the device, use |
| 66 |
* pdev as the bridge |
| 67 |
*/ |
| 68 |
if (segnum == parent_segnum && busnum == parent_busnum) { |
| 69 |
bus_info->bridge = pdev; |
| 70 |
bus_info->secondary = FALSE; |
| 71 |
bus_info->primary_bus = busnum; |
| 72 |
} else { |
| 73 |
bus_info->bridge = get_dev_on_bus(parent_segnum, |
| 74 |
parent_busnum); |
| 75 |
bus_info->secondary = TRUE; |
| 76 |
bus_info->primary_bus = parent_busnum; |
| 77 |
} |
| 78 |
pdev->businfo = bus_info; |
| 79 |
pdev->pci_base_class = PCI_CLASS_DISPLAY; |
| 80 |
pdev->pci_sub_class = PCI_SUBCLASS_PREHISTORIC_VGA; |
| 81 |
} |
| 82 |
|
| 83 |
void xf86PreScanAltix(void) |
14 |
void xf86PreScanAltix(void) |
| 84 |
{ |
15 |
{ |
| 85 |
/* Nothing to see here... */ |
16 |
/* Nothing to see here... */ |
|
Lines 88-123
Link Here
|
| 88 |
void xf86PostScanAltix(void) |
19 |
void xf86PostScanAltix(void) |
| 89 |
{ |
20 |
{ |
| 90 |
pciConfigPtr *pdev; |
21 |
pciConfigPtr *pdev; |
| 91 |
pciBusInfo_t *bus_info; |
22 |
int idx, free_idx; |
| 92 |
int prevBusNum, curBusNum, idx; |
|
|
| 93 |
|
23 |
|
| 94 |
/* |
24 |
/* |
| 95 |
* Altix PCI bridges are invisible to userspace, so we make each device |
25 |
* Some altix pci chipsets do not expose themselves as host |
| 96 |
* look like it's its own bridge unless it actually has a parent (as in |
26 |
* bridges. |
| 97 |
* the case of PCI to PCI bridges). |
27 |
* |
|
|
28 |
* Walk the devices looking for buses for which there is not a |
| 29 |
* corresponding pciDevice entry (ie. pciBusInfo[]->bridge is NULL). |
| 30 |
* |
| 31 |
* It is assumed that this indicates a root bridge for which we will |
| 32 |
* construct a fake pci host bridge device. |
| 98 |
*/ |
33 |
*/ |
| 99 |
bus_info = pciBusInfo[0]; |
34 |
|
| 100 |
pdev = xf86scanpci(0); |
35 |
pdev = xf86scanpci(0); |
| 101 |
prevBusNum = curBusNum = pdev[0]->busnum; |
36 |
for (idx = 0; pdev[idx] != NULL; idx++) |
| 102 |
bus_info = pciBusInfo[curBusNum]; |
37 |
; |
| 103 |
bus_info->bridge = pdev[0]; |
|
|
| 104 |
bus_info->secondary = FALSE; |
| 105 |
bus_info->primary_bus = curBusNum; |
| 106 |
|
| 107 |
/* Walk all the PCI devices, assigning their bridge info */ |
| 108 |
for (idx = 0; pdev[idx] != NULL; idx++) { |
| 109 |
if (pdev[idx]->busnum == prevBusNum) |
| 110 |
continue; /* Already fixed up this bus */ |
| 111 |
|
38 |
|
| 112 |
curBusNum = pdev[idx]->busnum; |
39 |
free_idx = idx; |
| 113 |
bus_info = pciBusInfo[curBusNum]; |
40 |
|
|
|
41 |
for (idx = 0; idx < free_idx; idx++) { |
| 42 |
pciConfigPtr dev, fakedev; |
| 43 |
pciBusInfo_t *businfo; |
| 44 |
|
| 45 |
dev = pdev[idx]; |
| 46 |
businfo = pciBusInfo[dev->busnum]; |
| 47 |
|
| 48 |
if (! businfo) { |
| 49 |
/* device has no bus ... should this be an error? */ |
| 50 |
continue; |
| 51 |
} |
| 52 |
|
| 53 |
if (businfo->bridge) { |
| 54 |
/* bus has a device ... no need for fixup */ |
| 55 |
continue; |
| 56 |
} |
| 57 |
|
| 58 |
if (free_idx >= MAX_PCI_DEVICES) |
| 59 |
FatalError("SN: No room for fake root bridge device\n"); |
| 114 |
|
60 |
|
| 115 |
/* |
61 |
/* |
| 116 |
* Fill in bus_info for pdev. The bridge field will either |
62 |
* Construct a fake device and stick it at the end of the |
| 117 |
* be pdev[idx] or a device on the parent bus. |
63 |
* pdev array. Make it look like a host bridge. |
| 118 |
*/ |
64 |
*/ |
| 119 |
get_bridge_info(bus_info, pdev[idx]); |
65 |
fakedev = xnfcalloc(1, sizeof(pciDevice)); |
| 120 |
prevBusNum = curBusNum; |
66 |
fakedev->tag = PCI_MAKE_TAG(dev->busnum, 0, 0);; |
|
|
67 |
fakedev->busnum = dev->busnum; |
| 68 |
fakedev->devnum = 0; |
| 69 |
fakedev->funcnum = 0; |
| 70 |
fakedev->fakeDevice = 1; |
| 71 |
/* should figure out a better DEVID */ |
| 72 |
fakedev->pci_device_vendor = DEVID(VENDOR_GENERIC, CHIP_VGA); |
| 73 |
fakedev->pci_base_class = PCI_CLASS_BRIDGE; |
| 74 |
|
| 75 |
businfo->secondary = 0; |
| 76 |
businfo->primary_bus = dev->busnum; |
| 77 |
businfo->bridge = fakedev; |
| 78 |
|
| 79 |
fakedev->businfo = businfo; |
| 80 |
|
| 81 |
pdev[free_idx++] = fakedev; |
| 121 |
} |
82 |
} |
| 122 |
return; |
|
|
| 123 |
} |
83 |
} |