105b261ecSmrg/* 205b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 305b261ecSmrg * 405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 505b261ecSmrg * copy of this software and associated documentation files (the "Software"), 605b261ecSmrg * to deal in the Software without restriction, including without limitation 705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 905b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1005b261ecSmrg * 1105b261ecSmrg * The above copyright notice and this permission notice shall be included in 1205b261ecSmrg * all copies or substantial portions of the Software. 1305b261ecSmrg * 1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1705b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1805b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1905b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2005b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 2105b261ecSmrg * 2205b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 2305b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 2405b261ecSmrg * the sale, use or other dealings in this Software without prior written 2505b261ecSmrg * authorization from the copyright holder(s) and author(s). 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg/* 2905b261ecSmrg * This file contains the interfaces to the bus-specific code 3005b261ecSmrg */ 3105b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 3205b261ecSmrg#include <xorg-config.h> 3305b261ecSmrg#endif 3405b261ecSmrg 3505b261ecSmrg#include <ctype.h> 3605b261ecSmrg#include <stdlib.h> 3705b261ecSmrg#include <unistd.h> 3805b261ecSmrg#include <X11/X.h> 394642e01fSmrg#include <pciaccess.h> 4005b261ecSmrg#include "os.h" 4105b261ecSmrg#include "Pci.h" 4205b261ecSmrg#include "xf86.h" 4305b261ecSmrg#include "xf86Priv.h" 44f7df2e56Smrg#include "dirent.h" /* DIR, FILE type definitions */ 4505b261ecSmrg 4605b261ecSmrg/* Bus-specific headers */ 4705b261ecSmrg#include "xf86Bus.h" 4805b261ecSmrg 4905b261ecSmrg#define XF86_OS_PRIVS 5005b261ecSmrg#include "xf86_OSproc.h" 5105b261ecSmrg 52f7df2e56Smrg#define PCI_VENDOR_GENERIC 0x00FF 5305b261ecSmrg 5405b261ecSmrg/* Bus-specific globals */ 55f7df2e56Smrgint pciSlotClaimed = 0; 5605b261ecSmrg 574642e01fSmrg#define PCIINFOCLASSES(c) \ 584642e01fSmrg ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ 594642e01fSmrg || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 604642e01fSmrg || ((((c) & 0x00ffff00) \ 614642e01fSmrg == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ 624642e01fSmrg || ((((c) & 0x00ffff00) \ 634642e01fSmrg == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) 6405b261ecSmrg 6505b261ecSmrg/* 6605b261ecSmrg * PCI classes that have messages printed always. The others are only 6705b261ecSmrg * have a message printed when the vendor/dev IDs are recognised. 6805b261ecSmrg */ 694642e01fSmrg#define PCIALWAYSPRINTCLASSES(c) \ 704642e01fSmrg ( (((c) & 0x00ffff00) \ 714642e01fSmrg == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ 724642e01fSmrg || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 734642e01fSmrg || ((((c) & 0x00ffff00) \ 744642e01fSmrg == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) 754642e01fSmrg 764642e01fSmrg#define IS_VGA(c) \ 774642e01fSmrg (((c) & 0x00ffff00) \ 784642e01fSmrg == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) 794642e01fSmrg 809ace9065Smrgstatic struct pci_slot_match xf86IsolateDevice = { 819ace9065Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0 829ace9065Smrg}; 839ace9065Smrg 844642e01fSmrg/* 854642e01fSmrg * xf86Bus.c interface 864642e01fSmrg */ 8705b261ecSmrg 884642e01fSmrgvoid 894642e01fSmrgxf86PciProbe(void) 9005b261ecSmrg{ 914642e01fSmrg int i = 0, k; 924642e01fSmrg int num = 0; 934642e01fSmrg struct pci_device *info; 944642e01fSmrg struct pci_device_iterator *iter; 95f7df2e56Smrg struct pci_device **xf86PciVideoInfo = NULL; 9605b261ecSmrg 974642e01fSmrg if (!xf86scanpci()) { 98f7df2e56Smrg xf86PciVideoInfo = NULL; 99f7df2e56Smrg return; 10005b261ecSmrg } 10105b261ecSmrg 102f7df2e56Smrg iter = pci_slot_match_iterator_create(&xf86IsolateDevice); 1034642e01fSmrg while ((info = pci_device_next(iter)) != NULL) { 104f7df2e56Smrg if (PCIINFOCLASSES(info->device_class)) { 105f7df2e56Smrg num++; 106f7df2e56Smrg xf86PciVideoInfo = xnfreallocarray(xf86PciVideoInfo, 107f7df2e56Smrg num + 1, 108f7df2e56Smrg sizeof(struct pci_device *)); 109f7df2e56Smrg xf86PciVideoInfo[num] = NULL; 110f7df2e56Smrg xf86PciVideoInfo[num - 1] = info; 111f7df2e56Smrg 112f7df2e56Smrg pci_device_probe(info); 113f7df2e56Smrg if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) { 1146747b715Smrg primaryBus.type = BUS_PCI; 1156747b715Smrg primaryBus.id.pci = info; 1166747b715Smrg } 117f7df2e56Smrg info->user_data = 0; 118f7df2e56Smrg } 11905b261ecSmrg } 1206747b715Smrg free(iter); 12105b261ecSmrg 1224642e01fSmrg /* If we haven't found a primary device try a different heuristic */ 1234642e01fSmrg if (primaryBus.type == BUS_NONE && num) { 124f7df2e56Smrg for (i = 0; i < num; i++) { 125f7df2e56Smrg uint16_t command; 126f7df2e56Smrg 127f7df2e56Smrg info = xf86PciVideoInfo[i]; 128f7df2e56Smrg pci_device_cfg_read_u16(info, &command, 4); 129f7df2e56Smrg 130f7df2e56Smrg if ((command & PCI_CMD_MEM_ENABLE) 131f7df2e56Smrg && ((num == 1) || IS_VGA(info->device_class))) { 132f7df2e56Smrg if (primaryBus.type == BUS_NONE) { 133f7df2e56Smrg primaryBus.type = BUS_PCI; 134f7df2e56Smrg primaryBus.id.pci = info; 135f7df2e56Smrg } 136f7df2e56Smrg else { 137f7df2e56Smrg xf86Msg(X_NOTICE, 138f7df2e56Smrg "More than one possible primary device found\n"); 139f7df2e56Smrg primaryBus.type ^= (BusType) (-1); 140f7df2e56Smrg } 141f7df2e56Smrg } 142f7df2e56Smrg } 1434642e01fSmrg } 144f7df2e56Smrg 1454642e01fSmrg /* Print a summary of the video devices found */ 1464642e01fSmrg for (k = 0; k < num; k++) { 147f7df2e56Smrg const char *prim = " "; 148f7df2e56Smrg Bool memdone = FALSE, iodone = FALSE; 14905b261ecSmrg 150f7df2e56Smrg info = xf86PciVideoInfo[k]; 15105b261ecSmrg 152f7df2e56Smrg if (!PCIALWAYSPRINTCLASSES(info->device_class)) 153f7df2e56Smrg continue; 15405b261ecSmrg 155f7df2e56Smrg if (xf86IsPrimaryPci(info)) 156f7df2e56Smrg prim = "*"; 1574642e01fSmrg 1587e31ba66Smrg xf86Msg(X_PROBED, "PCI:%s(%u@%u:%u:%u) %04x:%04x:%04x:%04x ", prim, 1597e31ba66Smrg info->bus, info->domain, info->dev, info->func, 160f7df2e56Smrg info->vendor_id, info->device_id, 161f7df2e56Smrg info->subvendor_id, info->subdevice_id); 1624642e01fSmrg 163f7df2e56Smrg xf86ErrorF("rev %d", info->revision); 1644642e01fSmrg 165f7df2e56Smrg for (i = 0; i < 6; i++) { 166f7df2e56Smrg struct pci_mem_region *r = &info->regions[i]; 16705b261ecSmrg 168f7df2e56Smrg if (r->size && !r->is_IO) { 169f7df2e56Smrg if (!memdone) { 170f7df2e56Smrg xf86ErrorF(", Mem @ "); 171f7df2e56Smrg memdone = TRUE; 172f7df2e56Smrg } 173f7df2e56Smrg else 174f7df2e56Smrg xf86ErrorF(", "); 175f7df2e56Smrg xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size); 176f7df2e56Smrg } 177f7df2e56Smrg } 17805b261ecSmrg 179f7df2e56Smrg for (i = 0; i < 6; i++) { 180f7df2e56Smrg struct pci_mem_region *r = &info->regions[i]; 18105b261ecSmrg 182f7df2e56Smrg if (r->size && r->is_IO) { 183f7df2e56Smrg if (!iodone) { 184f7df2e56Smrg xf86ErrorF(", I/O @ "); 185f7df2e56Smrg iodone = TRUE; 186f7df2e56Smrg } 187f7df2e56Smrg else 188f7df2e56Smrg xf86ErrorF(", "); 189f7df2e56Smrg xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size); 190f7df2e56Smrg } 191f7df2e56Smrg } 1924642e01fSmrg 193f7df2e56Smrg if (info->rom_size) { 194f7df2e56Smrg xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", 195f7df2e56Smrg (long) info->rom_size); 196f7df2e56Smrg } 1974642e01fSmrg 198f7df2e56Smrg xf86ErrorF("\n"); 19905b261ecSmrg } 2006747b715Smrg free(xf86PciVideoInfo); 20105b261ecSmrg} 20205b261ecSmrg 20305b261ecSmrg/* 20405b261ecSmrg * If the slot requested is already in use, return -1. 20505b261ecSmrg * Otherwise, claim the slot for the screen requesting it. 20605b261ecSmrg */ 20705b261ecSmrg 2086747b715Smrgint 209f7df2e56Smrgxf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp, 210f7df2e56Smrg int chipset, GDevPtr dev, Bool active) 21105b261ecSmrg{ 21205b261ecSmrg EntityPtr p = NULL; 21305b261ecSmrg int num; 214f7df2e56Smrg 2154642e01fSmrg if (xf86CheckPciSlot(d)) { 216f7df2e56Smrg num = xf86AllocateEntity(); 217f7df2e56Smrg p = xf86Entities[num]; 218f7df2e56Smrg p->driver = drvp; 219f7df2e56Smrg p->chipset = chipset; 220f7df2e56Smrg p->bus.type = BUS_PCI; 221f7df2e56Smrg p->bus.id.pci = d; 222f7df2e56Smrg p->active = active; 223f7df2e56Smrg p->inUse = FALSE; 224f7df2e56Smrg if (dev) 22505b261ecSmrg xf86AddDevToEntity(num, dev); 226f7df2e56Smrg pciSlotClaimed++; 227f7df2e56Smrg 228f7df2e56Smrg return num; 229f7df2e56Smrg } 230f7df2e56Smrg else 231f7df2e56Smrg return -1; 23205b261ecSmrg} 23305b261ecSmrg 2346747b715Smrg/* 2356747b715Smrg * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim. 2366747b715Smrg */ 2376747b715Smrgvoid 238f7df2e56Smrgxf86UnclaimPciSlot(struct pci_device *d, GDevPtr dev) 2396747b715Smrg{ 2406747b715Smrg int i; 2416747b715Smrg 2426747b715Smrg for (i = 0; i < xf86NumEntities; i++) { 243f7df2e56Smrg const EntityPtr p = xf86Entities[i]; 244f7df2e56Smrg 245f7df2e56Smrg if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { 246f7df2e56Smrg /* Probably the slot should be deallocated? */ 247f7df2e56Smrg xf86RemoveDevFromEntity(i, dev); 248f7df2e56Smrg pciSlotClaimed--; 249f7df2e56Smrg p->bus.type = BUS_NONE; 250f7df2e56Smrg return; 251f7df2e56Smrg } 2526747b715Smrg } 2536747b715Smrg} 2546747b715Smrg 25505b261ecSmrg/* 25605b261ecSmrg * Parse a BUS ID string, and return the PCI bus parameters if it was 25705b261ecSmrg * in the correct format for a PCI bus id. 25805b261ecSmrg */ 25905b261ecSmrg 2606747b715SmrgBool 26105b261ecSmrgxf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) 26205b261ecSmrg{ 26305b261ecSmrg /* 26405b261ecSmrg * The format is assumed to be "bus[@domain]:device[:func]", where domain, 26505b261ecSmrg * bus, device and func are decimal integers. domain and func may be 26605b261ecSmrg * omitted and assumed to be zero, although doing this isn't encouraged. 26705b261ecSmrg */ 26805b261ecSmrg 26905b261ecSmrg char *p, *s, *d; 27005b261ecSmrg const char *id; 27105b261ecSmrg int i; 27205b261ecSmrg 27305b261ecSmrg if (StringToBusType(busID, &id) != BUS_PCI) 274f7df2e56Smrg return FALSE; 27505b261ecSmrg 27605b261ecSmrg s = xstrdup(id); 27705b261ecSmrg p = strtok(s, ":"); 27805b261ecSmrg if (p == NULL || *p == 0) { 279f7df2e56Smrg free(s); 280f7df2e56Smrg return FALSE; 28105b261ecSmrg } 28205b261ecSmrg d = strpbrk(p, "@"); 28305b261ecSmrg if (d != NULL) { 284f7df2e56Smrg *(d++) = 0; 285f7df2e56Smrg for (i = 0; d[i] != 0; i++) { 286f7df2e56Smrg if (!isdigit(d[i])) { 287f7df2e56Smrg free(s); 288f7df2e56Smrg return FALSE; 289f7df2e56Smrg } 290f7df2e56Smrg } 29105b261ecSmrg } 29205b261ecSmrg for (i = 0; p[i] != 0; i++) { 293f7df2e56Smrg if (!isdigit(p[i])) { 294f7df2e56Smrg free(s); 295f7df2e56Smrg return FALSE; 296f7df2e56Smrg } 29705b261ecSmrg } 29805b261ecSmrg *bus = atoi(p); 29905b261ecSmrg if (d != NULL && *d != 0) 300f7df2e56Smrg *bus += atoi(d) << 8; 30105b261ecSmrg p = strtok(NULL, ":"); 30205b261ecSmrg if (p == NULL || *p == 0) { 303f7df2e56Smrg free(s); 304f7df2e56Smrg return FALSE; 30505b261ecSmrg } 30605b261ecSmrg for (i = 0; p[i] != 0; i++) { 307f7df2e56Smrg if (!isdigit(p[i])) { 308f7df2e56Smrg free(s); 309f7df2e56Smrg return FALSE; 310f7df2e56Smrg } 31105b261ecSmrg } 31205b261ecSmrg *device = atoi(p); 31305b261ecSmrg *func = 0; 31405b261ecSmrg p = strtok(NULL, ":"); 31505b261ecSmrg if (p == NULL || *p == 0) { 316f7df2e56Smrg free(s); 317f7df2e56Smrg return TRUE; 31805b261ecSmrg } 31905b261ecSmrg for (i = 0; p[i] != 0; i++) { 320f7df2e56Smrg if (!isdigit(p[i])) { 321f7df2e56Smrg free(s); 322f7df2e56Smrg return FALSE; 323f7df2e56Smrg } 32405b261ecSmrg } 32505b261ecSmrg *func = atoi(p); 3266747b715Smrg free(s); 32705b261ecSmrg return TRUE; 32805b261ecSmrg} 32905b261ecSmrg 33005b261ecSmrg/* 33105b261ecSmrg * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. 33205b261ecSmrg */ 33305b261ecSmrg 3346747b715SmrgBool 33505b261ecSmrgxf86ComparePciBusString(const char *busID, int bus, int device, int func) 33605b261ecSmrg{ 33705b261ecSmrg int ibus, idevice, ifunc; 33805b261ecSmrg 33905b261ecSmrg if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { 340f7df2e56Smrg return bus == ibus && device == idevice && func == ifunc; 341f7df2e56Smrg } 342f7df2e56Smrg else { 343f7df2e56Smrg return FALSE; 34405b261ecSmrg } 34505b261ecSmrg} 34605b261ecSmrg 34705b261ecSmrg/* 34805b261ecSmrg * xf86IsPrimaryPci() -- return TRUE if primary device 34905b261ecSmrg * is PCI and bus, dev and func numbers match. 35005b261ecSmrg */ 351f7df2e56Smrg 3526747b715SmrgBool 3534642e01fSmrgxf86IsPrimaryPci(struct pci_device *pPci) 35405b261ecSmrg{ 3557e31ba66Smrg /* Add max. 1 screen for the IgnorePrimary fallback path */ 3567e31ba66Smrg if (xf86ProbeIgnorePrimary && xf86NumScreens == 0) 3577e31ba66Smrg return TRUE; 3587e31ba66Smrg 359f7df2e56Smrg if (primaryBus.type == BUS_PCI) 360f7df2e56Smrg return pPci == primaryBus.id.pci; 361f7df2e56Smrg#ifdef XSERVER_PLATFORM_BUS 362f7df2e56Smrg if (primaryBus.type == BUS_PLATFORM) 363f7df2e56Smrg if (primaryBus.id.plat->pdev) 364f7df2e56Smrg if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci)) 365f7df2e56Smrg return TRUE; 366f7df2e56Smrg#endif 367f7df2e56Smrg return FALSE; 36805b261ecSmrg} 36905b261ecSmrg 37005b261ecSmrg/* 37105b261ecSmrg * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. 37205b261ecSmrg */ 3736747b715Smrgstruct pci_device * 37405b261ecSmrgxf86GetPciInfoForEntity(int entityIndex) 37505b261ecSmrg{ 37605b261ecSmrg EntityPtr p; 377f7df2e56Smrg 37805b261ecSmrg if (entityIndex >= xf86NumEntities) 379f7df2e56Smrg return NULL; 38005b261ecSmrg 38105b261ecSmrg p = xf86Entities[entityIndex]; 382f7df2e56Smrg switch (p->bus.type) { 383f7df2e56Smrg case BUS_PCI: 384f7df2e56Smrg return p->bus.id.pci; 385f7df2e56Smrg case BUS_PLATFORM: 386f7df2e56Smrg return p->bus.id.plat->pdev; 387f7df2e56Smrg default: 388f7df2e56Smrg break; 389f7df2e56Smrg } 390f7df2e56Smrg return NULL; 39105b261ecSmrg} 39205b261ecSmrg 39305b261ecSmrg/* 39405b261ecSmrg * xf86CheckPciMemBase() checks that the memory base value matches one of the 39505b261ecSmrg * PCI base address register values for the given PCI device. 39605b261ecSmrg */ 3976747b715SmrgBool 398f7df2e56Smrgxf86CheckPciMemBase(struct pci_device *pPci, memType base) 39905b261ecSmrg{ 40005b261ecSmrg int i; 40105b261ecSmrg 40205b261ecSmrg for (i = 0; i < 6; i++) 403f7df2e56Smrg if (base == pPci->regions[i].base_addr) 404f7df2e56Smrg return TRUE; 40505b261ecSmrg return FALSE; 40605b261ecSmrg} 40705b261ecSmrg 40805b261ecSmrg/* 40905b261ecSmrg * Check if the slot requested is free. If it is already in use, return FALSE. 41005b261ecSmrg */ 41105b261ecSmrg 4126747b715SmrgBool 4134642e01fSmrgxf86CheckPciSlot(const struct pci_device *d) 41405b261ecSmrg{ 41505b261ecSmrg int i; 41605b261ecSmrg 41705b261ecSmrg for (i = 0; i < xf86NumEntities; i++) { 418f7df2e56Smrg const EntityPtr p = xf86Entities[i]; 41905b261ecSmrg 420f7df2e56Smrg if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { 421f7df2e56Smrg return FALSE; 422f7df2e56Smrg } 423f7df2e56Smrg#ifdef XSERVER_PLATFORM_BUS 424f7df2e56Smrg if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) { 425f7df2e56Smrg struct pci_device *ud = p->bus.id.plat->pdev; 426f7df2e56Smrg if (MATCH_PCI_DEVICES(ud, d)) 427f7df2e56Smrg return FALSE; 428f7df2e56Smrg } 429f7df2e56Smrg#endif 43005b261ecSmrg } 4314642e01fSmrg return TRUE; 43205b261ecSmrg} 43305b261ecSmrg 4346747b715Smrg#define END_OF_MATCHES(m) \ 4356747b715Smrg (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) 4366747b715Smrg 4376747b715SmrgBool 4386747b715Smrgxf86PciAddMatchingDev(DriverPtr drvp) 4396747b715Smrg{ 440f7df2e56Smrg const struct pci_id_match *const devices = drvp->supported_devices; 4416747b715Smrg int j; 4426747b715Smrg struct pci_device *pPci; 4436747b715Smrg struct pci_device_iterator *iter; 4446747b715Smrg int numFound = 0; 4456747b715Smrg 4466747b715Smrg iter = pci_id_match_iterator_create(NULL); 4476747b715Smrg while ((pPci = pci_device_next(iter)) != NULL) { 448f7df2e56Smrg /* Determine if this device is supported by the driver. If it is, 449f7df2e56Smrg * add it to the list of devices to configure. 450f7df2e56Smrg */ 451f7df2e56Smrg for (j = 0; !END_OF_MATCHES(devices[j]); j++) { 452f7df2e56Smrg if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id) 453f7df2e56Smrg && PCI_ID_COMPARE(devices[j].device_id, pPci->device_id) 454f7df2e56Smrg && ((devices[j].device_class_mask & pPci->device_class) 455f7df2e56Smrg == devices[j].device_class)) { 456f7df2e56Smrg if (xf86CheckPciSlot(pPci)) { 457f7df2e56Smrg GDevPtr pGDev = 458f7df2e56Smrg xf86AddBusDeviceToConfigure(drvp->driverName, BUS_PCI, 459f7df2e56Smrg pPci, -1); 460f7df2e56Smrg if (pGDev != NULL) { 461f7df2e56Smrg /* After configure pass 1, chipID and chipRev are 462f7df2e56Smrg * treated as over-rides, so clobber them here. 463f7df2e56Smrg */ 464f7df2e56Smrg pGDev->chipID = -1; 465f7df2e56Smrg pGDev->chipRev = -1; 466f7df2e56Smrg } 4676747b715Smrg 468f7df2e56Smrg numFound++; 469f7df2e56Smrg } 4706747b715Smrg 471f7df2e56Smrg break; 472f7df2e56Smrg } 4736747b715Smrg } 4746747b715Smrg } 4756747b715Smrg 4766747b715Smrg pci_iterator_destroy(iter); 4776747b715Smrg 4786747b715Smrg return numFound != 0; 4796747b715Smrg} 4806747b715Smrg 4816747b715SmrgBool 4826747b715Smrgxf86PciProbeDev(DriverPtr drvp) 4836747b715Smrg{ 4846747b715Smrg int i, j; 485f7df2e56Smrg struct pci_device *pPci; 4866747b715Smrg Bool foundScreen = FALSE; 487f7df2e56Smrg const struct pci_id_match *const devices = drvp->supported_devices; 4886747b715Smrg GDevPtr *devList; 489f7df2e56Smrg const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList); 490f7df2e56Smrg 491f7df2e56Smrg for (i = 0; i < numDevs; i++) { 492f7df2e56Smrg struct pci_device_iterator *iter; 493f7df2e56Smrg unsigned device_id; 494f7df2e56Smrg 495f7df2e56Smrg /* Find the pciVideoRec associated with this device section. 496f7df2e56Smrg */ 497f7df2e56Smrg iter = pci_id_match_iterator_create(NULL); 498f7df2e56Smrg while ((pPci = pci_device_next(iter)) != NULL) { 499f7df2e56Smrg if (devList[i]->busID && *devList[i]->busID) { 500f7df2e56Smrg if (xf86ComparePciBusString(devList[i]->busID, 501f7df2e56Smrg ((pPci->domain << 8) 502f7df2e56Smrg | pPci->bus), 503f7df2e56Smrg pPci->dev, pPci->func)) { 504f7df2e56Smrg break; 505f7df2e56Smrg } 506f7df2e56Smrg } 507f7df2e56Smrg else if (xf86IsPrimaryPci(pPci)) { 508f7df2e56Smrg break; 509f7df2e56Smrg } 510f7df2e56Smrg } 511f7df2e56Smrg 512f7df2e56Smrg pci_iterator_destroy(iter); 513f7df2e56Smrg 514f7df2e56Smrg if (pPci == NULL) { 515f7df2e56Smrg continue; 516f7df2e56Smrg } 517f7df2e56Smrg device_id = (devList[i]->chipID > 0) 518f7df2e56Smrg ? devList[i]->chipID : pPci->device_id; 519f7df2e56Smrg 520f7df2e56Smrg /* Once the pciVideoRec is found, determine if the device is supported 521f7df2e56Smrg * by the driver. If it is, probe it! 522f7df2e56Smrg */ 523f7df2e56Smrg for (j = 0; !END_OF_MATCHES(devices[j]); j++) { 524f7df2e56Smrg if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id) 525f7df2e56Smrg && PCI_ID_COMPARE(devices[j].device_id, device_id) 5266747b715Smrg && ((devices[j].device_class_mask & pPci->device_class) 527f7df2e56Smrg == devices[j].device_class)) { 528f7df2e56Smrg int entry; 529f7df2e56Smrg 530f7df2e56Smrg /* Allow the same entity to be used more than once for 531f7df2e56Smrg * devices with multiple screens per entity. This assumes 532f7df2e56Smrg * implicitly that there will be a screen == 0 instance. 533f7df2e56Smrg * 534f7df2e56Smrg * FIXME Need to make sure that two different drivers don't 535f7df2e56Smrg * FIXME claim the same screen > 0 instance. 536f7df2e56Smrg */ 537f7df2e56Smrg if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci)) 538f7df2e56Smrg continue; 539f7df2e56Smrg 540f7df2e56Smrg DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", 541f7df2e56Smrg drvp->driverName, pPci->bus, pPci->dev, pPci->func); 542f7df2e56Smrg 543f7df2e56Smrg /* Allocate an entry in the lists to be returned */ 544f7df2e56Smrg entry = xf86ClaimPciSlot(pPci, drvp, device_id, 5456747b715Smrg devList[i], devList[i]->active); 5466747b715Smrg 547f7df2e56Smrg if ((entry == -1) && (devList[i]->screen > 0)) { 548f7df2e56Smrg unsigned k; 549f7df2e56Smrg 550f7df2e56Smrg for (k = 0; k < xf86NumEntities; k++) { 551f7df2e56Smrg EntityPtr pEnt = xf86Entities[k]; 552f7df2e56Smrg 553f7df2e56Smrg if (pEnt->bus.type != BUS_PCI) 554f7df2e56Smrg continue; 555f7df2e56Smrg if (pEnt->bus.id.pci == pPci) { 556f7df2e56Smrg entry = k; 557f7df2e56Smrg xf86AddDevToEntity(k, devList[i]); 558f7df2e56Smrg break; 559f7df2e56Smrg } 560f7df2e56Smrg } 561f7df2e56Smrg } 562f7df2e56Smrg 563f7df2e56Smrg if (entry != -1) { 564f7df2e56Smrg if ((*drvp->PciProbe) (drvp, entry, pPci, 565f7df2e56Smrg devices[j].match_data)) { 566f7df2e56Smrg foundScreen = TRUE; 567f7df2e56Smrg } 568f7df2e56Smrg else 569f7df2e56Smrg xf86UnclaimPciSlot(pPci, devList[i]); 570f7df2e56Smrg } 571f7df2e56Smrg 572f7df2e56Smrg break; 573f7df2e56Smrg } 574f7df2e56Smrg } 5756747b715Smrg } 5766747b715Smrg free(devList); 5776747b715Smrg 5786747b715Smrg return foundScreen; 5796747b715Smrg} 58005b261ecSmrg 5814642e01fSmrgvoid 582f7df2e56Smrgxf86PciIsolateDevice(const char *argument) 58305b261ecSmrg{ 5846747b715Smrg int bus, device, func; 58505b261ecSmrg 5866747b715Smrg if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { 5876747b715Smrg xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); 5886747b715Smrg xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); 5896747b715Smrg xf86IsolateDevice.dev = device; 5906747b715Smrg xf86IsolateDevice.func = func; 591f7df2e56Smrg } 592f7df2e56Smrg else 5936747b715Smrg FatalError("Invalid isolated device specification\n"); 5946747b715Smrg} 5956747b715Smrg 5966747b715Smrgstatic Bool 5976747b715SmrgpciDeviceHasBars(struct pci_device *pci) 5986747b715Smrg{ 5996747b715Smrg int i; 6006747b715Smrg 6016747b715Smrg for (i = 0; i < 6; i++) 602f7df2e56Smrg if (pci->regions[i].size) 603f7df2e56Smrg return TRUE; 6046747b715Smrg 6056747b715Smrg if (pci->rom_size) 606f7df2e56Smrg return TRUE; 6076747b715Smrg 6086747b715Smrg return FALSE; 6096747b715Smrg} 6106747b715Smrg 6116747b715Smrgstruct Inst { 612f7df2e56Smrg struct pci_device *pci; 613f7df2e56Smrg GDevPtr dev; 614f7df2e56Smrg Bool foundHW; /* PCIid in list of supported chipsets */ 615f7df2e56Smrg Bool claimed; /* BusID matches with a device section */ 616f7df2e56Smrg int chip; 617f7df2e56Smrg int screen; 6186747b715Smrg}; 6196747b715Smrg 6206747b715Smrg/** 6216747b715Smrg * Find set of unclaimed devices matching a given vendor ID. 6226747b715Smrg * 6236747b715Smrg * Used by drivers to find as yet unclaimed devices matching the specified 6246747b715Smrg * vendor ID. 6256747b715Smrg * 6266747b715Smrg * \param driverName Name of the driver. This is used to find Device 6276747b715Smrg * sections in the config file. 6286747b715Smrg * \param vendorID PCI vendor ID of associated devices. If zero, then 6296747b715Smrg * the true vendor ID must be encoded in the \c PCIid 6306747b715Smrg * fields of the \c PCIchipsets entries. 6316747b715Smrg * \param chipsets Symbol table used to associate chipset names with 6326747b715Smrg * PCI IDs. 6336747b715Smrg * \param devList List of Device sections parsed from the config file. 6346747b715Smrg * \param numDevs Number of entries in \c devList. 6356747b715Smrg * \param drvp Pointer the driver's control structure. 6365a112b11Smrg * \param foundEntities Returned list of entity indices associated with the 6376747b715Smrg * driver. 6386747b715Smrg * 6396747b715Smrg * \returns 6406747b715Smrg * The number of elements in returned in \c foundEntities on success or zero 6416747b715Smrg * on failure. 6426747b715Smrg * 6436747b715Smrg * \todo 6446747b715Smrg * This function does a bit more than short description says. Fill in some 6456747b715Smrg * more of the details of its operation. 6466747b715Smrg * 6476747b715Smrg * \todo 6486747b715Smrg * The \c driverName parameter is redundant. It is the same as 6496747b715Smrg * \c DriverRec::driverName. In a future version of this function, remove 6506747b715Smrg * that parameter. 6516747b715Smrg */ 6526747b715Smrgint 6536747b715Smrgxf86MatchPciInstances(const char *driverName, int vendorID, 654f7df2e56Smrg SymTabPtr chipsets, PciChipsets * PCIchipsets, 655f7df2e56Smrg GDevPtr * devList, int numDevs, DriverPtr drvp, 656f7df2e56Smrg int **foundEntities) 6576747b715Smrg{ 658f7df2e56Smrg int i, j; 659f7df2e56Smrg struct pci_device *pPci; 6606747b715Smrg struct pci_device_iterator *iter; 6616747b715Smrg struct Inst *instances = NULL; 6626747b715Smrg int numClaimedInstances = 0; 6636747b715Smrg int allocatedInstances = 0; 6646747b715Smrg int numFound = 0; 6656747b715Smrg SymTabRec *c; 6666747b715Smrg PciChipsets *id; 6676747b715Smrg int *retEntities = NULL; 6686747b715Smrg 6696747b715Smrg *foundEntities = NULL; 6706747b715Smrg 6716747b715Smrg /* Each PCI device will contribute at least one entry. Each device 6726747b715Smrg * section can contribute at most one entry. The sum of the two is 6736747b715Smrg * guaranteed to be larger than the maximum possible number of entries. 6746747b715Smrg * Do this calculation and memory allocation once now to eliminate the 6756747b715Smrg * need for realloc calls inside the loop. 6766747b715Smrg */ 6776747b715Smrg if (!(xf86DoConfigure && xf86DoConfigurePass1)) { 678f7df2e56Smrg unsigned max_entries = numDevs; 6796747b715Smrg 680f7df2e56Smrg iter = pci_slot_match_iterator_create(NULL); 681f7df2e56Smrg while ((pPci = pci_device_next(iter)) != NULL) { 682f7df2e56Smrg max_entries++; 683f7df2e56Smrg } 6846747b715Smrg 685f7df2e56Smrg pci_iterator_destroy(iter); 686f7df2e56Smrg instances = xnfallocarray(max_entries, sizeof(struct Inst)); 68705b261ecSmrg } 68805b261ecSmrg 6896747b715Smrg iter = pci_slot_match_iterator_create(NULL); 6906747b715Smrg while ((pPci = pci_device_next(iter)) != NULL) { 691f7df2e56Smrg unsigned device_class = pPci->device_class; 692f7df2e56Smrg Bool foundVendor = FALSE; 693f7df2e56Smrg 694f7df2e56Smrg /* Convert the pre-PCI 2.0 device class for a VGA adapter to the 695f7df2e56Smrg * 2.0 version of the same class. 696f7df2e56Smrg */ 697f7df2e56Smrg if (device_class == 0x00000101) { 698f7df2e56Smrg device_class = 0x00030000; 699f7df2e56Smrg } 700f7df2e56Smrg 701f7df2e56Smrg /* Find PCI devices that match the given vendor ID. The vendor ID is 702f7df2e56Smrg * either specified explicitly as a parameter to the function or 703f7df2e56Smrg * implicitly encoded in the high bits of id->PCIid. 704f7df2e56Smrg * 705f7df2e56Smrg * The first device with a matching vendor is recorded, even if the 706f7df2e56Smrg * device ID doesn't match. This is done because the Device section 707f7df2e56Smrg * in the xorg.conf file can over-ride the device ID. A matching PCI 708f7df2e56Smrg * ID might not be found now, but after the device ID over-ride is 709f7df2e56Smrg * applied there /might/ be a match. 710f7df2e56Smrg */ 711f7df2e56Smrg for (id = PCIchipsets; id->PCIid != -1; id++) { 712f7df2e56Smrg const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16) 713f7df2e56Smrg | vendorID; 714f7df2e56Smrg const unsigned device_id = (id->PCIid & 0x0000FFFF); 715f7df2e56Smrg const unsigned match_class = 0x00030000 | id->PCIid; 716f7df2e56Smrg 717f7df2e56Smrg if ((vendor_id == pPci->vendor_id) 718f7df2e56Smrg || ((vendorID == PCI_VENDOR_GENERIC) && 719f7df2e56Smrg (match_class == device_class))) { 720f7df2e56Smrg if (!foundVendor && (instances != NULL)) { 721f7df2e56Smrg ++allocatedInstances; 722f7df2e56Smrg instances[allocatedInstances - 1].pci = pPci; 723f7df2e56Smrg instances[allocatedInstances - 1].dev = NULL; 724f7df2e56Smrg instances[allocatedInstances - 1].claimed = FALSE; 725f7df2e56Smrg instances[allocatedInstances - 1].foundHW = FALSE; 726f7df2e56Smrg instances[allocatedInstances - 1].screen = 0; 727f7df2e56Smrg } 728f7df2e56Smrg 729f7df2e56Smrg foundVendor = TRUE; 730f7df2e56Smrg 731f7df2e56Smrg if ((device_id == pPci->device_id) 732f7df2e56Smrg || ((vendorID == PCI_VENDOR_GENERIC) 733f7df2e56Smrg && (match_class == device_class))) { 734f7df2e56Smrg if (instances != NULL) { 735f7df2e56Smrg instances[allocatedInstances - 1].foundHW = TRUE; 736f7df2e56Smrg instances[allocatedInstances - 1].chip = id->numChipset; 737f7df2e56Smrg } 738f7df2e56Smrg 739f7df2e56Smrg if (xf86DoConfigure && xf86DoConfigurePass1) { 740f7df2e56Smrg if (xf86CheckPciSlot(pPci)) { 741f7df2e56Smrg GDevPtr pGDev = 742f7df2e56Smrg xf86AddBusDeviceToConfigure(drvp->driverName, 743f7df2e56Smrg BUS_PCI, pPci, -1); 744f7df2e56Smrg 745f7df2e56Smrg if (pGDev) { 746f7df2e56Smrg /* After configure pass 1, chipID and chipRev 747f7df2e56Smrg * are treated as over-rides, so clobber them 748f7df2e56Smrg * here. 749f7df2e56Smrg */ 750f7df2e56Smrg pGDev->chipID = -1; 751f7df2e56Smrg pGDev->chipRev = -1; 752f7df2e56Smrg } 753f7df2e56Smrg 754f7df2e56Smrg numFound++; 755f7df2e56Smrg } 756f7df2e56Smrg } 757f7df2e56Smrg else { 758f7df2e56Smrg numFound++; 759f7df2e56Smrg } 760f7df2e56Smrg 761f7df2e56Smrg break; 762f7df2e56Smrg } 763f7df2e56Smrg } 764f7df2e56Smrg } 7656747b715Smrg } 7666747b715Smrg 7676747b715Smrg pci_iterator_destroy(iter); 7686747b715Smrg 7696747b715Smrg /* In "probe only" or "configure" mode (signaled by instances being NULL), 7706747b715Smrg * our work is done. Return the number of detected devices. 7716747b715Smrg */ 772f7df2e56Smrg if (instances == NULL) { 773f7df2e56Smrg return numFound; 7746747b715Smrg } 7756747b715Smrg 7766747b715Smrg /* 7776747b715Smrg * This may be debatable, but if no PCI devices with a matching vendor 7786747b715Smrg * type is found, return zero now. It is probably not desirable to 7796747b715Smrg * allow the config file to override this. 7806747b715Smrg */ 7816747b715Smrg if (allocatedInstances <= 0) { 782f7df2e56Smrg free(instances); 783f7df2e56Smrg return 0; 7846747b715Smrg } 7856747b715Smrg 7866747b715Smrg DebugF("%s instances found: %d\n", driverName, allocatedInstances); 7876747b715Smrg 788f7df2e56Smrg /* 789f7df2e56Smrg * Check for devices that need duplicated instances. This is required 790f7df2e56Smrg * when there is more than one screen per entity. 791f7df2e56Smrg * 792f7df2e56Smrg * XXX This currently doesn't work for cases where the BusID isn't 793f7df2e56Smrg * specified explicitly in the config file. 794f7df2e56Smrg */ 7956747b715Smrg 7966747b715Smrg for (j = 0; j < numDevs; j++) { 797f7df2e56Smrg if (devList[j]->screen > 0 && devList[j]->busID && *devList[j]->busID) { 798f7df2e56Smrg for (i = 0; i < allocatedInstances; i++) { 799f7df2e56Smrg pPci = instances[i].pci; 800f7df2e56Smrg if (xf86ComparePciBusString(devList[j]->busID, 801f7df2e56Smrg PCI_MAKE_BUS(pPci->domain, 802f7df2e56Smrg pPci->bus), pPci->dev, 803f7df2e56Smrg pPci->func)) { 804f7df2e56Smrg allocatedInstances++; 805f7df2e56Smrg instances[allocatedInstances - 1] = instances[i]; 806f7df2e56Smrg instances[allocatedInstances - 1].screen = 807f7df2e56Smrg devList[j]->screen; 808f7df2e56Smrg numFound++; 809f7df2e56Smrg break; 810f7df2e56Smrg } 811f7df2e56Smrg } 812f7df2e56Smrg } 8136747b715Smrg } 8146747b715Smrg 8156747b715Smrg for (i = 0; i < allocatedInstances; i++) { 816f7df2e56Smrg GDevPtr dev = NULL; 817f7df2e56Smrg GDevPtr devBus = NULL; 818f7df2e56Smrg 819f7df2e56Smrg pPci = instances[i].pci; 820f7df2e56Smrg for (j = 0; j < numDevs; j++) { 821f7df2e56Smrg if (devList[j]->busID && *devList[j]->busID) { 822f7df2e56Smrg if (xf86ComparePciBusString(devList[j]->busID, 823f7df2e56Smrg PCI_MAKE_BUS(pPci->domain, 824f7df2e56Smrg pPci->bus), pPci->dev, 825f7df2e56Smrg pPci->func) && 826f7df2e56Smrg devList[j]->screen == instances[i].screen) { 827f7df2e56Smrg 828f7df2e56Smrg if (devBus) 829f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, 830f7df2e56Smrg "%s: More than one matching Device section for " 831f7df2e56Smrg "instances\n\t(BusID: %s) found: %s\n", 832f7df2e56Smrg driverName, devList[j]->busID, 833f7df2e56Smrg devList[j]->identifier); 834f7df2e56Smrg else 835f7df2e56Smrg devBus = devList[j]; 836f7df2e56Smrg } 837f7df2e56Smrg } 838f7df2e56Smrg else { 839f7df2e56Smrg /* 840f7df2e56Smrg * if device section without BusID is found 841f7df2e56Smrg * only assign to it to the primary device. 842f7df2e56Smrg */ 843f7df2e56Smrg if (xf86IsPrimaryPci(pPci)) { 844f7df2e56Smrg xf86Msg(X_PROBED, "Assigning device section with no busID" 845f7df2e56Smrg " to primary device\n"); 846f7df2e56Smrg if (dev || devBus) 847f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, 848f7df2e56Smrg "%s: More than one matching Device section " 849f7df2e56Smrg "found: %s\n", driverName, 850f7df2e56Smrg devList[j]->identifier); 851f7df2e56Smrg else 852f7df2e56Smrg dev = devList[j]; 853f7df2e56Smrg } 854f7df2e56Smrg } 855f7df2e56Smrg } 856f7df2e56Smrg if (devBus) 857f7df2e56Smrg dev = devBus; /* busID preferred */ 858f7df2e56Smrg if (!dev) { 859f7df2e56Smrg if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) { 860f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 861f7df2e56Smrg "for instance (BusID PCI:%u@%u:%u:%u) found\n", 8627e31ba66Smrg driverName, pPci->bus, pPci->domain, pPci->dev, 863f7df2e56Smrg pPci->func); 864f7df2e56Smrg } 865f7df2e56Smrg } 866f7df2e56Smrg else { 867f7df2e56Smrg numClaimedInstances++; 868f7df2e56Smrg instances[i].claimed = TRUE; 869f7df2e56Smrg instances[i].dev = dev; 870f7df2e56Smrg } 8716747b715Smrg } 8726747b715Smrg DebugF("%s instances found: %d\n", driverName, numClaimedInstances); 8736747b715Smrg /* 8746747b715Smrg * Now check that a chipset or chipID override in the device section 8756747b715Smrg * is valid. Chipset has precedence over chipID. 8766747b715Smrg * If chipset is not valid ignore BusSlot completely. 8776747b715Smrg */ 8786747b715Smrg for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 879f7df2e56Smrg MessageType from = X_PROBED; 880f7df2e56Smrg 881f7df2e56Smrg if (!instances[i].claimed) { 882f7df2e56Smrg continue; 883f7df2e56Smrg } 884f7df2e56Smrg if (instances[i].dev->chipset) { 885f7df2e56Smrg for (c = chipsets; c->token >= 0; c++) { 886f7df2e56Smrg if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0) 887f7df2e56Smrg break; 888f7df2e56Smrg } 889f7df2e56Smrg if (c->token == -1) { 890f7df2e56Smrg instances[i].claimed = FALSE; 891f7df2e56Smrg numClaimedInstances--; 892f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " 893f7df2e56Smrg "section \"%s\" isn't valid for this driver\n", 894f7df2e56Smrg driverName, instances[i].dev->chipset, 895f7df2e56Smrg instances[i].dev->identifier); 896f7df2e56Smrg } 897f7df2e56Smrg else { 898f7df2e56Smrg instances[i].chip = c->token; 899f7df2e56Smrg 900f7df2e56Smrg for (id = PCIchipsets; id->numChipset >= 0; id++) { 901f7df2e56Smrg if (id->numChipset == instances[i].chip) 902f7df2e56Smrg break; 903f7df2e56Smrg } 904f7df2e56Smrg if (id->numChipset >= 0) { 905f7df2e56Smrg xf86Msg(X_CONFIG, "Chipset override: %s\n", 906f7df2e56Smrg instances[i].dev->chipset); 907f7df2e56Smrg from = X_CONFIG; 908f7df2e56Smrg } 909f7df2e56Smrg else { 910f7df2e56Smrg instances[i].claimed = FALSE; 911f7df2e56Smrg numClaimedInstances--; 912f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " 913f7df2e56Smrg "section \"%s\" isn't a valid PCI chipset\n", 914f7df2e56Smrg driverName, instances[i].dev->chipset, 915f7df2e56Smrg instances[i].dev->identifier); 916f7df2e56Smrg } 917f7df2e56Smrg } 918f7df2e56Smrg } 919f7df2e56Smrg else if (instances[i].dev->chipID > 0) { 920f7df2e56Smrg for (id = PCIchipsets; id->numChipset >= 0; id++) { 921f7df2e56Smrg if (id->PCIid == instances[i].dev->chipID) 922f7df2e56Smrg break; 923f7df2e56Smrg } 924f7df2e56Smrg if (id->numChipset == -1) { 925f7df2e56Smrg instances[i].claimed = FALSE; 926f7df2e56Smrg numClaimedInstances--; 927f7df2e56Smrg xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device " 928f7df2e56Smrg "section \"%s\" isn't valid for this driver\n", 929f7df2e56Smrg driverName, instances[i].dev->chipID, 930f7df2e56Smrg instances[i].dev->identifier); 931f7df2e56Smrg } 932f7df2e56Smrg else { 933f7df2e56Smrg instances[i].chip = id->numChipset; 934f7df2e56Smrg 935f7df2e56Smrg xf86Msg(X_CONFIG, "ChipID override: 0x%04X\n", 936f7df2e56Smrg instances[i].dev->chipID); 937f7df2e56Smrg from = X_CONFIG; 938f7df2e56Smrg } 939f7df2e56Smrg } 940f7df2e56Smrg else if (!instances[i].foundHW) { 941f7df2e56Smrg /* 942f7df2e56Smrg * This means that there was no override and the PCI chipType 943f7df2e56Smrg * doesn't match one that is supported 944f7df2e56Smrg */ 945f7df2e56Smrg instances[i].claimed = FALSE; 946f7df2e56Smrg numClaimedInstances--; 947f7df2e56Smrg } 948f7df2e56Smrg if (instances[i].claimed == TRUE) { 949f7df2e56Smrg for (c = chipsets; c->token >= 0; c++) { 950f7df2e56Smrg if (c->token == instances[i].chip) 951f7df2e56Smrg break; 952f7df2e56Smrg } 953f7df2e56Smrg xf86Msg(from, "Chipset %s found\n", c->name); 954f7df2e56Smrg } 9556747b715Smrg } 9566747b715Smrg 9576747b715Smrg /* 9586747b715Smrg * Of the claimed instances, check that another driver hasn't already 9596747b715Smrg * claimed its slot. 9606747b715Smrg */ 9616747b715Smrg numFound = 0; 9626747b715Smrg for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 963f7df2e56Smrg if (!instances[i].claimed) 964f7df2e56Smrg continue; 965f7df2e56Smrg pPci = instances[i].pci; 9666747b715Smrg 9676747b715Smrg /* 968f7df2e56Smrg * Allow the same entity to be used more than once for devices with 969f7df2e56Smrg * multiple screens per entity. This assumes implicitly that there 970f7df2e56Smrg * will be a screen == 0 instance. 971f7df2e56Smrg * 972f7df2e56Smrg * XXX Need to make sure that two different drivers don't claim 973f7df2e56Smrg * the same screen > 0 instance. 974f7df2e56Smrg */ 975f7df2e56Smrg if (instances[i].screen == 0 && !xf86CheckPciSlot(pPci)) 976f7df2e56Smrg continue; 977f7df2e56Smrg 978f7df2e56Smrg DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", 979f7df2e56Smrg driverName, pPci->bus, pPci->dev, pPci->func); 980f7df2e56Smrg 981f7df2e56Smrg /* Allocate an entry in the lists to be returned */ 982f7df2e56Smrg numFound++; 983f7df2e56Smrg retEntities = xnfreallocarray(retEntities, numFound, sizeof(int)); 984f7df2e56Smrg retEntities[numFound - 1] = xf86ClaimPciSlot(pPci, drvp, 985f7df2e56Smrg instances[i].chip, 986f7df2e56Smrg instances[i].dev, 987f7df2e56Smrg instances[i].dev->active); 9886747b715Smrg if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) { 989f7df2e56Smrg for (j = 0; j < xf86NumEntities; j++) { 990f7df2e56Smrg EntityPtr pEnt = xf86Entities[j]; 991f7df2e56Smrg 992f7df2e56Smrg if (pEnt->bus.type != BUS_PCI) 993f7df2e56Smrg continue; 994f7df2e56Smrg if (pEnt->bus.id.pci == pPci) { 995f7df2e56Smrg retEntities[numFound - 1] = j; 996f7df2e56Smrg xf86AddDevToEntity(j, instances[i].dev); 997f7df2e56Smrg break; 998f7df2e56Smrg } 999f7df2e56Smrg } 1000f7df2e56Smrg } 10016747b715Smrg } 10026747b715Smrg free(instances); 10036747b715Smrg if (numFound > 0) { 1004f7df2e56Smrg *foundEntities = retEntities; 10056747b715Smrg } 10066747b715Smrg 10076747b715Smrg return numFound; 10086747b715Smrg} 10096747b715Smrg 10106747b715Smrg/* 10116747b715Smrg * xf86ConfigPciEntityInactive() -- This function can be used 10126747b715Smrg * to configure an inactive entity as well as to reconfigure an 10136747b715Smrg * previously active entity inactive. If the entity has been 10146747b715Smrg * assigned to a screen before it will be removed. If p_chip is 10156747b715Smrg * non-NULL all static resources listed there will be registered. 10166747b715Smrg */ 10176747b715Smrgstatic void 1018f7df2e56Smrgxf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets * p_chip, 1019f7df2e56Smrg EntityProc init, EntityProc enter, 1020f7df2e56Smrg EntityProc leave, void *private) 10216747b715Smrg{ 10226747b715Smrg ScrnInfoPtr pScrn; 10236747b715Smrg 10246747b715Smrg if ((pScrn = xf86FindScreenForEntity(pEnt->index))) 1025f7df2e56Smrg xf86RemoveEntityFromScreen(pScrn, pEnt->index); 10266747b715Smrg} 10276747b715Smrg 10286747b715SmrgScrnInfoPtr 10296747b715Smrgxf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, 1030f7df2e56Smrg PciChipsets * p_chip, void *dummy, EntityProc init, 1031f7df2e56Smrg EntityProc enter, EntityProc leave, void *private) 10326747b715Smrg{ 10336747b715Smrg EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); 1034f7df2e56Smrg 10357e31ba66Smrg if (dummy || init || enter || leave) 10367e31ba66Smrg FatalError("Legacy entity access functions are unsupported\n"); 10377e31ba66Smrg 1038f7df2e56Smrg if (!pEnt) 1039f7df2e56Smrg return pScrn; 10406747b715Smrg 10416747b715Smrg if (!(pEnt->location.type == BUS_PCI) 1042f7df2e56Smrg || !xf86GetPciInfoForEntity(entityIndex)) { 1043f7df2e56Smrg free(pEnt); 1044f7df2e56Smrg return pScrn; 10456747b715Smrg } 10466747b715Smrg if (!pEnt->active) { 1047f7df2e56Smrg xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, leave, private); 1048f7df2e56Smrg free(pEnt); 1049f7df2e56Smrg return pScrn; 10506747b715Smrg } 10516747b715Smrg 10526747b715Smrg if (!pScrn) 1053f7df2e56Smrg pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag); 10546747b715Smrg if (xf86IsEntitySharable(entityIndex)) { 10556747b715Smrg xf86SetEntityShared(entityIndex); 10566747b715Smrg } 1057f7df2e56Smrg xf86AddEntityToScreen(pScrn, entityIndex); 10586747b715Smrg if (xf86IsEntityShared(entityIndex)) { 10596747b715Smrg return pScrn; 10606747b715Smrg } 10616747b715Smrg free(pEnt); 106205b261ecSmrg 10636747b715Smrg return pScrn; 10646747b715Smrg} 10656747b715Smrg 10667e31ba66Smrgvoid 10677e31ba66Smrgxf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md) 10686747b715Smrg{ 10696747b715Smrg int i; 1070f7df2e56Smrg 10716747b715Smrg /* Add more entries here if we ever return more than 4 drivers for 10726747b715Smrg any device */ 1073f7df2e56Smrg const char *driverList[5] = { NULL, NULL, NULL, NULL, NULL }; 10746747b715Smrg 1075e005038aSmaya switch (dev->vendor_id) { 1076e005038aSmaya /* AMD Geode LX */ 1077f7df2e56Smrg case 0x1022: 1078f7df2e56Smrg if (dev->device_id == 0x2081) 1079f7df2e56Smrg driverList[0] = "geode"; 1080f7df2e56Smrg break; 1081f7df2e56Smrg /* older Geode products acquired by AMD still carry an NSC vendor_id */ 1082f7df2e56Smrg case 0x100b: 1083f7df2e56Smrg if (dev->device_id == 0x0030) { 1084f7df2e56Smrg /* NSC Geode GX2 specifically */ 1085f7df2e56Smrg driverList[0] = "geode"; 1086f7df2e56Smrg /* GX2 support started its life in the NSC tree and was later 1087f7df2e56Smrg forked by AMD for GEODE so we keep it as a backup */ 1088f7df2e56Smrg driverList[1] = "nsc"; 1089f7df2e56Smrg } 1090f7df2e56Smrg else 1091f7df2e56Smrg /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */ 1092f7df2e56Smrg driverList[0] = "nsc"; 1093f7df2e56Smrg break; 1094f7df2e56Smrg /* Cyrix Geode GX1 */ 1095f7df2e56Smrg case 0x1078: 1096f7df2e56Smrg if (dev->device_id == 0x0104) 1097f7df2e56Smrg driverList[0] = "cyrix"; 1098f7df2e56Smrg break; 1099f7df2e56Smrg case 0x1142: 1100f7df2e56Smrg driverList[0] = "apm"; 1101f7df2e56Smrg break; 1102f7df2e56Smrg case 0xedd8: 1103f7df2e56Smrg driverList[0] = "ark"; 1104f7df2e56Smrg break; 1105f7df2e56Smrg case 0x1a03: 1106f7df2e56Smrg driverList[0] = "ast"; 1107f7df2e56Smrg break; 1108f7df2e56Smrg case 0x1002: 1109f7df2e56Smrg driverList[0] = "ati"; 1110f7df2e56Smrg break; 1111f7df2e56Smrg case 0x102c: 1112f7df2e56Smrg driverList[0] = "chips"; 1113f7df2e56Smrg break; 1114f7df2e56Smrg case 0x1013: 1115f7df2e56Smrg driverList[0] = "cirrus"; 1116f7df2e56Smrg break; 1117f7df2e56Smrg case 0x3d3d: 1118f7df2e56Smrg driverList[0] = "glint"; 1119f7df2e56Smrg break; 1120f7df2e56Smrg case 0x105d: 1121f7df2e56Smrg driverList[0] = "i128"; 1122f7df2e56Smrg break; 1123f7df2e56Smrg case 0x8086: 1124f7df2e56Smrg switch (dev->device_id) 1125f7df2e56Smrg { 1126f7df2e56Smrg /* Intel i740 */ 1127f7df2e56Smrg case 0x00d1: 1128f7df2e56Smrg case 0x7800: 1129f7df2e56Smrg driverList[0] = "i740"; 1130f7df2e56Smrg break; 1131f7df2e56Smrg /* GMA500/Poulsbo */ 1132f7df2e56Smrg case 0x8108: 1133f7df2e56Smrg case 0x8109: 1134f7df2e56Smrg /* Try psb driver on Poulsbo - if available */ 1135f7df2e56Smrg driverList[0] = "psb"; 1136f7df2e56Smrg driverList[1] = "psb_drv"; 1137f7df2e56Smrg break; 1138f7df2e56Smrg /* GMA600/Oaktrail */ 1139f7df2e56Smrg case 0x4100: 1140f7df2e56Smrg case 0x4101: 1141f7df2e56Smrg case 0x4102: 1142f7df2e56Smrg case 0x4103: 1143f7df2e56Smrg case 0x4104: 1144f7df2e56Smrg case 0x4105: 1145f7df2e56Smrg case 0x4106: 1146f7df2e56Smrg case 0x4107: 1147f7df2e56Smrg /* Atom E620/Oaktrail */ 1148f7df2e56Smrg case 0x4108: 1149f7df2e56Smrg /* Medfield */ 1150f7df2e56Smrg case 0x0130: 1151f7df2e56Smrg case 0x0131: 1152f7df2e56Smrg case 0x0132: 1153f7df2e56Smrg case 0x0133: 1154f7df2e56Smrg case 0x0134: 1155f7df2e56Smrg case 0x0135: 1156f7df2e56Smrg case 0x0136: 1157f7df2e56Smrg case 0x0137: 1158f7df2e56Smrg /* GMA 3600/CDV */ 1159f7df2e56Smrg case 0x0be0: 1160f7df2e56Smrg case 0x0be1: 1161f7df2e56Smrg case 0x0be2: 1162f7df2e56Smrg case 0x0be3: 1163f7df2e56Smrg case 0x0be4: 1164f7df2e56Smrg case 0x0be5: 1165f7df2e56Smrg case 0x0be6: 1166f7df2e56Smrg case 0x0be7: 1167f7df2e56Smrg case 0x0be8: 1168f7df2e56Smrg case 0x0be9: 1169f7df2e56Smrg case 0x0bea: 1170f7df2e56Smrg case 0x0beb: 1171f7df2e56Smrg case 0x0bec: 1172f7df2e56Smrg case 0x0bed: 1173f7df2e56Smrg case 0x0bee: 1174f7df2e56Smrg case 0x0bef: 1175f7df2e56Smrg /* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */ 1176f7df2e56Smrg break; 11776747b715Smrg default: 1178f7df2e56Smrg driverList[0] = "intel"; 1179f7df2e56Smrg break; 1180f7df2e56Smrg } 1181f7df2e56Smrg break; 1182f7df2e56Smrg case 0x102b: 1183f7df2e56Smrg driverList[0] = "mga"; 1184f7df2e56Smrg break; 1185f7df2e56Smrg case 0x10c8: 1186f7df2e56Smrg driverList[0] = "neomagic"; 1187f7df2e56Smrg break; 1188f7df2e56Smrg case 0x10de: 1189f7df2e56Smrg case 0x12d2: 1190f7df2e56Smrg { 1191f7df2e56Smrg int idx = 0; 1192f7df2e56Smrg 1193f7df2e56Smrg#if defined(__linux__) || defined(__NetBSD__) 1194f7df2e56Smrg driverList[idx++] = "nouveau"; 1195f7df2e56Smrg#endif 1196f7df2e56Smrg driverList[idx++] = "nv"; 1197f7df2e56Smrg break; 1198f7df2e56Smrg } 1199f7df2e56Smrg case 0x1106: 1200f7df2e56Smrg driverList[0] = "openchrome"; 1201f7df2e56Smrg break; 1202f7df2e56Smrg case 0x1b36: 1203f7df2e56Smrg driverList[0] = "qxl"; 1204f7df2e56Smrg break; 1205f7df2e56Smrg case 0x1163: 1206f7df2e56Smrg driverList[0] = "rendition"; 1207f7df2e56Smrg break; 1208f7df2e56Smrg case 0x5333: 1209f7df2e56Smrg switch (dev->device_id) { 1210f7df2e56Smrg case 0x88d0: 1211f7df2e56Smrg case 0x88d1: 1212f7df2e56Smrg case 0x88f0: 1213f7df2e56Smrg case 0x8811: 1214f7df2e56Smrg case 0x8812: 1215f7df2e56Smrg case 0x8814: 1216f7df2e56Smrg case 0x8901: 1217f7df2e56Smrg driverList[0] = "s3"; 1218f7df2e56Smrg break; 1219f7df2e56Smrg case 0x5631: 1220f7df2e56Smrg case 0x883d: 1221f7df2e56Smrg case 0x8a01: 1222f7df2e56Smrg case 0x8a10: 1223f7df2e56Smrg case 0x8c01: 1224f7df2e56Smrg case 0x8c03: 1225f7df2e56Smrg case 0x8904: 1226f7df2e56Smrg case 0x8a13: 1227f7df2e56Smrg driverList[0] = "s3virge"; 1228f7df2e56Smrg break; 1229f7df2e56Smrg default: 1230f7df2e56Smrg driverList[0] = "savage"; 1231f7df2e56Smrg break; 1232f7df2e56Smrg } 1233f7df2e56Smrg break; 1234f7df2e56Smrg case 0x1039: 1235f7df2e56Smrg driverList[0] = "sis"; 1236f7df2e56Smrg break; 1237f7df2e56Smrg case 0x126f: 1238f7df2e56Smrg driverList[0] = "siliconmotion"; 1239f7df2e56Smrg break; 1240f7df2e56Smrg case 0x121a: 1241f7df2e56Smrg if (dev->device_id < 0x0003) 1242f7df2e56Smrg driverList[0] = "voodoo"; 1243f7df2e56Smrg else 1244f7df2e56Smrg driverList[0] = "tdfx"; 1245f7df2e56Smrg break; 1246f7df2e56Smrg case 0x1011: 1247f7df2e56Smrg driverList[0] = "tga"; 1248f7df2e56Smrg break; 1249f7df2e56Smrg case 0x1023: 1250f7df2e56Smrg driverList[0] = "trident"; 1251f7df2e56Smrg break; 1252f7df2e56Smrg case 0x100c: 1253f7df2e56Smrg driverList[0] = "tseng"; 1254f7df2e56Smrg break; 1255f7df2e56Smrg case 0x80ee: 1256f7df2e56Smrg driverList[0] = "vboxvideo"; 1257f7df2e56Smrg break; 1258f7df2e56Smrg case 0x15ad: 1259f7df2e56Smrg driverList[0] = "vmware"; 1260f7df2e56Smrg break; 1261f7df2e56Smrg case 0x18ca: 1262f7df2e56Smrg if (dev->device_id == 0x47) 1263f7df2e56Smrg driverList[0] = "xgixp"; 1264f7df2e56Smrg else 1265f7df2e56Smrg driverList[0] = "xgi"; 1266f7df2e56Smrg break; 1267f7df2e56Smrg default: 1268f7df2e56Smrg break; 12696747b715Smrg } 12707e31ba66Smrg for (i = 0; driverList[i] != NULL; i++) { 12717e31ba66Smrg xf86AddMatchedDriver(md, driverList[i]); 12726747b715Smrg } 12736747b715Smrg} 12746747b715Smrg 12759ace9065Smrg#ifdef __linux__ 12766747b715Smrgstatic int 12776747b715Smrgxchomp(char *line) 12786747b715Smrg{ 12796747b715Smrg size_t len = 0; 12806747b715Smrg 12816747b715Smrg if (!line) { 12826747b715Smrg return 1; 12836747b715Smrg } 12846747b715Smrg 12856747b715Smrg len = strlen(line); 12866747b715Smrg if (line[len - 1] == '\n' && len > 0) { 12876747b715Smrg line[len - 1] = '\0'; 12886747b715Smrg } 12896747b715Smrg return 0; 12906747b715Smrg} 12916747b715Smrg 12926747b715Smrg/* This function is used to provide a workaround for binary drivers that 12936747b715Smrg * don't export their PCI ID's properly. If distros don't end up using this 12946747b715Smrg * feature it can and should be removed because the symbol-based resolution 12956747b715Smrg * scheme should be the primary one */ 12967e31ba66Smrgvoid 1297f7df2e56Smrgxf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip, 12987e31ba66Smrg XF86MatchedDrivers *md) 12996747b715Smrg{ 13006747b715Smrg DIR *idsdir; 13016747b715Smrg FILE *fp; 13026747b715Smrg struct dirent *direntry; 13037e31ba66Smrg char *line = NULL, *tmpMatch; 13046747b715Smrg size_t len; 13056747b715Smrg ssize_t read; 13067e31ba66Smrg char path_name[512], vendor_str[5], chip_str[5]; 13076747b715Smrg uint16_t vendor, chip; 13087e31ba66Smrg int j; 13096747b715Smrg 13106747b715Smrg idsdir = opendir(PCI_TXT_IDS_PATH); 13116747b715Smrg if (!idsdir) 13127e31ba66Smrg return; 13136747b715Smrg 1314f7df2e56Smrg xf86Msg(X_INFO, 1315f7df2e56Smrg "Scanning %s directory for additional PCI ID's supported by the drivers\n", 1316f7df2e56Smrg PCI_TXT_IDS_PATH); 13176747b715Smrg direntry = readdir(idsdir); 13186747b715Smrg /* Read the directory */ 13196747b715Smrg while (direntry) { 13206747b715Smrg if (direntry->d_name[0] == '.') { 13216747b715Smrg direntry = readdir(idsdir); 13226747b715Smrg continue; 13236747b715Smrg } 13246747b715Smrg len = strlen(direntry->d_name); 13256747b715Smrg /* A tiny bit of sanity checking. We should probably do better */ 1326f7df2e56Smrg if (strncmp(&(direntry->d_name[len - 4]), ".ids", 4) == 0) { 13276747b715Smrg /* We need the full path name to open the file */ 1328f7df2e56Smrg snprintf(path_name, sizeof(path_name), "%s/%s", 1329f7df2e56Smrg PCI_TXT_IDS_PATH, direntry->d_name); 13306747b715Smrg fp = fopen(path_name, "r"); 13316747b715Smrg if (fp == NULL) { 1332f7df2e56Smrg xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", 1333f7df2e56Smrg path_name); 13346747b715Smrg goto end; 13356747b715Smrg } 13366747b715Smrg /* Read the file */ 13376747b715Smrg#ifdef __GLIBC__ 13386747b715Smrg while ((read = getline(&line, &len, fp)) != -1) { 13396747b715Smrg#else 1340f7df2e56Smrg while ((line = fgetln(fp, &len)) != (char *) NULL) { 1341f7df2e56Smrg#endif /* __GLIBC __ */ 13426747b715Smrg xchomp(line); 13436747b715Smrg if (isdigit(line[0])) { 1344f7df2e56Smrg strlcpy(vendor_str, line, sizeof(vendor_str)); 1345f7df2e56Smrg vendor = (int) strtol(vendor_str, NULL, 16); 13466747b715Smrg if ((strlen(&line[4])) == 0) { 13476747b715Smrg chip_str[0] = '\0'; 13486747b715Smrg chip = -1; 1349f7df2e56Smrg } 1350f7df2e56Smrg else { 13516747b715Smrg /* Handle trailing whitespace */ 13526747b715Smrg if (isspace(line[4])) { 13536747b715Smrg chip_str[0] = '\0'; 13546747b715Smrg chip = -1; 1355f7df2e56Smrg } 1356f7df2e56Smrg else { 13576747b715Smrg /* Ok, it's a real ID */ 1358f7df2e56Smrg strlcpy(chip_str, &line[4], sizeof(chip_str)); 1359f7df2e56Smrg chip = (int) strtol(chip_str, NULL, 16); 13606747b715Smrg } 13616747b715Smrg } 1362f7df2e56Smrg if (vendor == match_vendor && chip == match_chip) { 13637e31ba66Smrg tmpMatch = 1364f7df2e56Smrg (char *) malloc(sizeof(char) * 1365f7df2e56Smrg strlen(direntry->d_name) - 3); 13667e31ba66Smrg if (!tmpMatch) { 1367f7df2e56Smrg xf86Msg(X_ERROR, 1368f7df2e56Smrg "Could not allocate space for the module name. Exiting.\n"); 13696747b715Smrg goto end; 13706747b715Smrg } 13716747b715Smrg /* hack off the .ids suffix. This should guard 13726747b715Smrg * against other problems, but it will end up 13736747b715Smrg * taking off anything after the first '.' */ 1374f7df2e56Smrg for (j = 0; j < (strlen(direntry->d_name) - 3); j++) { 13756747b715Smrg if (direntry->d_name[j] == '.') { 13767e31ba66Smrg tmpMatch[j] = '\0'; 13776747b715Smrg break; 1378f7df2e56Smrg } 1379f7df2e56Smrg else { 13807e31ba66Smrg tmpMatch[j] = direntry->d_name[j]; 13816747b715Smrg } 13826747b715Smrg } 13837e31ba66Smrg xf86AddMatchedDriver(md, tmpMatch); 1384f7df2e56Smrg xf86Msg(X_INFO, "Matched %s from file name %s\n", 13857e31ba66Smrg tmpMatch, direntry->d_name); 13867e31ba66Smrg free(tmpMatch); 13876747b715Smrg } 1388f7df2e56Smrg } 1389f7df2e56Smrg else { 13906747b715Smrg /* TODO Handle driver overrides here */ 13916747b715Smrg } 13926747b715Smrg } 13936747b715Smrg fclose(fp); 13946747b715Smrg } 13956747b715Smrg direntry = readdir(idsdir); 13966747b715Smrg } 13976747b715Smrg end: 13986747b715Smrg free(line); 13996747b715Smrg closedir(idsdir); 14006747b715Smrg} 1401f7df2e56Smrg#endif /* __linux__ */ 14026747b715Smrg 14037e31ba66Smrgvoid 14047e31ba66Smrgxf86PciMatchDriver(XF86MatchedDrivers *md) 1405f7df2e56Smrg{ 1406f7df2e56Smrg struct pci_device *info = NULL; 14076747b715Smrg struct pci_device_iterator *iter; 14086747b715Smrg 14096747b715Smrg /* Find the primary device, and get some information about it. */ 14106747b715Smrg iter = pci_slot_match_iterator_create(NULL); 14116747b715Smrg while ((info = pci_device_next(iter)) != NULL) { 1412f7df2e56Smrg if (xf86IsPrimaryPci(info)) { 1413f7df2e56Smrg break; 1414f7df2e56Smrg } 141505b261ecSmrg } 141605b261ecSmrg 14176747b715Smrg pci_iterator_destroy(iter); 14186747b715Smrg#ifdef __linux__ 14199ace9065Smrg if (info) 14207e31ba66Smrg xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md); 14219ace9065Smrg#endif 14226747b715Smrg 14237e31ba66Smrg if (info != NULL) { 14247e31ba66Smrg xf86VideoPtrToDriverList(info, md); 14256747b715Smrg } 142605b261ecSmrg} 14279ace9065Smrg 14289ace9065SmrgBool 14299ace9065Smrgxf86PciConfigure(void *busData, struct pci_device *pDev) 14309ace9065Smrg{ 1431f7df2e56Smrg struct pci_device *pVideo = NULL; 14329ace9065Smrg 14339ace9065Smrg pVideo = (struct pci_device *) busData; 14349ace9065Smrg if (pDev && 14359ace9065Smrg (pDev->domain == pVideo->domain) && 14369ace9065Smrg (pDev->bus == pVideo->bus) && 1437f7df2e56Smrg (pDev->dev == pVideo->dev) && (pDev->func == pVideo->func)) 14389ace9065Smrg return 0; 14399ace9065Smrg 14409ace9065Smrg return 1; 14419ace9065Smrg} 14429ace9065Smrg 14439ace9065Smrgvoid 14449ace9065Smrgxf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, 1445f7df2e56Smrg GDevRec * GDev, int *chipset) 14469ace9065Smrg{ 14479ace9065Smrg char busnum[8]; 1448f7df2e56Smrg char *tmp; 14499ace9065Smrg 14509ace9065Smrg pVideo = (struct pci_device *) busData; 14519ace9065Smrg 14527e31ba66Smrg snprintf(busnum, sizeof(busnum), "%d", pVideo->bus); 1453f7df2e56Smrg 1454f7df2e56Smrg XNFasprintf(&tmp, "PCI:%s:%d:%d", 1455f7df2e56Smrg busnum, pVideo->dev, pVideo->func); 1456f7df2e56Smrg GDev->busID = tmp; 14579ace9065Smrg 14589ace9065Smrg GDev->chipID = pVideo->device_id; 14599ace9065Smrg GDev->chipRev = pVideo->revision; 14609ace9065Smrg 14619ace9065Smrg if (*chipset < 0) 14629ace9065Smrg *chipset = (pVideo->vendor_id << 16) | pVideo->device_id; 14639ace9065Smrg} 14647e31ba66Smrg 14657e31ba66Smrgchar * 14667e31ba66SmrgDRICreatePCIBusID(const struct pci_device *dev) 14677e31ba66Smrg{ 14687e31ba66Smrg char *busID; 14697e31ba66Smrg 14707e31ba66Smrg if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", 14717e31ba66Smrg dev->domain, dev->bus, dev->dev, dev->func) == -1) 14727e31ba66Smrg return NULL; 14737e31ba66Smrg 14747e31ba66Smrg return busID; 14757e31ba66Smrg} 1476