1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 23706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 24706f2543Smrg * the sale, use or other dealings in this Software without prior written 25706f2543Smrg * authorization from the copyright holder(s) and author(s). 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * This file contains the interfaces to the bus-specific code 30706f2543Smrg */ 31706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 32706f2543Smrg#include <xorg-config.h> 33706f2543Smrg#endif 34706f2543Smrg 35706f2543Smrg#include <ctype.h> 36706f2543Smrg#include <stdlib.h> 37706f2543Smrg#include <unistd.h> 38706f2543Smrg#include <X11/X.h> 39706f2543Smrg#include <pciaccess.h> 40706f2543Smrg#include "os.h" 41706f2543Smrg#include "Pci.h" 42706f2543Smrg#include "xf86.h" 43706f2543Smrg#include "xf86Priv.h" 44706f2543Smrg#include "dirent.h" /* DIR, FILE type definitions */ 45706f2543Smrg 46706f2543Smrg/* Bus-specific headers */ 47706f2543Smrg#include "xf86Bus.h" 48706f2543Smrg 49706f2543Smrg#define XF86_OS_PRIVS 50706f2543Smrg#include "xf86_OSproc.h" 51706f2543Smrg 52706f2543Smrg 53706f2543Smrg/* Bus-specific globals */ 54706f2543SmrgBool pciSlotClaimed = FALSE; 55706f2543Smrg 56706f2543Smrg#define PCIINFOCLASSES(c) \ 57706f2543Smrg ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ 58706f2543Smrg || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 59706f2543Smrg || ((((c) & 0x00ffff00) \ 60706f2543Smrg == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ 61706f2543Smrg || ((((c) & 0x00ffff00) \ 62706f2543Smrg == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) 63706f2543Smrg 64706f2543Smrg/* 65706f2543Smrg * PCI classes that have messages printed always. The others are only 66706f2543Smrg * have a message printed when the vendor/dev IDs are recognised. 67706f2543Smrg */ 68706f2543Smrg#define PCIALWAYSPRINTCLASSES(c) \ 69706f2543Smrg ( (((c) & 0x00ffff00) \ 70706f2543Smrg == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ 71706f2543Smrg || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ 72706f2543Smrg || ((((c) & 0x00ffff00) \ 73706f2543Smrg == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) 74706f2543Smrg 75706f2543Smrg#define IS_VGA(c) \ 76706f2543Smrg (((c) & 0x00ffff00) \ 77706f2543Smrg == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) 78706f2543Smrg 79706f2543Smrg 80706f2543Smrgstatic struct pci_slot_match xf86IsolateDevice = { 81706f2543Smrg PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0 82706f2543Smrg}; 83706f2543Smrg 84706f2543Smrgvoid 85706f2543Smrgxf86FormatPciBusNumber(int busnum, char *buffer) 86706f2543Smrg{ 87706f2543Smrg /* 'buffer' should be at least 8 characters long */ 88706f2543Smrg if (busnum < 256) 89706f2543Smrg sprintf(buffer, "%d", busnum); 90706f2543Smrg else 91706f2543Smrg sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8); 92706f2543Smrg} 93706f2543Smrg 94706f2543Smrg/* 95706f2543Smrg * xf86Bus.c interface 96706f2543Smrg */ 97706f2543Smrg 98706f2543Smrgvoid 99706f2543Smrgxf86PciProbe(void) 100706f2543Smrg{ 101706f2543Smrg int i = 0, k; 102706f2543Smrg int num = 0; 103706f2543Smrg struct pci_device *info; 104706f2543Smrg struct pci_device_iterator *iter; 105706f2543Smrg struct pci_device ** xf86PciVideoInfo = NULL; 106706f2543Smrg 107706f2543Smrg 108706f2543Smrg if (!xf86scanpci()) { 109706f2543Smrg xf86PciVideoInfo = NULL; 110706f2543Smrg return; 111706f2543Smrg } 112706f2543Smrg 113706f2543Smrg iter = pci_slot_match_iterator_create(& xf86IsolateDevice); 114706f2543Smrg while ((info = pci_device_next(iter)) != NULL) { 115706f2543Smrg if (PCIINFOCLASSES(info->device_class)) { 116706f2543Smrg num++; 117706f2543Smrg xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo, 118706f2543Smrg (sizeof(struct pci_device *) 119706f2543Smrg * (num + 1))); 120706f2543Smrg xf86PciVideoInfo[num] = NULL; 121706f2543Smrg xf86PciVideoInfo[num - 1] = info; 122706f2543Smrg 123706f2543Smrg pci_device_probe(info); 124706f2543Smrg#ifdef HAVE_PCI_DEVICE_IS_BOOT_VGA 125706f2543Smrg if (pci_device_is_boot_vga(info)) { 126706f2543Smrg primaryBus.type = BUS_PCI; 127706f2543Smrg primaryBus.id.pci = info; 128706f2543Smrg } 129706f2543Smrg#endif 130706f2543Smrg info->user_data = 0; 131706f2543Smrg } 132706f2543Smrg } 133706f2543Smrg free(iter); 134706f2543Smrg 135706f2543Smrg /* If we haven't found a primary device try a different heuristic */ 136706f2543Smrg if (primaryBus.type == BUS_NONE && num) { 137706f2543Smrg for (i = 0; i < num; i++) { 138706f2543Smrg uint16_t command; 139706f2543Smrg 140706f2543Smrg info = xf86PciVideoInfo[i]; 141706f2543Smrg pci_device_cfg_read_u16(info, & command, 4); 142706f2543Smrg 143706f2543Smrg if ((command & PCI_CMD_MEM_ENABLE) 144706f2543Smrg && ((num == 1) || IS_VGA(info->device_class))) { 145706f2543Smrg if (primaryBus.type == BUS_NONE) { 146706f2543Smrg primaryBus.type = BUS_PCI; 147706f2543Smrg primaryBus.id.pci = info; 148706f2543Smrg } else { 149706f2543Smrg xf86Msg(X_NOTICE, 150706f2543Smrg "More than one possible primary device found\n"); 151706f2543Smrg primaryBus.type ^= (BusType)(-1); 152706f2543Smrg } 153706f2543Smrg } 154706f2543Smrg } 155706f2543Smrg } 156706f2543Smrg 157706f2543Smrg /* Print a summary of the video devices found */ 158706f2543Smrg for (k = 0; k < num; k++) { 159706f2543Smrg const char *prim = " "; 160706f2543Smrg Bool memdone = FALSE, iodone = FALSE; 161706f2543Smrg 162706f2543Smrg 163706f2543Smrg info = xf86PciVideoInfo[k]; 164706f2543Smrg 165706f2543Smrg if (!PCIALWAYSPRINTCLASSES(info->device_class)) 166706f2543Smrg continue; 167706f2543Smrg 168706f2543Smrg if (xf86IsPrimaryPci(info)) 169706f2543Smrg prim = "*"; 170706f2543Smrg 171706f2543Smrg xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim, 172706f2543Smrg info->domain, info->bus, info->dev, info->func, 173706f2543Smrg info->vendor_id, info->device_id, 174706f2543Smrg info->subvendor_id, info->subdevice_id); 175706f2543Smrg 176706f2543Smrg xf86ErrorF("rev %d", info->revision); 177706f2543Smrg 178706f2543Smrg for (i = 0; i < 6; i++) { 179706f2543Smrg struct pci_mem_region * r = & info->regions[i]; 180706f2543Smrg 181706f2543Smrg if ( r->size && ! r->is_IO ) { 182706f2543Smrg if (!memdone) { 183706f2543Smrg xf86ErrorF(", Mem @ "); 184706f2543Smrg memdone = TRUE; 185706f2543Smrg } else 186706f2543Smrg xf86ErrorF(", "); 187706f2543Smrg xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); 188706f2543Smrg } 189706f2543Smrg } 190706f2543Smrg 191706f2543Smrg for (i = 0; i < 6; i++) { 192706f2543Smrg struct pci_mem_region * r = & info->regions[i]; 193706f2543Smrg 194706f2543Smrg if ( r->size && r->is_IO ) { 195706f2543Smrg if (!iodone) { 196706f2543Smrg xf86ErrorF(", I/O @ "); 197706f2543Smrg iodone = TRUE; 198706f2543Smrg } else 199706f2543Smrg xf86ErrorF(", "); 200706f2543Smrg xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); 201706f2543Smrg } 202706f2543Smrg } 203706f2543Smrg 204706f2543Smrg if ( info->rom_size ) { 205706f2543Smrg xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size); 206706f2543Smrg } 207706f2543Smrg 208706f2543Smrg xf86ErrorF("\n"); 209706f2543Smrg } 210706f2543Smrg free(xf86PciVideoInfo); 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrg/* 214706f2543Smrg * If the slot requested is already in use, return -1. 215706f2543Smrg * Otherwise, claim the slot for the screen requesting it. 216706f2543Smrg */ 217706f2543Smrg 218706f2543Smrgint 219706f2543Smrgxf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp, 220706f2543Smrg int chipset, GDevPtr dev, Bool active) 221706f2543Smrg{ 222706f2543Smrg EntityPtr p = NULL; 223706f2543Smrg int num; 224706f2543Smrg 225706f2543Smrg if (xf86CheckPciSlot(d)) { 226706f2543Smrg num = xf86AllocateEntity(); 227706f2543Smrg p = xf86Entities[num]; 228706f2543Smrg p->driver = drvp; 229706f2543Smrg p->chipset = chipset; 230706f2543Smrg p->bus.type = BUS_PCI; 231706f2543Smrg p->bus.id.pci = d; 232706f2543Smrg p->active = active; 233706f2543Smrg p->inUse = FALSE; 234706f2543Smrg if (dev) 235706f2543Smrg xf86AddDevToEntity(num, dev); 236706f2543Smrg pciSlotClaimed = TRUE; 237706f2543Smrg 238706f2543Smrg if (active) { 239706f2543Smrg /* Map in this domain's I/O space */ 240706f2543Smrg p->domainIO = xf86MapLegacyIO(d); 241706f2543Smrg } 242706f2543Smrg 243706f2543Smrg return num; 244706f2543Smrg } else 245706f2543Smrg return -1; 246706f2543Smrg} 247706f2543Smrg 248706f2543Smrg/* 249706f2543Smrg * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim. 250706f2543Smrg */ 251706f2543Smrgvoid 252706f2543Smrgxf86UnclaimPciSlot(struct pci_device *d) 253706f2543Smrg{ 254706f2543Smrg int i; 255706f2543Smrg 256706f2543Smrg for (i = 0; i < xf86NumEntities; i++) { 257706f2543Smrg const EntityPtr p = xf86Entities[i]; 258706f2543Smrg 259706f2543Smrg if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { 260706f2543Smrg /* Probably the slot should be deallocated? */ 261706f2543Smrg p->bus.type = BUS_NONE; 262706f2543Smrg return; 263706f2543Smrg } 264706f2543Smrg } 265706f2543Smrg} 266706f2543Smrg 267706f2543Smrg/* 268706f2543Smrg * Parse a BUS ID string, and return the PCI bus parameters if it was 269706f2543Smrg * in the correct format for a PCI bus id. 270706f2543Smrg */ 271706f2543Smrg 272706f2543SmrgBool 273706f2543Smrgxf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) 274706f2543Smrg{ 275706f2543Smrg /* 276706f2543Smrg * The format is assumed to be "bus[@domain]:device[:func]", where domain, 277706f2543Smrg * bus, device and func are decimal integers. domain and func may be 278706f2543Smrg * omitted and assumed to be zero, although doing this isn't encouraged. 279706f2543Smrg */ 280706f2543Smrg 281706f2543Smrg char *p, *s, *d; 282706f2543Smrg const char *id; 283706f2543Smrg int i; 284706f2543Smrg 285706f2543Smrg if (StringToBusType(busID, &id) != BUS_PCI) 286706f2543Smrg return FALSE; 287706f2543Smrg 288706f2543Smrg s = xstrdup(id); 289706f2543Smrg p = strtok(s, ":"); 290706f2543Smrg if (p == NULL || *p == 0) { 291706f2543Smrg free(s); 292706f2543Smrg return FALSE; 293706f2543Smrg } 294706f2543Smrg d = strpbrk(p, "@"); 295706f2543Smrg if (d != NULL) { 296706f2543Smrg *(d++) = 0; 297706f2543Smrg for (i = 0; d[i] != 0; i++) { 298706f2543Smrg if (!isdigit(d[i])) { 299706f2543Smrg free(s); 300706f2543Smrg return FALSE; 301706f2543Smrg } 302706f2543Smrg } 303706f2543Smrg } 304706f2543Smrg for (i = 0; p[i] != 0; i++) { 305706f2543Smrg if (!isdigit(p[i])) { 306706f2543Smrg free(s); 307706f2543Smrg return FALSE; 308706f2543Smrg } 309706f2543Smrg } 310706f2543Smrg *bus = atoi(p); 311706f2543Smrg if (d != NULL && *d != 0) 312706f2543Smrg *bus += atoi(d) << 8; 313706f2543Smrg p = strtok(NULL, ":"); 314706f2543Smrg if (p == NULL || *p == 0) { 315706f2543Smrg free(s); 316706f2543Smrg return FALSE; 317706f2543Smrg } 318706f2543Smrg for (i = 0; p[i] != 0; i++) { 319706f2543Smrg if (!isdigit(p[i])) { 320706f2543Smrg free(s); 321706f2543Smrg return FALSE; 322706f2543Smrg } 323706f2543Smrg } 324706f2543Smrg *device = atoi(p); 325706f2543Smrg *func = 0; 326706f2543Smrg p = strtok(NULL, ":"); 327706f2543Smrg if (p == NULL || *p == 0) { 328706f2543Smrg free(s); 329706f2543Smrg return TRUE; 330706f2543Smrg } 331706f2543Smrg for (i = 0; p[i] != 0; i++) { 332706f2543Smrg if (!isdigit(p[i])) { 333706f2543Smrg free(s); 334706f2543Smrg return FALSE; 335706f2543Smrg } 336706f2543Smrg } 337706f2543Smrg *func = atoi(p); 338706f2543Smrg free(s); 339706f2543Smrg return TRUE; 340706f2543Smrg} 341706f2543Smrg 342706f2543Smrg/* 343706f2543Smrg * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. 344706f2543Smrg */ 345706f2543Smrg 346706f2543SmrgBool 347706f2543Smrgxf86ComparePciBusString(const char *busID, int bus, int device, int func) 348706f2543Smrg{ 349706f2543Smrg int ibus, idevice, ifunc; 350706f2543Smrg 351706f2543Smrg if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { 352706f2543Smrg return bus == ibus && device == idevice && func == ifunc; 353706f2543Smrg } else { 354706f2543Smrg return FALSE; 355706f2543Smrg } 356706f2543Smrg} 357706f2543Smrg 358706f2543Smrg/* 359706f2543Smrg * xf86IsPrimaryPci() -- return TRUE if primary device 360706f2543Smrg * is PCI and bus, dev and func numbers match. 361706f2543Smrg */ 362706f2543Smrg 363706f2543SmrgBool 364706f2543Smrgxf86IsPrimaryPci(struct pci_device *pPci) 365706f2543Smrg{ 366706f2543Smrg return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci)); 367706f2543Smrg} 368706f2543Smrg 369706f2543Smrg/* 370706f2543Smrg * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. 371706f2543Smrg */ 372706f2543Smrgstruct pci_device * 373706f2543Smrgxf86GetPciInfoForEntity(int entityIndex) 374706f2543Smrg{ 375706f2543Smrg EntityPtr p; 376706f2543Smrg 377706f2543Smrg if (entityIndex >= xf86NumEntities) 378706f2543Smrg return NULL; 379706f2543Smrg 380706f2543Smrg p = xf86Entities[entityIndex]; 381706f2543Smrg return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; 382706f2543Smrg} 383706f2543Smrg 384706f2543Smrg/* 385706f2543Smrg * xf86CheckPciMemBase() checks that the memory base value matches one of the 386706f2543Smrg * PCI base address register values for the given PCI device. 387706f2543Smrg */ 388706f2543SmrgBool 389706f2543Smrgxf86CheckPciMemBase( struct pci_device * pPci, memType base ) 390706f2543Smrg{ 391706f2543Smrg int i; 392706f2543Smrg 393706f2543Smrg for (i = 0; i < 6; i++) 394706f2543Smrg if (base == pPci->regions[i].base_addr) 395706f2543Smrg return TRUE; 396706f2543Smrg return FALSE; 397706f2543Smrg} 398706f2543Smrg 399706f2543Smrg/* 400706f2543Smrg * Check if the slot requested is free. If it is already in use, return FALSE. 401706f2543Smrg */ 402706f2543Smrg 403706f2543SmrgBool 404706f2543Smrgxf86CheckPciSlot(const struct pci_device *d) 405706f2543Smrg{ 406706f2543Smrg int i; 407706f2543Smrg 408706f2543Smrg for (i = 0; i < xf86NumEntities; i++) { 409706f2543Smrg const EntityPtr p = xf86Entities[i]; 410706f2543Smrg 411706f2543Smrg if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { 412706f2543Smrg return FALSE; 413706f2543Smrg } 414706f2543Smrg } 415706f2543Smrg return TRUE; 416706f2543Smrg} 417706f2543Smrg 418706f2543Smrg#define END_OF_MATCHES(m) \ 419706f2543Smrg (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) 420706f2543Smrg 421706f2543SmrgBool 422706f2543Smrgxf86PciAddMatchingDev(DriverPtr drvp) 423706f2543Smrg{ 424706f2543Smrg const struct pci_id_match * const devices = drvp->supported_devices; 425706f2543Smrg int j; 426706f2543Smrg struct pci_device *pPci; 427706f2543Smrg struct pci_device_iterator *iter; 428706f2543Smrg int numFound = 0; 429706f2543Smrg 430706f2543Smrg 431706f2543Smrg iter = pci_id_match_iterator_create(NULL); 432706f2543Smrg while ((pPci = pci_device_next(iter)) != NULL) { 433706f2543Smrg /* Determine if this device is supported by the driver. If it is, 434706f2543Smrg * add it to the list of devices to configure. 435706f2543Smrg */ 436706f2543Smrg for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { 437706f2543Smrg if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) 438706f2543Smrg && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) 439706f2543Smrg && ((devices[j].device_class_mask & pPci->device_class) 440706f2543Smrg == devices[j].device_class) ) { 441706f2543Smrg if (xf86CheckPciSlot(pPci)) { 442706f2543Smrg GDevPtr pGDev = xf86AddBusDeviceToConfigure( 443706f2543Smrg drvp->driverName, BUS_PCI, pPci, -1); 444706f2543Smrg if (pGDev != NULL) { 445706f2543Smrg /* After configure pass 1, chipID and chipRev are 446706f2543Smrg * treated as over-rides, so clobber them here. 447706f2543Smrg */ 448706f2543Smrg pGDev->chipID = -1; 449706f2543Smrg pGDev->chipRev = -1; 450706f2543Smrg } 451706f2543Smrg 452706f2543Smrg numFound++; 453706f2543Smrg } 454706f2543Smrg 455706f2543Smrg break; 456706f2543Smrg } 457706f2543Smrg } 458706f2543Smrg } 459706f2543Smrg 460706f2543Smrg pci_iterator_destroy(iter); 461706f2543Smrg 462706f2543Smrg return numFound != 0; 463706f2543Smrg} 464706f2543Smrg 465706f2543SmrgBool 466706f2543Smrgxf86PciProbeDev(DriverPtr drvp) 467706f2543Smrg{ 468706f2543Smrg int i, j; 469706f2543Smrg struct pci_device * pPci; 470706f2543Smrg Bool foundScreen = FALSE; 471706f2543Smrg const struct pci_id_match * const devices = drvp->supported_devices; 472706f2543Smrg GDevPtr *devList; 473706f2543Smrg const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); 474706f2543Smrg 475706f2543Smrg for ( i = 0 ; i < numDevs ; i++ ) { 476706f2543Smrg struct pci_device_iterator *iter; 477706f2543Smrg unsigned device_id; 478706f2543Smrg 479706f2543Smrg 480706f2543Smrg /* Find the pciVideoRec associated with this device section. 481706f2543Smrg */ 482706f2543Smrg iter = pci_id_match_iterator_create(NULL); 483706f2543Smrg while ((pPci = pci_device_next(iter)) != NULL) { 484706f2543Smrg if (devList[i]->busID && *devList[i]->busID) { 485706f2543Smrg if (xf86ComparePciBusString(devList[i]->busID, 486706f2543Smrg ((pPci->domain << 8) 487706f2543Smrg | pPci->bus), 488706f2543Smrg pPci->dev, 489706f2543Smrg pPci->func)) { 490706f2543Smrg break; 491706f2543Smrg } 492706f2543Smrg } 493706f2543Smrg else if (xf86IsPrimaryPci(pPci)) { 494706f2543Smrg break; 495706f2543Smrg } 496706f2543Smrg } 497706f2543Smrg 498706f2543Smrg pci_iterator_destroy(iter); 499706f2543Smrg 500706f2543Smrg if (pPci == NULL) { 501706f2543Smrg continue; 502706f2543Smrg } 503706f2543Smrg device_id = (devList[i]->chipID > 0) 504706f2543Smrg ? devList[i]->chipID : pPci->device_id; 505706f2543Smrg 506706f2543Smrg 507706f2543Smrg /* Once the pciVideoRec is found, determine if the device is supported 508706f2543Smrg * by the driver. If it is, probe it! 509706f2543Smrg */ 510706f2543Smrg for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { 511706f2543Smrg if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) 512706f2543Smrg && PCI_ID_COMPARE( devices[j].device_id, device_id ) 513706f2543Smrg && ((devices[j].device_class_mask & pPci->device_class) 514706f2543Smrg == devices[j].device_class) ) { 515706f2543Smrg int entry; 516706f2543Smrg 517706f2543Smrg /* Allow the same entity to be used more than once for 518706f2543Smrg * devices with multiple screens per entity. This assumes 519706f2543Smrg * implicitly that there will be a screen == 0 instance. 520706f2543Smrg * 521706f2543Smrg * FIXME Need to make sure that two different drivers don't 522706f2543Smrg * FIXME claim the same screen > 0 instance. 523706f2543Smrg */ 524706f2543Smrg if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci)) 525706f2543Smrg continue; 526706f2543Smrg 527706f2543Smrg DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", 528706f2543Smrg drvp->driverName, pPci->bus, pPci->dev, pPci->func); 529706f2543Smrg 530706f2543Smrg /* Allocate an entry in the lists to be returned */ 531706f2543Smrg entry = xf86ClaimPciSlot(pPci, drvp, device_id, 532706f2543Smrg devList[i], devList[i]->active); 533706f2543Smrg 534706f2543Smrg if ((entry == -1) && (devList[i]->screen > 0)) { 535706f2543Smrg unsigned k; 536706f2543Smrg 537706f2543Smrg for (k = 0; k < xf86NumEntities; k++ ) { 538706f2543Smrg EntityPtr pEnt = xf86Entities[k]; 539706f2543Smrg if (pEnt->bus.type != BUS_PCI) 540706f2543Smrg continue; 541706f2543Smrg if (pEnt->bus.id.pci == pPci) { 542706f2543Smrg entry = k; 543706f2543Smrg xf86AddDevToEntity(k, devList[i]); 544706f2543Smrg break; 545706f2543Smrg } 546706f2543Smrg } 547706f2543Smrg } 548706f2543Smrg 549706f2543Smrg if (entry != -1) { 550706f2543Smrg if ((*drvp->PciProbe)(drvp, entry, pPci, 551706f2543Smrg devices[j].match_data)) { 552706f2543Smrg foundScreen = TRUE; 553706f2543Smrg } else 554706f2543Smrg xf86UnclaimPciSlot(pPci); 555706f2543Smrg } 556706f2543Smrg 557706f2543Smrg break; 558706f2543Smrg } 559706f2543Smrg } 560706f2543Smrg } 561706f2543Smrg free(devList); 562706f2543Smrg 563706f2543Smrg return foundScreen; 564706f2543Smrg} 565706f2543Smrg 566706f2543Smrgvoid 567706f2543Smrgxf86PciIsolateDevice(char *argument) 568706f2543Smrg{ 569706f2543Smrg int bus, device, func; 570706f2543Smrg 571706f2543Smrg if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { 572706f2543Smrg xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); 573706f2543Smrg xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); 574706f2543Smrg xf86IsolateDevice.dev = device; 575706f2543Smrg xf86IsolateDevice.func = func; 576706f2543Smrg } else 577706f2543Smrg FatalError("Invalid isolated device specification\n"); 578706f2543Smrg} 579706f2543Smrg 580706f2543Smrgstatic Bool 581706f2543SmrgpciDeviceHasBars(struct pci_device *pci) 582706f2543Smrg{ 583706f2543Smrg int i; 584706f2543Smrg 585706f2543Smrg for (i = 0; i < 6; i++) 586706f2543Smrg if (pci->regions[i].size) 587706f2543Smrg return TRUE; 588706f2543Smrg 589706f2543Smrg if (pci->rom_size) 590706f2543Smrg return TRUE; 591706f2543Smrg 592706f2543Smrg return FALSE; 593706f2543Smrg} 594706f2543Smrg 595706f2543Smrgstruct Inst { 596706f2543Smrg struct pci_device * pci; 597706f2543Smrg GDevPtr dev; 598706f2543Smrg Bool foundHW; /* PCIid in list of supported chipsets */ 599706f2543Smrg Bool claimed; /* BusID matches with a device section */ 600706f2543Smrg int chip; 601706f2543Smrg int screen; 602706f2543Smrg}; 603706f2543Smrg 604706f2543Smrg 605706f2543Smrg/** 606706f2543Smrg * Find set of unclaimed devices matching a given vendor ID. 607706f2543Smrg * 608706f2543Smrg * Used by drivers to find as yet unclaimed devices matching the specified 609706f2543Smrg * vendor ID. 610706f2543Smrg * 611706f2543Smrg * \param driverName Name of the driver. This is used to find Device 612706f2543Smrg * sections in the config file. 613706f2543Smrg * \param vendorID PCI vendor ID of associated devices. If zero, then 614706f2543Smrg * the true vendor ID must be encoded in the \c PCIid 615706f2543Smrg * fields of the \c PCIchipsets entries. 616706f2543Smrg * \param chipsets Symbol table used to associate chipset names with 617706f2543Smrg * PCI IDs. 618706f2543Smrg * \param devList List of Device sections parsed from the config file. 619706f2543Smrg * \param numDevs Number of entries in \c devList. 620706f2543Smrg * \param drvp Pointer the driver's control structure. 621706f2543Smrg * \param foundEntities Returned list of entity indicies associated with the 622706f2543Smrg * driver. 623706f2543Smrg * 624706f2543Smrg * \returns 625706f2543Smrg * The number of elements in returned in \c foundEntities on success or zero 626706f2543Smrg * on failure. 627706f2543Smrg * 628706f2543Smrg * \todo 629706f2543Smrg * This function does a bit more than short description says. Fill in some 630706f2543Smrg * more of the details of its operation. 631706f2543Smrg * 632706f2543Smrg * \todo 633706f2543Smrg * The \c driverName parameter is redundant. It is the same as 634706f2543Smrg * \c DriverRec::driverName. In a future version of this function, remove 635706f2543Smrg * that parameter. 636706f2543Smrg */ 637706f2543Smrgint 638706f2543Smrgxf86MatchPciInstances(const char *driverName, int vendorID, 639706f2543Smrg SymTabPtr chipsets, PciChipsets *PCIchipsets, 640706f2543Smrg GDevPtr *devList, int numDevs, DriverPtr drvp, 641706f2543Smrg int **foundEntities) 642706f2543Smrg{ 643706f2543Smrg int i,j; 644706f2543Smrg struct pci_device * pPci; 645706f2543Smrg struct pci_device_iterator *iter; 646706f2543Smrg struct Inst *instances = NULL; 647706f2543Smrg int numClaimedInstances = 0; 648706f2543Smrg int allocatedInstances = 0; 649706f2543Smrg int numFound = 0; 650706f2543Smrg SymTabRec *c; 651706f2543Smrg PciChipsets *id; 652706f2543Smrg int *retEntities = NULL; 653706f2543Smrg 654706f2543Smrg *foundEntities = NULL; 655706f2543Smrg 656706f2543Smrg 657706f2543Smrg /* Each PCI device will contribute at least one entry. Each device 658706f2543Smrg * section can contribute at most one entry. The sum of the two is 659706f2543Smrg * guaranteed to be larger than the maximum possible number of entries. 660706f2543Smrg * Do this calculation and memory allocation once now to eliminate the 661706f2543Smrg * need for realloc calls inside the loop. 662706f2543Smrg */ 663706f2543Smrg if (!(xf86DoConfigure && xf86DoConfigurePass1)) { 664706f2543Smrg unsigned max_entries = numDevs; 665706f2543Smrg 666706f2543Smrg iter = pci_slot_match_iterator_create(NULL); 667706f2543Smrg while ((pPci = pci_device_next(iter)) != NULL) { 668706f2543Smrg max_entries++; 669706f2543Smrg } 670706f2543Smrg 671706f2543Smrg pci_iterator_destroy(iter); 672706f2543Smrg instances = xnfalloc(max_entries * sizeof(struct Inst)); 673706f2543Smrg } 674706f2543Smrg 675706f2543Smrg iter = pci_slot_match_iterator_create(NULL); 676706f2543Smrg while ((pPci = pci_device_next(iter)) != NULL) { 677706f2543Smrg unsigned device_class = pPci->device_class; 678706f2543Smrg Bool foundVendor = FALSE; 679706f2543Smrg 680706f2543Smrg 681706f2543Smrg /* Convert the pre-PCI 2.0 device class for a VGA adapter to the 682706f2543Smrg * 2.0 version of the same class. 683706f2543Smrg */ 684706f2543Smrg if ( device_class == 0x00000101 ) { 685706f2543Smrg device_class = 0x00030000; 686706f2543Smrg } 687706f2543Smrg 688706f2543Smrg 689706f2543Smrg /* Find PCI devices that match the given vendor ID. The vendor ID is 690706f2543Smrg * either specified explicitly as a parameter to the function or 691706f2543Smrg * implicitly encoded in the high bits of id->PCIid. 692706f2543Smrg * 693706f2543Smrg * The first device with a matching vendor is recorded, even if the 694706f2543Smrg * device ID doesn't match. This is done because the Device section 695706f2543Smrg * in the xorg.conf file can over-ride the device ID. A matching PCI 696706f2543Smrg * ID might not be found now, but after the device ID over-ride is 697706f2543Smrg * applied there /might/ be a match. 698706f2543Smrg */ 699706f2543Smrg for (id = PCIchipsets; id->PCIid != -1; id++) { 700706f2543Smrg const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16) 701706f2543Smrg | vendorID; 702706f2543Smrg const unsigned device_id = (id->PCIid & 0x0000FFFF); 703706f2543Smrg const unsigned match_class = 0x00030000 | id->PCIid; 704706f2543Smrg 705706f2543Smrg if ((vendor_id == pPci->vendor_id) 706706f2543Smrg || ((vendorID == PCI_VENDOR_GENERIC) && (match_class == device_class))) { 707706f2543Smrg if (!foundVendor && (instances != NULL)) { 708706f2543Smrg ++allocatedInstances; 709706f2543Smrg instances[allocatedInstances - 1].pci = pPci; 710706f2543Smrg instances[allocatedInstances - 1].dev = NULL; 711706f2543Smrg instances[allocatedInstances - 1].claimed = FALSE; 712706f2543Smrg instances[allocatedInstances - 1].foundHW = FALSE; 713706f2543Smrg instances[allocatedInstances - 1].screen = 0; 714706f2543Smrg } 715706f2543Smrg 716706f2543Smrg foundVendor = TRUE; 717706f2543Smrg 718706f2543Smrg if ( (device_id == pPci->device_id) 719706f2543Smrg || ((vendorID == PCI_VENDOR_GENERIC) 720706f2543Smrg && (match_class == device_class)) ) { 721706f2543Smrg if ( instances != NULL ) { 722706f2543Smrg instances[allocatedInstances - 1].foundHW = TRUE; 723706f2543Smrg instances[allocatedInstances - 1].chip = id->numChipset; 724706f2543Smrg } 725706f2543Smrg 726706f2543Smrg 727706f2543Smrg if ( xf86DoConfigure && xf86DoConfigurePass1 ) { 728706f2543Smrg if (xf86CheckPciSlot(pPci)) { 729706f2543Smrg GDevPtr pGDev = 730706f2543Smrg xf86AddBusDeviceToConfigure(drvp->driverName, 731706f2543Smrg BUS_PCI, pPci, -1); 732706f2543Smrg if (pGDev) { 733706f2543Smrg /* After configure pass 1, chipID and chipRev 734706f2543Smrg * are treated as over-rides, so clobber them 735706f2543Smrg * here. 736706f2543Smrg */ 737706f2543Smrg pGDev->chipID = -1; 738706f2543Smrg pGDev->chipRev = -1; 739706f2543Smrg } 740706f2543Smrg 741706f2543Smrg numFound++; 742706f2543Smrg } 743706f2543Smrg } 744706f2543Smrg else { 745706f2543Smrg numFound++; 746706f2543Smrg } 747706f2543Smrg 748706f2543Smrg break; 749706f2543Smrg } 750706f2543Smrg } 751706f2543Smrg } 752706f2543Smrg } 753706f2543Smrg 754706f2543Smrg pci_iterator_destroy(iter); 755706f2543Smrg 756706f2543Smrg 757706f2543Smrg /* In "probe only" or "configure" mode (signaled by instances being NULL), 758706f2543Smrg * our work is done. Return the number of detected devices. 759706f2543Smrg */ 760706f2543Smrg if ( instances == NULL ) { 761706f2543Smrg return numFound; 762706f2543Smrg } 763706f2543Smrg 764706f2543Smrg 765706f2543Smrg /* 766706f2543Smrg * This may be debatable, but if no PCI devices with a matching vendor 767706f2543Smrg * type is found, return zero now. It is probably not desirable to 768706f2543Smrg * allow the config file to override this. 769706f2543Smrg */ 770706f2543Smrg if (allocatedInstances <= 0) { 771706f2543Smrg free(instances); 772706f2543Smrg return 0; 773706f2543Smrg } 774706f2543Smrg 775706f2543Smrg 776706f2543Smrg DebugF("%s instances found: %d\n", driverName, allocatedInstances); 777706f2543Smrg 778706f2543Smrg /* 779706f2543Smrg * Check for devices that need duplicated instances. This is required 780706f2543Smrg * when there is more than one screen per entity. 781706f2543Smrg * 782706f2543Smrg * XXX This currently doesn't work for cases where the BusID isn't 783706f2543Smrg * specified explicitly in the config file. 784706f2543Smrg */ 785706f2543Smrg 786706f2543Smrg for (j = 0; j < numDevs; j++) { 787706f2543Smrg if (devList[j]->screen > 0 && devList[j]->busID 788706f2543Smrg && *devList[j]->busID) { 789706f2543Smrg for (i = 0; i < allocatedInstances; i++) { 790706f2543Smrg pPci = instances[i].pci; 791706f2543Smrg if (xf86ComparePciBusString(devList[j]->busID, 792706f2543Smrg PCI_MAKE_BUS( pPci->domain, pPci->bus ), 793706f2543Smrg pPci->dev, 794706f2543Smrg pPci->func)) { 795706f2543Smrg allocatedInstances++; 796706f2543Smrg instances[allocatedInstances - 1] = instances[i]; 797706f2543Smrg instances[allocatedInstances - 1].screen = devList[j]->screen; 798706f2543Smrg numFound++; 799706f2543Smrg break; 800706f2543Smrg } 801706f2543Smrg } 802706f2543Smrg } 803706f2543Smrg } 804706f2543Smrg 805706f2543Smrg for (i = 0; i < allocatedInstances; i++) { 806706f2543Smrg GDevPtr dev = NULL; 807706f2543Smrg GDevPtr devBus = NULL; 808706f2543Smrg 809706f2543Smrg pPci = instances[i].pci; 810706f2543Smrg for (j = 0; j < numDevs; j++) { 811706f2543Smrg if (devList[j]->busID && *devList[j]->busID) { 812706f2543Smrg if (xf86ComparePciBusString(devList[j]->busID, 813706f2543Smrg PCI_MAKE_BUS( pPci->domain, pPci->bus ), 814706f2543Smrg pPci->dev, 815706f2543Smrg pPci->func) && 816706f2543Smrg devList[j]->screen == instances[i].screen) { 817706f2543Smrg 818706f2543Smrg if (devBus) 819706f2543Smrg xf86MsgVerb(X_WARNING,0, 820706f2543Smrg "%s: More than one matching Device section for " 821706f2543Smrg "instances\n\t(BusID: %s) found: %s\n", 822706f2543Smrg driverName, devList[j]->busID, 823706f2543Smrg devList[j]->identifier); 824706f2543Smrg else 825706f2543Smrg devBus = devList[j]; 826706f2543Smrg } 827706f2543Smrg } else { 828706f2543Smrg /* 829706f2543Smrg * if device section without BusID is found 830706f2543Smrg * only assign to it to the primary device. 831706f2543Smrg */ 832706f2543Smrg if (xf86IsPrimaryPci(pPci)) { 833706f2543Smrg xf86Msg(X_PROBED, "Assigning device section with no busID" 834706f2543Smrg " to primary device\n"); 835706f2543Smrg if (dev || devBus) 836706f2543Smrg xf86MsgVerb(X_WARNING, 0, 837706f2543Smrg "%s: More than one matching Device section " 838706f2543Smrg "found: %s\n", driverName, devList[j]->identifier); 839706f2543Smrg else 840706f2543Smrg dev = devList[j]; 841706f2543Smrg } 842706f2543Smrg } 843706f2543Smrg } 844706f2543Smrg if (devBus) dev = devBus; /* busID preferred */ 845706f2543Smrg if (!dev) { 846706f2543Smrg if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) { 847706f2543Smrg xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 848706f2543Smrg "for instance (BusID PCI:%u@%u:%u:%u) found\n", 849706f2543Smrg driverName, pPci->domain, pPci->bus, pPci->dev, 850706f2543Smrg pPci->func); 851706f2543Smrg } 852706f2543Smrg } else { 853706f2543Smrg numClaimedInstances++; 854706f2543Smrg instances[i].claimed = TRUE; 855706f2543Smrg instances[i].dev = dev; 856706f2543Smrg } 857706f2543Smrg } 858706f2543Smrg DebugF("%s instances found: %d\n", driverName, numClaimedInstances); 859706f2543Smrg /* 860706f2543Smrg * Now check that a chipset or chipID override in the device section 861706f2543Smrg * is valid. Chipset has precedence over chipID. 862706f2543Smrg * If chipset is not valid ignore BusSlot completely. 863706f2543Smrg */ 864706f2543Smrg for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 865706f2543Smrg MessageType from = X_PROBED; 866706f2543Smrg 867706f2543Smrg if (!instances[i].claimed) { 868706f2543Smrg continue; 869706f2543Smrg } 870706f2543Smrg if (instances[i].dev->chipset) { 871706f2543Smrg for (c = chipsets; c->token >= 0; c++) { 872706f2543Smrg if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0) 873706f2543Smrg break; 874706f2543Smrg } 875706f2543Smrg if (c->token == -1) { 876706f2543Smrg instances[i].claimed = FALSE; 877706f2543Smrg numClaimedInstances--; 878706f2543Smrg xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " 879706f2543Smrg "section \"%s\" isn't valid for this driver\n", 880706f2543Smrg driverName, instances[i].dev->chipset, 881706f2543Smrg instances[i].dev->identifier); 882706f2543Smrg } else { 883706f2543Smrg instances[i].chip = c->token; 884706f2543Smrg 885706f2543Smrg for (id = PCIchipsets; id->numChipset >= 0; id++) { 886706f2543Smrg if (id->numChipset == instances[i].chip) 887706f2543Smrg break; 888706f2543Smrg } 889706f2543Smrg if(id->numChipset >=0){ 890706f2543Smrg xf86Msg(X_CONFIG,"Chipset override: %s\n", 891706f2543Smrg instances[i].dev->chipset); 892706f2543Smrg from = X_CONFIG; 893706f2543Smrg } else { 894706f2543Smrg instances[i].claimed = FALSE; 895706f2543Smrg numClaimedInstances--; 896706f2543Smrg xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " 897706f2543Smrg "section \"%s\" isn't a valid PCI chipset\n", 898706f2543Smrg driverName, instances[i].dev->chipset, 899706f2543Smrg instances[i].dev->identifier); 900706f2543Smrg } 901706f2543Smrg } 902706f2543Smrg } else if (instances[i].dev->chipID > 0) { 903706f2543Smrg for (id = PCIchipsets; id->numChipset >= 0; id++) { 904706f2543Smrg if (id->PCIid == instances[i].dev->chipID) 905706f2543Smrg break; 906706f2543Smrg } 907706f2543Smrg if (id->numChipset == -1) { 908706f2543Smrg instances[i].claimed = FALSE; 909706f2543Smrg numClaimedInstances--; 910706f2543Smrg xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device " 911706f2543Smrg "section \"%s\" isn't valid for this driver\n", 912706f2543Smrg driverName, instances[i].dev->chipID, 913706f2543Smrg instances[i].dev->identifier); 914706f2543Smrg } else { 915706f2543Smrg instances[i].chip = id->numChipset; 916706f2543Smrg 917706f2543Smrg xf86Msg( X_CONFIG,"ChipID override: 0x%04X\n", 918706f2543Smrg instances[i].dev->chipID); 919706f2543Smrg from = X_CONFIG; 920706f2543Smrg } 921706f2543Smrg } else if (!instances[i].foundHW) { 922706f2543Smrg /* 923706f2543Smrg * This means that there was no override and the PCI chipType 924706f2543Smrg * doesn't match one that is supported 925706f2543Smrg */ 926706f2543Smrg instances[i].claimed = FALSE; 927706f2543Smrg numClaimedInstances--; 928706f2543Smrg } 929706f2543Smrg if (instances[i].claimed == TRUE){ 930706f2543Smrg for (c = chipsets; c->token >= 0; c++) { 931706f2543Smrg if (c->token == instances[i].chip) 932706f2543Smrg break; 933706f2543Smrg } 934706f2543Smrg xf86Msg(from,"Chipset %s found\n", 935706f2543Smrg c->name); 936706f2543Smrg } 937706f2543Smrg } 938706f2543Smrg 939706f2543Smrg /* 940706f2543Smrg * Of the claimed instances, check that another driver hasn't already 941706f2543Smrg * claimed its slot. 942706f2543Smrg */ 943706f2543Smrg numFound = 0; 944706f2543Smrg for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 945706f2543Smrg if (!instances[i].claimed) 946706f2543Smrg continue; 947706f2543Smrg pPci = instances[i].pci; 948706f2543Smrg 949706f2543Smrg 950706f2543Smrg /* 951706f2543Smrg * Allow the same entity to be used more than once for devices with 952706f2543Smrg * multiple screens per entity. This assumes implicitly that there 953706f2543Smrg * will be a screen == 0 instance. 954706f2543Smrg * 955706f2543Smrg * XXX Need to make sure that two different drivers don't claim 956706f2543Smrg * the same screen > 0 instance. 957706f2543Smrg */ 958706f2543Smrg if (instances[i].screen == 0 && !xf86CheckPciSlot( pPci )) 959706f2543Smrg continue; 960706f2543Smrg 961706f2543Smrg DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", 962706f2543Smrg driverName, pPci->bus, pPci->dev, pPci->func); 963706f2543Smrg 964706f2543Smrg /* Allocate an entry in the lists to be returned */ 965706f2543Smrg numFound++; 966706f2543Smrg retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); 967706f2543Smrg retEntities[numFound - 1] = xf86ClaimPciSlot( pPci, drvp, 968706f2543Smrg instances[i].chip, 969706f2543Smrg instances[i].dev, 970706f2543Smrg instances[i].dev->active); 971706f2543Smrg if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) { 972706f2543Smrg for (j = 0; j < xf86NumEntities; j++) { 973706f2543Smrg EntityPtr pEnt = xf86Entities[j]; 974706f2543Smrg if (pEnt->bus.type != BUS_PCI) 975706f2543Smrg continue; 976706f2543Smrg if (pEnt->bus.id.pci == pPci) { 977706f2543Smrg retEntities[numFound - 1] = j; 978706f2543Smrg xf86AddDevToEntity(j, instances[i].dev); 979706f2543Smrg break; 980706f2543Smrg } 981706f2543Smrg } 982706f2543Smrg } 983706f2543Smrg } 984706f2543Smrg free(instances); 985706f2543Smrg if (numFound > 0) { 986706f2543Smrg *foundEntities = retEntities; 987706f2543Smrg } 988706f2543Smrg 989706f2543Smrg return numFound; 990706f2543Smrg} 991706f2543Smrg 992706f2543Smrg/* 993706f2543Smrg * xf86ConfigPciEntityInactive() -- This function can be used 994706f2543Smrg * to configure an inactive entity as well as to reconfigure an 995706f2543Smrg * previously active entity inactive. If the entity has been 996706f2543Smrg * assigned to a screen before it will be removed. If p_chip is 997706f2543Smrg * non-NULL all static resources listed there will be registered. 998706f2543Smrg */ 999706f2543Smrgstatic void 1000706f2543Smrgxf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets *p_chip, 1001706f2543Smrg EntityProc init, EntityProc enter, 1002706f2543Smrg EntityProc leave, pointer private) 1003706f2543Smrg{ 1004706f2543Smrg ScrnInfoPtr pScrn; 1005706f2543Smrg 1006706f2543Smrg if ((pScrn = xf86FindScreenForEntity(pEnt->index))) 1007706f2543Smrg xf86RemoveEntityFromScreen(pScrn,pEnt->index); 1008706f2543Smrg 1009706f2543Smrg /* shared resources are only needed when entity is active: remove */ 1010706f2543Smrg xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); 1011706f2543Smrg} 1012706f2543Smrg 1013706f2543SmrgScrnInfoPtr 1014706f2543Smrgxf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, 1015706f2543Smrg PciChipsets *p_chip, void *dummy, EntityProc init, 1016706f2543Smrg EntityProc enter, EntityProc leave, pointer private) 1017706f2543Smrg{ 1018706f2543Smrg EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); 1019706f2543Smrg if (!pEnt) return pScrn; 1020706f2543Smrg 1021706f2543Smrg if (!(pEnt->location.type == BUS_PCI) 1022706f2543Smrg || !xf86GetPciInfoForEntity(entityIndex)) { 1023706f2543Smrg free(pEnt); 1024706f2543Smrg return pScrn; 1025706f2543Smrg } 1026706f2543Smrg if (!pEnt->active) { 1027706f2543Smrg xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, 1028706f2543Smrg leave, private); 1029706f2543Smrg free(pEnt); 1030706f2543Smrg return pScrn; 1031706f2543Smrg } 1032706f2543Smrg 1033706f2543Smrg if (!pScrn) 1034706f2543Smrg pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); 1035706f2543Smrg if (xf86IsEntitySharable(entityIndex)) { 1036706f2543Smrg xf86SetEntityShared(entityIndex); 1037706f2543Smrg } 1038706f2543Smrg xf86AddEntityToScreen(pScrn,entityIndex); 1039706f2543Smrg if (xf86IsEntityShared(entityIndex)) { 1040706f2543Smrg return pScrn; 1041706f2543Smrg } 1042706f2543Smrg free(pEnt); 1043706f2543Smrg 1044706f2543Smrg xf86SetEntityFuncs(entityIndex,init,enter,leave,private); 1045706f2543Smrg 1046706f2543Smrg return pScrn; 1047706f2543Smrg} 1048706f2543Smrg 1049706f2543Smrg/* 1050706f2543Smrg * OBSOLETE ! xf86ConfigActivePciEntity() is an obsolete function. 1051706f2543Smrg * It is likely to be removed. Don't use! 1052706f2543Smrg */ 1053706f2543SmrgBool 1054706f2543Smrgxf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex, 1055706f2543Smrg PciChipsets *p_chip, void *dummy, EntityProc init, 1056706f2543Smrg EntityProc enter, EntityProc leave, pointer private) 1057706f2543Smrg{ 1058706f2543Smrg EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); 1059706f2543Smrg if (!pEnt) return FALSE; 1060706f2543Smrg 1061706f2543Smrg if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) { 1062706f2543Smrg free(pEnt); 1063706f2543Smrg return FALSE; 1064706f2543Smrg } 1065706f2543Smrg xf86AddEntityToScreen(pScrn,entityIndex); 1066706f2543Smrg 1067706f2543Smrg free(pEnt); 1068706f2543Smrg if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private)) 1069706f2543Smrg return FALSE; 1070706f2543Smrg 1071706f2543Smrg return TRUE; 1072706f2543Smrg} 1073706f2543Smrg 1074706f2543Smrgstatic int 1075706f2543SmrgvideoPtrToDriverList(struct pci_device *dev, 1076706f2543Smrg char *returnList[], int returnListMax) 1077706f2543Smrg{ 1078706f2543Smrg int i; 1079706f2543Smrg /* Add more entries here if we ever return more than 4 drivers for 1080706f2543Smrg any device */ 1081706f2543Smrg char *driverList[5] = { NULL, NULL, NULL, NULL, NULL }; 1082706f2543Smrg 1083706f2543Smrg switch (dev->vendor_id) 1084706f2543Smrg { 1085706f2543Smrg /* AMD Geode LX */ 1086706f2543Smrg case 0x1022: 1087706f2543Smrg if (dev->device_id == 0x2081) 1088706f2543Smrg driverList[0] = "geode"; 1089706f2543Smrg break; 1090706f2543Smrg /* older Geode products acquired by AMD still carry an NSC vendor_id */ 1091706f2543Smrg case 0x100b: 1092706f2543Smrg if (dev->device_id == 0x0030) { 1093706f2543Smrg /* NSC Geode GX2 specifically */ 1094706f2543Smrg driverList[0] = "geode"; 1095706f2543Smrg /* GX2 support started its life in the NSC tree and was later 1096706f2543Smrg forked by AMD for GEODE so we keep it as a backup */ 1097706f2543Smrg driverList[1] = "nsc"; 1098706f2543Smrg } else 1099706f2543Smrg /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */ 1100706f2543Smrg driverList[0] = "nsc"; 1101706f2543Smrg break; 1102706f2543Smrg /* Cyrix Geode GX1 */ 1103706f2543Smrg case 0x1078: 1104706f2543Smrg if (dev->device_id == 0x0104) 1105706f2543Smrg driverList[0] = "cyrix"; 1106706f2543Smrg break; 1107706f2543Smrg case 0x1142: driverList[0] = "apm"; break; 1108706f2543Smrg case 0xedd8: driverList[0] = "ark"; break; 1109706f2543Smrg case 0x1a03: driverList[0] = "ast"; break; 1110706f2543Smrg case 0x1002: driverList[0] = "ati"; break; 1111706f2543Smrg case 0x102c: driverList[0] = "chips"; break; 1112706f2543Smrg case 0x1013: driverList[0] = "cirrus"; break; 1113706f2543Smrg case 0x3d3d: driverList[0] = "glint"; break; 1114706f2543Smrg case 0x105d: driverList[0] = "i128"; break; 1115706f2543Smrg case 0x8086: 1116706f2543Smrg if ((dev->device_id == 0x00d1) || (dev->device_id == 0x7800)) { 1117706f2543Smrg driverList[0] = "i740"; 1118706f2543Smrg } else if (dev->device_id == 0x8108) { 1119706f2543Smrg break; /* "hooray" for poulsbo */ 1120706f2543Smrg } else { 1121706f2543Smrg driverList[0] = "intel"; 1122706f2543Smrg } 1123706f2543Smrg break; 1124706f2543Smrg case 0x102b: driverList[0] = "mga"; break; 1125706f2543Smrg case 0x10c8: driverList[0] = "neomagic"; break; 1126706f2543Smrg case 0x10de: 1127706f2543Smrg case 0x12d2: 1128706f2543Smrg driverList[0] = "nouveau"; 1129706f2543Smrg driverList[1] = "nv"; 1130706f2543Smrg break; 1131706f2543Smrg case 0x1106: driverList[0] = "openchrome"; break; 1132706f2543Smrg case 0x1b36: driverList[0] = "qxl"; break; 1133706f2543Smrg case 0x1163: driverList[0] = "rendition"; break; 1134706f2543Smrg case 0x5333: 1135706f2543Smrg switch (dev->device_id) 1136706f2543Smrg { 1137706f2543Smrg case 0x88d0: case 0x88d1: case 0x88f0: case 0x8811: 1138706f2543Smrg case 0x8812: case 0x8814: case 0x8901: 1139706f2543Smrg driverList[0] = "s3"; break; 1140706f2543Smrg case 0x5631: case 0x883d: case 0x8a01: case 0x8a10: 1141706f2543Smrg case 0x8c01: case 0x8c03: case 0x8904: case 0x8a13: 1142706f2543Smrg driverList[0] = "s3virge"; break; 1143706f2543Smrg default: 1144706f2543Smrg driverList[0] = "savage"; break; 1145706f2543Smrg } 1146706f2543Smrg break; 1147706f2543Smrg case 0x1039: driverList[0] = "sis"; break; 1148706f2543Smrg case 0x126f: driverList[0] = "siliconmotion"; break; 1149706f2543Smrg case 0x121a: 1150706f2543Smrg if (dev->device_id < 0x0003) 1151706f2543Smrg driverList[0] = "voodoo"; 1152706f2543Smrg else 1153706f2543Smrg driverList[0] = "tdfx"; 1154706f2543Smrg break; 1155706f2543Smrg case 0x1011: driverList[0] = "tga"; break; 1156706f2543Smrg case 0x1023: driverList[0] = "trident"; break; 1157706f2543Smrg case 0x100c: driverList[0] = "tseng"; break; 1158706f2543Smrg case 0x80ee: driverList[0] = "vboxvideo"; break; 1159706f2543Smrg case 0x15ad: driverList[0] = "vmware"; break; 1160706f2543Smrg case 0x18ca: 1161706f2543Smrg if (dev->device_id == 0x47) 1162706f2543Smrg driverList[0] = "xgixp"; 1163706f2543Smrg else 1164706f2543Smrg driverList[0] = "xgi"; 1165706f2543Smrg break; 1166706f2543Smrg default: break; 1167706f2543Smrg } 1168706f2543Smrg for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) { 1169706f2543Smrg returnList[i] = xnfstrdup(driverList[i]); 1170706f2543Smrg } 1171706f2543Smrg return i; /* Number of entries added */ 1172706f2543Smrg} 1173706f2543Smrg 1174706f2543Smrg#ifdef __linux__ 1175706f2543Smrgstatic int 1176706f2543Smrgxchomp(char *line) 1177706f2543Smrg{ 1178706f2543Smrg size_t len = 0; 1179706f2543Smrg 1180706f2543Smrg if (!line) { 1181706f2543Smrg return 1; 1182706f2543Smrg } 1183706f2543Smrg 1184706f2543Smrg len = strlen(line); 1185706f2543Smrg if (line[len - 1] == '\n' && len > 0) { 1186706f2543Smrg line[len - 1] = '\0'; 1187706f2543Smrg } 1188706f2543Smrg return 0; 1189706f2543Smrg} 1190706f2543Smrg 1191706f2543Smrg/* This function is used to provide a workaround for binary drivers that 1192706f2543Smrg * don't export their PCI ID's properly. If distros don't end up using this 1193706f2543Smrg * feature it can and should be removed because the symbol-based resolution 1194706f2543Smrg * scheme should be the primary one */ 1195706f2543Smrgstatic void 1196706f2543SmrgmatchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) 1197706f2543Smrg{ 1198706f2543Smrg DIR *idsdir; 1199706f2543Smrg FILE *fp; 1200706f2543Smrg struct dirent *direntry; 1201706f2543Smrg char *line = NULL; 1202706f2543Smrg size_t len; 1203706f2543Smrg ssize_t read; 1204706f2543Smrg char path_name[256], vendor_str[5], chip_str[5]; 1205706f2543Smrg uint16_t vendor, chip; 1206706f2543Smrg int i, j; 1207706f2543Smrg 1208706f2543Smrg idsdir = opendir(PCI_TXT_IDS_PATH); 1209706f2543Smrg if (!idsdir) 1210706f2543Smrg return; 1211706f2543Smrg 1212706f2543Smrg xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", PCI_TXT_IDS_PATH); 1213706f2543Smrg direntry = readdir(idsdir); 1214706f2543Smrg /* Read the directory */ 1215706f2543Smrg while (direntry) { 1216706f2543Smrg if (direntry->d_name[0] == '.') { 1217706f2543Smrg direntry = readdir(idsdir); 1218706f2543Smrg continue; 1219706f2543Smrg } 1220706f2543Smrg len = strlen(direntry->d_name); 1221706f2543Smrg /* A tiny bit of sanity checking. We should probably do better */ 1222706f2543Smrg if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { 1223706f2543Smrg /* We need the full path name to open the file */ 1224706f2543Smrg strncpy(path_name, PCI_TXT_IDS_PATH, 256); 1225706f2543Smrg strncat(path_name, "/", 1); 1226706f2543Smrg strncat(path_name, direntry->d_name, (256 - strlen(path_name) - 1)); 1227706f2543Smrg fp = fopen(path_name, "r"); 1228706f2543Smrg if (fp == NULL) { 1229706f2543Smrg xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); 1230706f2543Smrg goto end; 1231706f2543Smrg } 1232706f2543Smrg /* Read the file */ 1233706f2543Smrg#ifdef __GLIBC__ 1234706f2543Smrg while ((read = getline(&line, &len, fp)) != -1) { 1235706f2543Smrg#else 1236706f2543Smrg while ((line = fgetln(fp, &len)) != (char *)NULL) { 1237706f2543Smrg#endif /* __GLIBC __ */ 1238706f2543Smrg xchomp(line); 1239706f2543Smrg if (isdigit(line[0])) { 1240706f2543Smrg strncpy(vendor_str, line, 4); 1241706f2543Smrg vendor_str[4] = '\0'; 1242706f2543Smrg vendor = (int)strtol(vendor_str, NULL, 16); 1243706f2543Smrg if ((strlen(&line[4])) == 0) { 1244706f2543Smrg chip_str[0] = '\0'; 1245706f2543Smrg chip = -1; 1246706f2543Smrg } else { 1247706f2543Smrg /* Handle trailing whitespace */ 1248706f2543Smrg if (isspace(line[4])) { 1249706f2543Smrg chip_str[0] = '\0'; 1250706f2543Smrg chip = -1; 1251706f2543Smrg } else { 1252706f2543Smrg /* Ok, it's a real ID */ 1253706f2543Smrg strncpy(chip_str, &line[4], 4); 1254706f2543Smrg chip_str[4] = '\0'; 1255706f2543Smrg chip = (int)strtol(chip_str, NULL, 16); 1256706f2543Smrg } 1257706f2543Smrg } 1258706f2543Smrg if (vendor == match_vendor && chip == match_chip ) { 1259706f2543Smrg i = 0; 1260706f2543Smrg while (matches[i]) { 1261706f2543Smrg i++; 1262706f2543Smrg } 1263706f2543Smrg matches[i] = (char*)malloc(sizeof(char) * strlen(direntry->d_name) - 3); 1264706f2543Smrg if (!matches[i]) { 1265706f2543Smrg xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); 1266706f2543Smrg goto end; 1267706f2543Smrg } 1268706f2543Smrg /* hack off the .ids suffix. This should guard 1269706f2543Smrg * against other problems, but it will end up 1270706f2543Smrg * taking off anything after the first '.' */ 1271706f2543Smrg for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { 1272706f2543Smrg if (direntry->d_name[j] == '.') { 1273706f2543Smrg matches[i][j] = '\0'; 1274706f2543Smrg break; 1275706f2543Smrg } else { 1276706f2543Smrg matches[i][j] = direntry->d_name[j]; 1277706f2543Smrg } 1278706f2543Smrg } 1279706f2543Smrg xf86Msg(X_INFO, "Matched %s from file name %s\n", matches[i], direntry->d_name); 1280706f2543Smrg } 1281706f2543Smrg } else { 1282706f2543Smrg /* TODO Handle driver overrides here */ 1283706f2543Smrg } 1284706f2543Smrg } 1285706f2543Smrg fclose(fp); 1286706f2543Smrg } 1287706f2543Smrg direntry = readdir(idsdir); 1288706f2543Smrg } 1289706f2543Smrg end: 1290706f2543Smrg free(line); 1291706f2543Smrg closedir(idsdir); 1292706f2543Smrg} 1293706f2543Smrg#endif /* __linux__ */ 1294706f2543Smrg 1295706f2543Smrg/** 1296706f2543Smrg * @return The numbers of found devices that match with the current system 1297706f2543Smrg * drivers. 1298706f2543Smrg */ 1299706f2543Smrgint 1300706f2543Smrgxf86PciMatchDriver(char* matches[], int nmatches) { 1301706f2543Smrg int i; 1302706f2543Smrg struct pci_device * info = NULL; 1303706f2543Smrg struct pci_device_iterator *iter; 1304706f2543Smrg 1305706f2543Smrg /* Find the primary device, and get some information about it. */ 1306706f2543Smrg iter = pci_slot_match_iterator_create(NULL); 1307706f2543Smrg while ((info = pci_device_next(iter)) != NULL) { 1308706f2543Smrg if (xf86IsPrimaryPci(info)) { 1309706f2543Smrg break; 1310706f2543Smrg } 1311706f2543Smrg } 1312706f2543Smrg 1313706f2543Smrg pci_iterator_destroy(iter); 1314706f2543Smrg#ifdef __linux__ 1315706f2543Smrg if (info) 1316706f2543Smrg matchDriverFromFiles(matches, info->vendor_id, info->device_id); 1317706f2543Smrg#endif 1318706f2543Smrg 1319706f2543Smrg for (i = 0; (i < nmatches) && (matches[i]); i++) { 1320706f2543Smrg /* find end of matches list */ 1321706f2543Smrg } 1322706f2543Smrg 1323706f2543Smrg if ((info != NULL) && (i < nmatches)) { 1324706f2543Smrg i += videoPtrToDriverList(info, &(matches[i]), nmatches - i); 1325706f2543Smrg } 1326706f2543Smrg 1327706f2543Smrg return i; 1328706f2543Smrg} 1329706f2543Smrg 1330706f2543SmrgBool 1331706f2543Smrgxf86PciConfigure(void *busData, struct pci_device *pDev) 1332706f2543Smrg{ 1333706f2543Smrg struct pci_device * pVideo = NULL; 1334706f2543Smrg 1335706f2543Smrg pVideo = (struct pci_device *) busData; 1336706f2543Smrg if (pDev && 1337706f2543Smrg (pDev->domain == pVideo->domain) && 1338706f2543Smrg (pDev->bus == pVideo->bus) && 1339706f2543Smrg (pDev->dev == pVideo->dev) && 1340706f2543Smrg (pDev->func == pVideo->func)) 1341706f2543Smrg return 0; 1342706f2543Smrg 1343706f2543Smrg return 1; 1344706f2543Smrg} 1345706f2543Smrg 1346706f2543Smrgvoid 1347706f2543Smrgxf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, 1348706f2543Smrg GDevRec *GDev, int *chipset) 1349706f2543Smrg{ 1350706f2543Smrg char busnum[8]; 1351706f2543Smrg 1352706f2543Smrg pVideo = (struct pci_device *) busData; 1353706f2543Smrg 1354706f2543Smrg xf86FormatPciBusNumber(pVideo->bus, busnum); 1355706f2543Smrg XNFasprintf(&GDev->busID, "PCI:%s:%d:%d", 1356706f2543Smrg busnum, pVideo->dev, pVideo->func); 1357706f2543Smrg 1358706f2543Smrg GDev->chipID = pVideo->device_id; 1359706f2543Smrg GDev->chipRev = pVideo->revision; 1360706f2543Smrg 1361706f2543Smrg if (*chipset < 0) 1362706f2543Smrg *chipset = (pVideo->vendor_id << 16) | pVideo->device_id; 1363706f2543Smrg} 1364