1 /*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28 /*
29 * This file contains the interfaces to the bus-specific code
30 */
31 #ifdef HAVE_XORG_CONFIG_H
32 #include <xorg-config.h>
33 #endif
34
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <X11/X.h>
39 #include <pciaccess.h>
40 #include "os.h"
41 #include "Pci.h"
42 #include "xf86.h"
43 #include "xf86Priv.h"
44 #include "dirent.h" /* DIR, FILE type definitions */
45
46 /* Bus-specific headers */
47 #include "xf86Bus.h"
48
49 #define XF86_OS_PRIVS
50 #include "xf86_OSproc.h"
51
52 #define PCI_VENDOR_GENERIC 0x00FF
53
54 /* Bus-specific globals */
55 int pciSlotClaimed = 0;
56
57 #define PCIINFOCLASSES(c) \
58 ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \
59 || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
60 || ((((c) & 0x00ffff00) \
61 == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \
62 || ((((c) & 0x00ffff00) \
63 == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) )
64
65 /*
66 * PCI classes that have messages printed always. The others are only
67 * have a message printed when the vendor/dev IDs are recognised.
68 */
69 #define PCIALWAYSPRINTCLASSES(c) \
70 ( (((c) & 0x00ffff00) \
71 == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \
72 || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
73 || ((((c) & 0x00ffff00) \
74 == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) )
75
76 #define IS_VGA(c) \
77 (((c) & 0x00ffff00) \
78 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
79
80 static struct pci_slot_match xf86IsolateDevice = {
81 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
82 };
83
84 /*
85 * xf86Bus.c interface
86 */
87
88 void
xf86PciProbe(void)89 xf86PciProbe(void)
90 {
91 int i = 0, k;
92 int num = 0;
93 struct pci_device *info;
94 struct pci_device_iterator *iter;
95 struct pci_device **xf86PciVideoInfo = NULL;
96
97 if (!xf86scanpci()) {
98 xf86PciVideoInfo = NULL;
99 return;
100 }
101
102 iter = pci_slot_match_iterator_create(&xf86IsolateDevice);
103 while ((info = pci_device_next(iter)) != NULL) {
104 if (PCIINFOCLASSES(info->device_class)) {
105 num++;
106 xf86PciVideoInfo = xnfreallocarray(xf86PciVideoInfo,
107 num + 1,
108 sizeof(struct pci_device *));
109 xf86PciVideoInfo[num] = NULL;
110 xf86PciVideoInfo[num - 1] = info;
111
112 pci_device_probe(info);
113 if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) {
114 primaryBus.type = BUS_PCI;
115 primaryBus.id.pci = info;
116 }
117 info->user_data = 0;
118 }
119 }
120 free(iter);
121
122 /* If we haven't found a primary device try a different heuristic */
123 if (primaryBus.type == BUS_NONE && num) {
124 for (i = 0; i < num; i++) {
125 uint16_t command;
126
127 info = xf86PciVideoInfo[i];
128 pci_device_cfg_read_u16(info, &command, 4);
129
130 if ((command & PCI_CMD_MEM_ENABLE)
131 && ((num == 1) || IS_VGA(info->device_class))) {
132 if (primaryBus.type == BUS_NONE) {
133 primaryBus.type = BUS_PCI;
134 primaryBus.id.pci = info;
135 }
136 else {
137 xf86Msg(X_NOTICE,
138 "More than one possible primary device found\n");
139 primaryBus.type ^= (BusType) (-1);
140 }
141 }
142 }
143 }
144
145 /* Print a summary of the video devices found */
146 for (k = 0; k < num; k++) {
147 const char *prim = " ";
148 Bool memdone = FALSE, iodone = FALSE;
149
150 info = xf86PciVideoInfo[k];
151
152 if (!PCIALWAYSPRINTCLASSES(info->device_class))
153 continue;
154
155 if (xf86IsPrimaryPci(info))
156 prim = "*";
157
158 xf86Msg(X_PROBED, "PCI:%s(%u@%u:%u:%u) %04x:%04x:%04x:%04x ", prim,
159 info->bus, info->domain, info->dev, info->func,
160 info->vendor_id, info->device_id,
161 info->subvendor_id, info->subdevice_id);
162
163 xf86ErrorF("rev %d", info->revision);
164
165 for (i = 0; i < 6; i++) {
166 struct pci_mem_region *r = &info->regions[i];
167
168 if (r->size && !r->is_IO) {
169 if (!memdone) {
170 xf86ErrorF(", Mem @ ");
171 memdone = TRUE;
172 }
173 else
174 xf86ErrorF(", ");
175 xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
176 }
177 }
178
179 for (i = 0; i < 6; i++) {
180 struct pci_mem_region *r = &info->regions[i];
181
182 if (r->size && r->is_IO) {
183 if (!iodone) {
184 xf86ErrorF(", I/O @ ");
185 iodone = TRUE;
186 }
187 else
188 xf86ErrorF(", ");
189 xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
190 }
191 }
192
193 if (info->rom_size) {
194 xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld",
195 (long) info->rom_size);
196 }
197
198 xf86ErrorF("\n");
199 }
200 free(xf86PciVideoInfo);
201 }
202
203 /*
204 * If the slot requested is already in use, return -1.
205 * Otherwise, claim the slot for the screen requesting it.
206 */
207
208 int
xf86ClaimPciSlot(struct pci_device * d,DriverPtr drvp,int chipset,GDevPtr dev,Bool active)209 xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
210 int chipset, GDevPtr dev, Bool active)
211 {
212 EntityPtr p = NULL;
213 int num;
214
215 if (xf86CheckPciSlot(d)) {
216 num = xf86AllocateEntity();
217 p = xf86Entities[num];
218 p->driver = drvp;
219 p->chipset = chipset;
220 p->bus.type = BUS_PCI;
221 p->bus.id.pci = d;
222 p->active = active;
223 p->inUse = FALSE;
224 if (dev)
225 xf86AddDevToEntity(num, dev);
226 pciSlotClaimed++;
227
228 return num;
229 }
230 else
231 return -1;
232 }
233
234 /*
235 * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim.
236 */
237 void
xf86UnclaimPciSlot(struct pci_device * d,GDevPtr dev)238 xf86UnclaimPciSlot(struct pci_device *d, GDevPtr dev)
239 {
240 int i;
241
242 for (i = 0; i < xf86NumEntities; i++) {
243 const EntityPtr p = xf86Entities[i];
244
245 if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
246 /* Probably the slot should be deallocated? */
247 xf86RemoveDevFromEntity(i, dev);
248 pciSlotClaimed--;
249 p->bus.type = BUS_NONE;
250 return;
251 }
252 }
253 }
254
255 /*
256 * Parse a BUS ID string, and return the PCI bus parameters if it was
257 * in the correct format for a PCI bus id.
258 */
259
260 Bool
xf86ParsePciBusString(const char * busID,int * bus,int * device,int * func)261 xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
262 {
263 /*
264 * The format is assumed to be "bus[@domain]:device[:func]", where domain,
265 * bus, device and func are decimal integers. domain and func may be
266 * omitted and assumed to be zero, although doing this isn't encouraged.
267 */
268
269 char *p, *s, *d;
270 const char *id;
271 int i;
272
273 if (StringToBusType(busID, &id) != BUS_PCI)
274 return FALSE;
275
276 s = xstrdup(id);
277 p = strtok(s, ":");
278 if (p == NULL || *p == 0) {
279 free(s);
280 return FALSE;
281 }
282 d = strpbrk(p, "@");
283 if (d != NULL) {
284 *(d++) = 0;
285 for (i = 0; d[i] != 0; i++) {
286 if (!isdigit(d[i])) {
287 free(s);
288 return FALSE;
289 }
290 }
291 }
292 for (i = 0; p[i] != 0; i++) {
293 if (!isdigit(p[i])) {
294 free(s);
295 return FALSE;
296 }
297 }
298 *bus = atoi(p);
299 if (d != NULL && *d != 0)
300 *bus += atoi(d) << 8;
301 p = strtok(NULL, ":");
302 if (p == NULL || *p == 0) {
303 free(s);
304 return FALSE;
305 }
306 for (i = 0; p[i] != 0; i++) {
307 if (!isdigit(p[i])) {
308 free(s);
309 return FALSE;
310 }
311 }
312 *device = atoi(p);
313 *func = 0;
314 p = strtok(NULL, ":");
315 if (p == NULL || *p == 0) {
316 free(s);
317 return TRUE;
318 }
319 for (i = 0; p[i] != 0; i++) {
320 if (!isdigit(p[i])) {
321 free(s);
322 return FALSE;
323 }
324 }
325 *func = atoi(p);
326 free(s);
327 return TRUE;
328 }
329
330 /*
331 * Compare a BUS ID string with a PCI bus id. Return TRUE if they match.
332 */
333
334 Bool
xf86ComparePciBusString(const char * busID,int bus,int device,int func)335 xf86ComparePciBusString(const char *busID, int bus, int device, int func)
336 {
337 int ibus, idevice, ifunc;
338
339 if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
340 return bus == ibus && device == idevice && func == ifunc;
341 }
342 else {
343 return FALSE;
344 }
345 }
346
347 /*
348 * xf86IsPrimaryPci() -- return TRUE if primary device
349 * is PCI and bus, dev and func numbers match.
350 */
351
352 Bool
xf86IsPrimaryPci(struct pci_device * pPci)353 xf86IsPrimaryPci(struct pci_device *pPci)
354 {
355 /* Add max. 1 screen for the IgnorePrimary fallback path */
356 if (xf86ProbeIgnorePrimary && xf86NumScreens == 0)
357 return TRUE;
358
359 if (primaryBus.type == BUS_PCI)
360 return pPci == primaryBus.id.pci;
361 #ifdef XSERVER_PLATFORM_BUS
362 if (primaryBus.type == BUS_PLATFORM)
363 if (primaryBus.id.plat->pdev)
364 if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci))
365 return TRUE;
366 #endif
367 return FALSE;
368 }
369
370 /*
371 * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
372 */
373 struct pci_device *
xf86GetPciInfoForEntity(int entityIndex)374 xf86GetPciInfoForEntity(int entityIndex)
375 {
376 EntityPtr p;
377
378 if (entityIndex >= xf86NumEntities)
379 return NULL;
380
381 p = xf86Entities[entityIndex];
382 switch (p->bus.type) {
383 case BUS_PCI:
384 return p->bus.id.pci;
385 case BUS_PLATFORM:
386 return p->bus.id.plat->pdev;
387 default:
388 break;
389 }
390 return NULL;
391 }
392
393 /*
394 * xf86CheckPciMemBase() checks that the memory base value matches one of the
395 * PCI base address register values for the given PCI device.
396 */
397 Bool
xf86CheckPciMemBase(struct pci_device * pPci,memType base)398 xf86CheckPciMemBase(struct pci_device *pPci, memType base)
399 {
400 int i;
401
402 for (i = 0; i < 6; i++)
403 if (base == pPci->regions[i].base_addr)
404 return TRUE;
405 return FALSE;
406 }
407
408 /*
409 * Check if the slot requested is free. If it is already in use, return FALSE.
410 */
411
412 Bool
xf86CheckPciSlot(const struct pci_device * d)413 xf86CheckPciSlot(const struct pci_device *d)
414 {
415 int i;
416
417 for (i = 0; i < xf86NumEntities; i++) {
418 const EntityPtr p = xf86Entities[i];
419
420 if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
421 return FALSE;
422 }
423 #ifdef XSERVER_PLATFORM_BUS
424 if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) {
425 struct pci_device *ud = p->bus.id.plat->pdev;
426 if (MATCH_PCI_DEVICES(ud, d))
427 return FALSE;
428 }
429 #endif
430 }
431 return TRUE;
432 }
433
434 #define END_OF_MATCHES(m) \
435 (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
436
437 Bool
xf86PciAddMatchingDev(DriverPtr drvp)438 xf86PciAddMatchingDev(DriverPtr drvp)
439 {
440 const struct pci_id_match *const devices = drvp->supported_devices;
441 int j;
442 struct pci_device *pPci;
443 struct pci_device_iterator *iter;
444 int numFound = 0;
445
446 iter = pci_id_match_iterator_create(NULL);
447 while ((pPci = pci_device_next(iter)) != NULL) {
448 /* Determine if this device is supported by the driver. If it is,
449 * add it to the list of devices to configure.
450 */
451 for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
452 if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
453 && PCI_ID_COMPARE(devices[j].device_id, pPci->device_id)
454 && ((devices[j].device_class_mask & pPci->device_class)
455 == devices[j].device_class)) {
456 if (xf86CheckPciSlot(pPci)) {
457 GDevPtr pGDev =
458 xf86AddBusDeviceToConfigure(drvp->driverName, BUS_PCI,
459 pPci, -1);
460 if (pGDev != NULL) {
461 /* After configure pass 1, chipID and chipRev are
462 * treated as over-rides, so clobber them here.
463 */
464 pGDev->chipID = -1;
465 pGDev->chipRev = -1;
466 }
467
468 numFound++;
469 }
470
471 break;
472 }
473 }
474 }
475
476 pci_iterator_destroy(iter);
477
478 return numFound != 0;
479 }
480
481 Bool
xf86PciProbeDev(DriverPtr drvp)482 xf86PciProbeDev(DriverPtr drvp)
483 {
484 int i, j;
485 struct pci_device *pPci;
486 Bool foundScreen = FALSE;
487 const struct pci_id_match *const devices = drvp->supported_devices;
488 GDevPtr *devList;
489 const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList);
490
491 for (i = 0; i < numDevs; i++) {
492 struct pci_device_iterator *iter;
493 unsigned device_id;
494
495 /* Find the pciVideoRec associated with this device section.
496 */
497 iter = pci_id_match_iterator_create(NULL);
498 while ((pPci = pci_device_next(iter)) != NULL) {
499 if (devList[i]->busID && *devList[i]->busID) {
500 if (xf86ComparePciBusString(devList[i]->busID,
501 ((pPci->domain << 8)
502 | pPci->bus),
503 pPci->dev, pPci->func)) {
504 break;
505 }
506 }
507 else if (xf86IsPrimaryPci(pPci)) {
508 break;
509 }
510 }
511
512 pci_iterator_destroy(iter);
513
514 if (pPci == NULL) {
515 continue;
516 }
517 device_id = (devList[i]->chipID > 0)
518 ? devList[i]->chipID : pPci->device_id;
519
520 /* Once the pciVideoRec is found, determine if the device is supported
521 * by the driver. If it is, probe it!
522 */
523 for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
524 if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
525 && PCI_ID_COMPARE(devices[j].device_id, device_id)
526 && ((devices[j].device_class_mask & pPci->device_class)
527 == devices[j].device_class)) {
528 int entry;
529
530 /* Allow the same entity to be used more than once for
531 * devices with multiple screens per entity. This assumes
532 * implicitly that there will be a screen == 0 instance.
533 *
534 * FIXME Need to make sure that two different drivers don't
535 * FIXME claim the same screen > 0 instance.
536 */
537 if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci))
538 continue;
539
540 DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
541 drvp->driverName, pPci->bus, pPci->dev, pPci->func);
542
543 /* Allocate an entry in the lists to be returned */
544 entry = xf86ClaimPciSlot(pPci, drvp, device_id,
545 devList[i], devList[i]->active);
546
547 if ((entry == -1) && (devList[i]->screen > 0)) {
548 unsigned k;
549
550 for (k = 0; k < xf86NumEntities; k++) {
551 EntityPtr pEnt = xf86Entities[k];
552
553 if (pEnt->bus.type != BUS_PCI)
554 continue;
555 if (pEnt->bus.id.pci == pPci) {
556 entry = k;
557 xf86AddDevToEntity(k, devList[i]);
558 break;
559 }
560 }
561 }
562
563 if (entry != -1) {
564 if ((*drvp->PciProbe) (drvp, entry, pPci,
565 devices[j].match_data)) {
566 foundScreen = TRUE;
567 }
568 else
569 xf86UnclaimPciSlot(pPci, devList[i]);
570 }
571
572 break;
573 }
574 }
575 }
576 free(devList);
577
578 return foundScreen;
579 }
580
581 void
xf86PciIsolateDevice(const char * argument)582 xf86PciIsolateDevice(const char *argument)
583 {
584 int bus, device, func;
585
586 if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
587 xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
588 xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
589 xf86IsolateDevice.dev = device;
590 xf86IsolateDevice.func = func;
591 }
592 else
593 FatalError("Invalid isolated device specification\n");
594 }
595
596 static Bool
pciDeviceHasBars(struct pci_device * pci)597 pciDeviceHasBars(struct pci_device *pci)
598 {
599 int i;
600
601 for (i = 0; i < 6; i++)
602 if (pci->regions[i].size)
603 return TRUE;
604
605 if (pci->rom_size)
606 return TRUE;
607
608 return FALSE;
609 }
610
611 struct Inst {
612 struct pci_device *pci;
613 GDevPtr dev;
614 Bool foundHW; /* PCIid in list of supported chipsets */
615 Bool claimed; /* BusID matches with a device section */
616 int chip;
617 int screen;
618 };
619
620 /**
621 * Find set of unclaimed devices matching a given vendor ID.
622 *
623 * Used by drivers to find as yet unclaimed devices matching the specified
624 * vendor ID.
625 *
626 * \param driverName Name of the driver. This is used to find Device
627 * sections in the config file.
628 * \param vendorID PCI vendor ID of associated devices. If zero, then
629 * the true vendor ID must be encoded in the \c PCIid
630 * fields of the \c PCIchipsets entries.
631 * \param chipsets Symbol table used to associate chipset names with
632 * PCI IDs.
633 * \param devList List of Device sections parsed from the config file.
634 * \param numDevs Number of entries in \c devList.
635 * \param drvp Pointer the driver's control structure.
636 * \param foundEntities Returned list of entity indicies associated with the
637 * driver.
638 *
639 * \returns
640 * The number of elements in returned in \c foundEntities on success or zero
641 * on failure.
642 *
643 * \todo
644 * This function does a bit more than short description says. Fill in some
645 * more of the details of its operation.
646 *
647 * \todo
648 * The \c driverName parameter is redundant. It is the same as
649 * \c DriverRec::driverName. In a future version of this function, remove
650 * that parameter.
651 */
652 int
xf86MatchPciInstances(const char * driverName,int vendorID,SymTabPtr chipsets,PciChipsets * PCIchipsets,GDevPtr * devList,int numDevs,DriverPtr drvp,int ** foundEntities)653 xf86MatchPciInstances(const char *driverName, int vendorID,
654 SymTabPtr chipsets, PciChipsets * PCIchipsets,
655 GDevPtr * devList, int numDevs, DriverPtr drvp,
656 int **foundEntities)
657 {
658 int i, j;
659 struct pci_device *pPci;
660 struct pci_device_iterator *iter;
661 struct Inst *instances = NULL;
662 int numClaimedInstances = 0;
663 int allocatedInstances = 0;
664 int numFound = 0;
665 SymTabRec *c;
666 PciChipsets *id;
667 int *retEntities = NULL;
668
669 *foundEntities = NULL;
670
671 /* Each PCI device will contribute at least one entry. Each device
672 * section can contribute at most one entry. The sum of the two is
673 * guaranteed to be larger than the maximum possible number of entries.
674 * Do this calculation and memory allocation once now to eliminate the
675 * need for realloc calls inside the loop.
676 */
677 if (!(xf86DoConfigure && xf86DoConfigurePass1)) {
678 unsigned max_entries = numDevs;
679
680 iter = pci_slot_match_iterator_create(NULL);
681 while ((pPci = pci_device_next(iter)) != NULL) {
682 max_entries++;
683 }
684
685 pci_iterator_destroy(iter);
686 instances = xnfallocarray(max_entries, sizeof(struct Inst));
687 }
688
689 iter = pci_slot_match_iterator_create(NULL);
690 while ((pPci = pci_device_next(iter)) != NULL) {
691 unsigned device_class = pPci->device_class;
692 Bool foundVendor = FALSE;
693
694 /* Convert the pre-PCI 2.0 device class for a VGA adapter to the
695 * 2.0 version of the same class.
696 */
697 if (device_class == 0x00000101) {
698 device_class = 0x00030000;
699 }
700
701 /* Find PCI devices that match the given vendor ID. The vendor ID is
702 * either specified explicitly as a parameter to the function or
703 * implicitly encoded in the high bits of id->PCIid.
704 *
705 * The first device with a matching vendor is recorded, even if the
706 * device ID doesn't match. This is done because the Device section
707 * in the xorg.conf file can over-ride the device ID. A matching PCI
708 * ID might not be found now, but after the device ID over-ride is
709 * applied there /might/ be a match.
710 */
711 for (id = PCIchipsets; id->PCIid != -1; id++) {
712 const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16)
713 | vendorID;
714 const unsigned device_id = (id->PCIid & 0x0000FFFF);
715 const unsigned match_class = 0x00030000 | id->PCIid;
716
717 if ((vendor_id == pPci->vendor_id)
718 || ((vendorID == PCI_VENDOR_GENERIC) &&
719 (match_class == device_class))) {
720 if (!foundVendor && (instances != NULL)) {
721 ++allocatedInstances;
722 instances[allocatedInstances - 1].pci = pPci;
723 instances[allocatedInstances - 1].dev = NULL;
724 instances[allocatedInstances - 1].claimed = FALSE;
725 instances[allocatedInstances - 1].foundHW = FALSE;
726 instances[allocatedInstances - 1].screen = 0;
727 }
728
729 foundVendor = TRUE;
730
731 if ((device_id == pPci->device_id)
732 || ((vendorID == PCI_VENDOR_GENERIC)
733 && (match_class == device_class))) {
734 if (instances != NULL) {
735 instances[allocatedInstances - 1].foundHW = TRUE;
736 instances[allocatedInstances - 1].chip = id->numChipset;
737 }
738
739 if (xf86DoConfigure && xf86DoConfigurePass1) {
740 if (xf86CheckPciSlot(pPci)) {
741 GDevPtr pGDev =
742 xf86AddBusDeviceToConfigure(drvp->driverName,
743 BUS_PCI, pPci, -1);
744
745 if (pGDev) {
746 /* After configure pass 1, chipID and chipRev
747 * are treated as over-rides, so clobber them
748 * here.
749 */
750 pGDev->chipID = -1;
751 pGDev->chipRev = -1;
752 }
753
754 numFound++;
755 }
756 }
757 else {
758 numFound++;
759 }
760
761 break;
762 }
763 }
764 }
765 }
766
767 pci_iterator_destroy(iter);
768
769 /* In "probe only" or "configure" mode (signaled by instances being NULL),
770 * our work is done. Return the number of detected devices.
771 */
772 if (instances == NULL) {
773 return numFound;
774 }
775
776 /*
777 * This may be debatable, but if no PCI devices with a matching vendor
778 * type is found, return zero now. It is probably not desirable to
779 * allow the config file to override this.
780 */
781 if (allocatedInstances <= 0) {
782 free(instances);
783 return 0;
784 }
785
786 DebugF("%s instances found: %d\n", driverName, allocatedInstances);
787
788 /*
789 * Check for devices that need duplicated instances. This is required
790 * when there is more than one screen per entity.
791 *
792 * XXX This currently doesn't work for cases where the BusID isn't
793 * specified explicitly in the config file.
794 */
795
796 for (j = 0; j < numDevs; j++) {
797 if (devList[j]->screen > 0 && devList[j]->busID && *devList[j]->busID) {
798 for (i = 0; i < allocatedInstances; i++) {
799 pPci = instances[i].pci;
800 if (xf86ComparePciBusString(devList[j]->busID,
801 PCI_MAKE_BUS(pPci->domain,
802 pPci->bus), pPci->dev,
803 pPci->func)) {
804 allocatedInstances++;
805 instances[allocatedInstances - 1] = instances[i];
806 instances[allocatedInstances - 1].screen =
807 devList[j]->screen;
808 numFound++;
809 break;
810 }
811 }
812 }
813 }
814
815 for (i = 0; i < allocatedInstances; i++) {
816 GDevPtr dev = NULL;
817 GDevPtr devBus = NULL;
818
819 pPci = instances[i].pci;
820 for (j = 0; j < numDevs; j++) {
821 if (devList[j]->busID && *devList[j]->busID) {
822 if (xf86ComparePciBusString(devList[j]->busID,
823 PCI_MAKE_BUS(pPci->domain,
824 pPci->bus), pPci->dev,
825 pPci->func) &&
826 devList[j]->screen == instances[i].screen) {
827
828 if (devBus)
829 xf86MsgVerb(X_WARNING, 0,
830 "%s: More than one matching Device section for "
831 "instances\n\t(BusID: %s) found: %s\n",
832 driverName, devList[j]->busID,
833 devList[j]->identifier);
834 else
835 devBus = devList[j];
836 }
837 }
838 else {
839 /*
840 * if device section without BusID is found
841 * only assign to it to the primary device.
842 */
843 if (xf86IsPrimaryPci(pPci)) {
844 xf86Msg(X_PROBED, "Assigning device section with no busID"
845 " to primary device\n");
846 if (dev || devBus)
847 xf86MsgVerb(X_WARNING, 0,
848 "%s: More than one matching Device section "
849 "found: %s\n", driverName,
850 devList[j]->identifier);
851 else
852 dev = devList[j];
853 }
854 }
855 }
856 if (devBus)
857 dev = devBus; /* busID preferred */
858 if (!dev) {
859 if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) {
860 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
861 "for instance (BusID PCI:%u@%u:%u:%u) found\n",
862 driverName, pPci->bus, pPci->domain, pPci->dev,
863 pPci->func);
864 }
865 }
866 else {
867 numClaimedInstances++;
868 instances[i].claimed = TRUE;
869 instances[i].dev = dev;
870 }
871 }
872 DebugF("%s instances found: %d\n", driverName, numClaimedInstances);
873 /*
874 * Now check that a chipset or chipID override in the device section
875 * is valid. Chipset has precedence over chipID.
876 * If chipset is not valid ignore BusSlot completely.
877 */
878 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
879 MessageType from = X_PROBED;
880
881 if (!instances[i].claimed) {
882 continue;
883 }
884 if (instances[i].dev->chipset) {
885 for (c = chipsets; c->token >= 0; c++) {
886 if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0)
887 break;
888 }
889 if (c->token == -1) {
890 instances[i].claimed = FALSE;
891 numClaimedInstances--;
892 xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
893 "section \"%s\" isn't valid for this driver\n",
894 driverName, instances[i].dev->chipset,
895 instances[i].dev->identifier);
896 }
897 else {
898 instances[i].chip = c->token;
899
900 for (id = PCIchipsets; id->numChipset >= 0; id++) {
901 if (id->numChipset == instances[i].chip)
902 break;
903 }
904 if (id->numChipset >= 0) {
905 xf86Msg(X_CONFIG, "Chipset override: %s\n",
906 instances[i].dev->chipset);
907 from = X_CONFIG;
908 }
909 else {
910 instances[i].claimed = FALSE;
911 numClaimedInstances--;
912 xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
913 "section \"%s\" isn't a valid PCI chipset\n",
914 driverName, instances[i].dev->chipset,
915 instances[i].dev->identifier);
916 }
917 }
918 }
919 else if (instances[i].dev->chipID > 0) {
920 for (id = PCIchipsets; id->numChipset >= 0; id++) {
921 if (id->PCIid == instances[i].dev->chipID)
922 break;
923 }
924 if (id->numChipset == -1) {
925 instances[i].claimed = FALSE;
926 numClaimedInstances--;
927 xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device "
928 "section \"%s\" isn't valid for this driver\n",
929 driverName, instances[i].dev->chipID,
930 instances[i].dev->identifier);
931 }
932 else {
933 instances[i].chip = id->numChipset;
934
935 xf86Msg(X_CONFIG, "ChipID override: 0x%04X\n",
936 instances[i].dev->chipID);
937 from = X_CONFIG;
938 }
939 }
940 else if (!instances[i].foundHW) {
941 /*
942 * This means that there was no override and the PCI chipType
943 * doesn't match one that is supported
944 */
945 instances[i].claimed = FALSE;
946 numClaimedInstances--;
947 }
948 if (instances[i].claimed == TRUE) {
949 for (c = chipsets; c->token >= 0; c++) {
950 if (c->token == instances[i].chip)
951 break;
952 }
953 xf86Msg(from, "Chipset %s found\n", c->name);
954 }
955 }
956
957 /*
958 * Of the claimed instances, check that another driver hasn't already
959 * claimed its slot.
960 */
961 numFound = 0;
962 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
963 if (!instances[i].claimed)
964 continue;
965 pPci = instances[i].pci;
966
967 /*
968 * Allow the same entity to be used more than once for devices with
969 * multiple screens per entity. This assumes implicitly that there
970 * will be a screen == 0 instance.
971 *
972 * XXX Need to make sure that two different drivers don't claim
973 * the same screen > 0 instance.
974 */
975 if (instances[i].screen == 0 && !xf86CheckPciSlot(pPci))
976 continue;
977
978 DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
979 driverName, pPci->bus, pPci->dev, pPci->func);
980
981 /* Allocate an entry in the lists to be returned */
982 numFound++;
983 retEntities = xnfreallocarray(retEntities, numFound, sizeof(int));
984 retEntities[numFound - 1] = xf86ClaimPciSlot(pPci, drvp,
985 instances[i].chip,
986 instances[i].dev,
987 instances[i].dev->active);
988 if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) {
989 for (j = 0; j < xf86NumEntities; j++) {
990 EntityPtr pEnt = xf86Entities[j];
991
992 if (pEnt->bus.type != BUS_PCI)
993 continue;
994 if (pEnt->bus.id.pci == pPci) {
995 retEntities[numFound - 1] = j;
996 xf86AddDevToEntity(j, instances[i].dev);
997 break;
998 }
999 }
1000 }
1001 }
1002 free(instances);
1003 if (numFound > 0) {
1004 *foundEntities = retEntities;
1005 }
1006
1007 return numFound;
1008 }
1009
1010 /*
1011 * xf86ConfigPciEntityInactive() -- This function can be used
1012 * to configure an inactive entity as well as to reconfigure an
1013 * previously active entity inactive. If the entity has been
1014 * assigned to a screen before it will be removed. If p_chip is
1015 * non-NULL all static resources listed there will be registered.
1016 */
1017 static void
xf86ConfigPciEntityInactive(EntityInfoPtr pEnt,PciChipsets * p_chip,EntityProc init,EntityProc enter,EntityProc leave,void * private)1018 xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets * p_chip,
1019 EntityProc init, EntityProc enter,
1020 EntityProc leave, void *private)
1021 {
1022 ScrnInfoPtr pScrn;
1023
1024 if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1025 xf86RemoveEntityFromScreen(pScrn, pEnt->index);
1026 }
1027
1028 ScrnInfoPtr
xf86ConfigPciEntity(ScrnInfoPtr pScrn,int scrnFlag,int entityIndex,PciChipsets * p_chip,void * dummy,EntityProc init,EntityProc enter,EntityProc leave,void * private)1029 xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1030 PciChipsets * p_chip, void *dummy, EntityProc init,
1031 EntityProc enter, EntityProc leave, void *private)
1032 {
1033 EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1034
1035 if (dummy || init || enter || leave)
1036 FatalError("Legacy entity access functions are unsupported\n");
1037
1038 if (!pEnt)
1039 return pScrn;
1040
1041 if (!(pEnt->location.type == BUS_PCI)
1042 || !xf86GetPciInfoForEntity(entityIndex)) {
1043 free(pEnt);
1044 return pScrn;
1045 }
1046 if (!pEnt->active) {
1047 xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, leave, private);
1048 free(pEnt);
1049 return pScrn;
1050 }
1051
1052 if (!pScrn)
1053 pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
1054 if (xf86IsEntitySharable(entityIndex)) {
1055 xf86SetEntityShared(entityIndex);
1056 }
1057 xf86AddEntityToScreen(pScrn, entityIndex);
1058 if (xf86IsEntityShared(entityIndex)) {
1059 return pScrn;
1060 }
1061 free(pEnt);
1062
1063 return pScrn;
1064 }
1065
1066 void
xf86VideoPtrToDriverList(struct pci_device * dev,XF86MatchedDrivers * md)1067 xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md)
1068 {
1069 int i;
1070
1071 /* Add more entries here if we ever return more than 4 drivers for
1072 any device */
1073 const char *driverList[5] = { NULL, NULL, NULL, NULL, NULL };
1074
1075 switch (dev->vendor_id) {
1076 /* AMD Geode LX */
1077 case 0x1022:
1078 if (dev->device_id == 0x2081)
1079 driverList[0] = "geode";
1080 break;
1081 /* older Geode products acquired by AMD still carry an NSC vendor_id */
1082 case 0x100b:
1083 if (dev->device_id == 0x0030) {
1084 /* NSC Geode GX2 specifically */
1085 driverList[0] = "geode";
1086 /* GX2 support started its life in the NSC tree and was later
1087 forked by AMD for GEODE so we keep it as a backup */
1088 driverList[1] = "nsc";
1089 }
1090 else
1091 /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */
1092 driverList[0] = "nsc";
1093 break;
1094 /* Cyrix Geode GX1 */
1095 case 0x1078:
1096 if (dev->device_id == 0x0104)
1097 driverList[0] = "cyrix";
1098 break;
1099 case 0x1142:
1100 driverList[0] = "apm";
1101 break;
1102 case 0xedd8:
1103 driverList[0] = "ark";
1104 break;
1105 case 0x1a03:
1106 driverList[0] = "ast";
1107 break;
1108 case 0x1002:
1109 driverList[0] = "ati";
1110 break;
1111 case 0x102c:
1112 driverList[0] = "chips";
1113 break;
1114 case 0x1013:
1115 driverList[0] = "cirrus";
1116 break;
1117 case 0x3d3d:
1118 driverList[0] = "glint";
1119 break;
1120 case 0x105d:
1121 driverList[0] = "i128";
1122 break;
1123 case 0x8086:
1124 switch (dev->device_id)
1125 {
1126 /* Intel i740 */
1127 case 0x00d1:
1128 case 0x7800:
1129 driverList[0] = "i740";
1130 break;
1131 /* GMA500/Poulsbo */
1132 case 0x8108:
1133 case 0x8109:
1134 /* Try psb driver on Poulsbo - if available */
1135 driverList[0] = "psb";
1136 driverList[1] = "psb_drv";
1137 break;
1138 /* GMA600/Oaktrail */
1139 case 0x4100:
1140 case 0x4101:
1141 case 0x4102:
1142 case 0x4103:
1143 case 0x4104:
1144 case 0x4105:
1145 case 0x4106:
1146 case 0x4107:
1147 /* Atom E620/Oaktrail */
1148 case 0x4108:
1149 /* Medfield */
1150 case 0x0130:
1151 case 0x0131:
1152 case 0x0132:
1153 case 0x0133:
1154 case 0x0134:
1155 case 0x0135:
1156 case 0x0136:
1157 case 0x0137:
1158 /* GMA 3600/CDV */
1159 case 0x0be0:
1160 case 0x0be1:
1161 case 0x0be2:
1162 case 0x0be3:
1163 case 0x0be4:
1164 case 0x0be5:
1165 case 0x0be6:
1166 case 0x0be7:
1167 case 0x0be8:
1168 case 0x0be9:
1169 case 0x0bea:
1170 case 0x0beb:
1171 case 0x0bec:
1172 case 0x0bed:
1173 case 0x0bee:
1174 case 0x0bef:
1175 /* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */
1176 break;
1177 default:
1178 driverList[0] = "intel";
1179 break;
1180 }
1181 break;
1182 case 0x102b:
1183 driverList[0] = "mga";
1184 break;
1185 case 0x10c8:
1186 driverList[0] = "neomagic";
1187 break;
1188 case 0x10de:
1189 case 0x12d2:
1190 {
1191 int idx = 0;
1192
1193 #if defined(__linux__) || defined(__NetBSD__)
1194 driverList[idx++] = "nouveau";
1195 #endif
1196 driverList[idx++] = "nv";
1197 break;
1198 }
1199 case 0x1106:
1200 driverList[0] = "openchrome";
1201 break;
1202 case 0x1b36:
1203 driverList[0] = "qxl";
1204 break;
1205 case 0x1163:
1206 driverList[0] = "rendition";
1207 break;
1208 case 0x5333:
1209 switch (dev->device_id) {
1210 case 0x88d0:
1211 case 0x88d1:
1212 case 0x88f0:
1213 case 0x8811:
1214 case 0x8812:
1215 case 0x8814:
1216 case 0x8901:
1217 driverList[0] = "s3";
1218 break;
1219 case 0x5631:
1220 case 0x883d:
1221 case 0x8a01:
1222 case 0x8a10:
1223 case 0x8c01:
1224 case 0x8c03:
1225 case 0x8904:
1226 case 0x8a13:
1227 driverList[0] = "s3virge";
1228 break;
1229 default:
1230 driverList[0] = "savage";
1231 break;
1232 }
1233 break;
1234 case 0x1039:
1235 driverList[0] = "sis";
1236 break;
1237 case 0x126f:
1238 driverList[0] = "siliconmotion";
1239 break;
1240 case 0x121a:
1241 if (dev->device_id < 0x0003)
1242 driverList[0] = "voodoo";
1243 else
1244 driverList[0] = "tdfx";
1245 break;
1246 case 0x1011:
1247 driverList[0] = "tga";
1248 break;
1249 case 0x1023:
1250 driverList[0] = "trident";
1251 break;
1252 case 0x100c:
1253 driverList[0] = "tseng";
1254 break;
1255 case 0x80ee:
1256 driverList[0] = "vboxvideo";
1257 break;
1258 case 0x15ad:
1259 driverList[0] = "vmware";
1260 break;
1261 case 0x18ca:
1262 if (dev->device_id == 0x47)
1263 driverList[0] = "xgixp";
1264 else
1265 driverList[0] = "xgi";
1266 break;
1267 default:
1268 break;
1269 }
1270 for (i = 0; driverList[i] != NULL; i++) {
1271 xf86AddMatchedDriver(md, driverList[i]);
1272 }
1273 }
1274
1275 #ifdef __linux__
1276 static int
xchomp(char * line)1277 xchomp(char *line)
1278 {
1279 size_t len = 0;
1280
1281 if (!line) {
1282 return 1;
1283 }
1284
1285 len = strlen(line);
1286 if (line[len - 1] == '\n' && len > 0) {
1287 line[len - 1] = '\0';
1288 }
1289 return 0;
1290 }
1291
1292 /* This function is used to provide a workaround for binary drivers that
1293 * don't export their PCI ID's properly. If distros don't end up using this
1294 * feature it can and should be removed because the symbol-based resolution
1295 * scheme should be the primary one */
1296 void
xf86MatchDriverFromFiles(uint16_t match_vendor,uint16_t match_chip,XF86MatchedDrivers * md)1297 xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip,
1298 XF86MatchedDrivers *md)
1299 {
1300 DIR *idsdir;
1301 FILE *fp;
1302 struct dirent *direntry;
1303 char *line = NULL, *tmpMatch;
1304 size_t len;
1305 ssize_t read;
1306 char path_name[512], vendor_str[5], chip_str[5];
1307 uint16_t vendor, chip;
1308 int j;
1309
1310 idsdir = opendir(PCI_TXT_IDS_PATH);
1311 if (!idsdir)
1312 return;
1313
1314 xf86Msg(X_INFO,
1315 "Scanning %s directory for additional PCI ID's supported by the drivers\n",
1316 PCI_TXT_IDS_PATH);
1317 direntry = readdir(idsdir);
1318 /* Read the directory */
1319 while (direntry) {
1320 if (direntry->d_name[0] == '.') {
1321 direntry = readdir(idsdir);
1322 continue;
1323 }
1324 len = strlen(direntry->d_name);
1325 /* A tiny bit of sanity checking. We should probably do better */
1326 if (strncmp(&(direntry->d_name[len - 4]), ".ids", 4) == 0) {
1327 /* We need the full path name to open the file */
1328 snprintf(path_name, sizeof(path_name), "%s/%s",
1329 PCI_TXT_IDS_PATH, direntry->d_name);
1330 fp = fopen(path_name, "r");
1331 if (fp == NULL) {
1332 xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n",
1333 path_name);
1334 goto end;
1335 }
1336 /* Read the file */
1337 #ifdef __GLIBC__
1338 while ((read = getline(&line, &len, fp)) != -1) {
1339 #else
1340 while ((line = fgetln(fp, &len)) != (char *) NULL) {
1341 #endif /* __GLIBC __ */
1342 xchomp(line);
1343 if (isdigit(line[0])) {
1344 strlcpy(vendor_str, line, sizeof(vendor_str));
1345 vendor = (int) strtol(vendor_str, NULL, 16);
1346 if ((strlen(&line[4])) == 0) {
1347 chip_str[0] = '\0';
1348 chip = -1;
1349 }
1350 else {
1351 /* Handle trailing whitespace */
1352 if (isspace(line[4])) {
1353 chip_str[0] = '\0';
1354 chip = -1;
1355 }
1356 else {
1357 /* Ok, it's a real ID */
1358 strlcpy(chip_str, &line[4], sizeof(chip_str));
1359 chip = (int) strtol(chip_str, NULL, 16);
1360 }
1361 }
1362 if (vendor == match_vendor && chip == match_chip) {
1363 tmpMatch =
1364 (char *) malloc(sizeof(char) *
1365 strlen(direntry->d_name) - 3);
1366 if (!tmpMatch) {
1367 xf86Msg(X_ERROR,
1368 "Could not allocate space for the module name. Exiting.\n");
1369 goto end;
1370 }
1371 /* hack off the .ids suffix. This should guard
1372 * against other problems, but it will end up
1373 * taking off anything after the first '.' */
1374 for (j = 0; j < (strlen(direntry->d_name) - 3); j++) {
1375 if (direntry->d_name[j] == '.') {
1376 tmpMatch[j] = '\0';
1377 break;
1378 }
1379 else {
1380 tmpMatch[j] = direntry->d_name[j];
1381 }
1382 }
1383 xf86AddMatchedDriver(md, tmpMatch);
1384 xf86Msg(X_INFO, "Matched %s from file name %s\n",
1385 tmpMatch, direntry->d_name);
1386 free(tmpMatch);
1387 }
1388 }
1389 else {
1390 /* TODO Handle driver overrides here */
1391 }
1392 }
1393 fclose(fp);
1394 }
1395 direntry = readdir(idsdir);
1396 }
1397 end:
1398 free(line);
1399 closedir(idsdir);
1400 }
1401 #endif /* __linux__ */
1402
1403 void
1404 xf86PciMatchDriver(XF86MatchedDrivers *md)
1405 {
1406 struct pci_device *info = NULL;
1407 struct pci_device_iterator *iter;
1408
1409 /* Find the primary device, and get some information about it. */
1410 iter = pci_slot_match_iterator_create(NULL);
1411 while ((info = pci_device_next(iter)) != NULL) {
1412 if (xf86IsPrimaryPci(info)) {
1413 break;
1414 }
1415 }
1416
1417 pci_iterator_destroy(iter);
1418 #ifdef __linux__
1419 if (info)
1420 xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md);
1421 #endif
1422
1423 if (info != NULL) {
1424 xf86VideoPtrToDriverList(info, md);
1425 }
1426 }
1427
1428 Bool
1429 xf86PciConfigure(void *busData, struct pci_device *pDev)
1430 {
1431 struct pci_device *pVideo = NULL;
1432
1433 pVideo = (struct pci_device *) busData;
1434 if (pDev &&
1435 (pDev->domain == pVideo->domain) &&
1436 (pDev->bus == pVideo->bus) &&
1437 (pDev->dev == pVideo->dev) && (pDev->func == pVideo->func))
1438 return 0;
1439
1440 return 1;
1441 }
1442
1443 void
1444 xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
1445 GDevRec * GDev, int *chipset)
1446 {
1447 char busnum[8];
1448 char *tmp;
1449
1450 pVideo = (struct pci_device *) busData;
1451
1452 snprintf(busnum, sizeof(busnum), "%d", pVideo->bus);
1453
1454 XNFasprintf(&tmp, "PCI:%s:%d:%d",
1455 busnum, pVideo->dev, pVideo->func);
1456 GDev->busID = tmp;
1457
1458 GDev->chipID = pVideo->device_id;
1459 GDev->chipRev = pVideo->revision;
1460
1461 if (*chipset < 0)
1462 *chipset = (pVideo->vendor_id << 16) | pVideo->device_id;
1463 }
1464
1465 char *
1466 DRICreatePCIBusID(const struct pci_device *dev)
1467 {
1468 char *busID;
1469
1470 if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
1471 dev->domain, dev->bus, dev->dev, dev->func) == -1)
1472 return NULL;
1473
1474 return busID;
1475 }
1476