Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / common / xf86pciBus.c
CommitLineData
a09e091a
JB
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 */
55int 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
80static 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
88void
89xf86PciProbe(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 = xnfrealloc(xf86PciVideoInfo,
107 (sizeof(struct pci_device *)
108 * (num + 1)));
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->domain, info->bus, 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
208int
209xf86ClaimPciSlot(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 */
237void
238xf86UnclaimPciSlot(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
260Bool
261xf86ParsePciBusString(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
334Bool
335xf86ComparePciBusString(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
352Bool
353xf86IsPrimaryPci(struct pci_device *pPci)
354{
355 if (primaryBus.type == BUS_PCI)
356 return pPci == primaryBus.id.pci;
357#ifdef XSERVER_PLATFORM_BUS
358 if (primaryBus.type == BUS_PLATFORM)
359 if (primaryBus.id.plat->pdev)
360 if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci))
361 return TRUE;
362#endif
363 return FALSE;
364}
365
366/*
367 * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
368 */
369struct pci_device *
370xf86GetPciInfoForEntity(int entityIndex)
371{
372 EntityPtr p;
373
374 if (entityIndex >= xf86NumEntities)
375 return NULL;
376
377 p = xf86Entities[entityIndex];
378 switch (p->bus.type) {
379 case BUS_PCI:
380 return p->bus.id.pci;
381 case BUS_PLATFORM:
382 return p->bus.id.plat->pdev;
383 default:
384 break;
385 }
386 return NULL;
387}
388
389/*
390 * xf86CheckPciMemBase() checks that the memory base value matches one of the
391 * PCI base address register values for the given PCI device.
392 */
393Bool
394xf86CheckPciMemBase(struct pci_device *pPci, memType base)
395{
396 int i;
397
398 for (i = 0; i < 6; i++)
399 if (base == pPci->regions[i].base_addr)
400 return TRUE;
401 return FALSE;
402}
403
404/*
405 * Check if the slot requested is free. If it is already in use, return FALSE.
406 */
407
408Bool
409xf86CheckPciSlot(const struct pci_device *d)
410{
411 int i;
412
413 for (i = 0; i < xf86NumEntities; i++) {
414 const EntityPtr p = xf86Entities[i];
415
416 if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
417 return FALSE;
418 }
419#ifdef XSERVER_PLATFORM_BUS
420 if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) {
421 struct pci_device *ud = p->bus.id.plat->pdev;
422 if (MATCH_PCI_DEVICES(ud, d))
423 return FALSE;
424 }
425#endif
426 }
427 return TRUE;
428}
429
430#define END_OF_MATCHES(m) \
431 (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
432
433Bool
434xf86PciAddMatchingDev(DriverPtr drvp)
435{
436 const struct pci_id_match *const devices = drvp->supported_devices;
437 int j;
438 struct pci_device *pPci;
439 struct pci_device_iterator *iter;
440 int numFound = 0;
441
442 iter = pci_id_match_iterator_create(NULL);
443 while ((pPci = pci_device_next(iter)) != NULL) {
444 /* Determine if this device is supported by the driver. If it is,
445 * add it to the list of devices to configure.
446 */
447 for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
448 if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
449 && PCI_ID_COMPARE(devices[j].device_id, pPci->device_id)
450 && ((devices[j].device_class_mask & pPci->device_class)
451 == devices[j].device_class)) {
452 if (xf86CheckPciSlot(pPci)) {
453 GDevPtr pGDev =
454 xf86AddBusDeviceToConfigure(drvp->driverName, BUS_PCI,
455 pPci, -1);
456 if (pGDev != NULL) {
457 /* After configure pass 1, chipID and chipRev are
458 * treated as over-rides, so clobber them here.
459 */
460 pGDev->chipID = -1;
461 pGDev->chipRev = -1;
462 }
463
464 numFound++;
465 }
466
467 break;
468 }
469 }
470 }
471
472 pci_iterator_destroy(iter);
473
474 return numFound != 0;
475}
476
477Bool
478xf86PciProbeDev(DriverPtr drvp)
479{
480 int i, j;
481 struct pci_device *pPci;
482 Bool foundScreen = FALSE;
483 const struct pci_id_match *const devices = drvp->supported_devices;
484 GDevPtr *devList;
485 const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList);
486
487 for (i = 0; i < numDevs; i++) {
488 struct pci_device_iterator *iter;
489 unsigned device_id;
490
491 /* Find the pciVideoRec associated with this device section.
492 */
493 iter = pci_id_match_iterator_create(NULL);
494 while ((pPci = pci_device_next(iter)) != NULL) {
495 if (devList[i]->busID && *devList[i]->busID) {
496 if (xf86ComparePciBusString(devList[i]->busID,
497 ((pPci->domain << 8)
498 | pPci->bus),
499 pPci->dev, pPci->func)) {
500 break;
501 }
502 }
503 else if (xf86IsPrimaryPci(pPci)) {
504 break;
505 }
506 }
507
508 pci_iterator_destroy(iter);
509
510 if (pPci == NULL) {
511 continue;
512 }
513 device_id = (devList[i]->chipID > 0)
514 ? devList[i]->chipID : pPci->device_id;
515
516 /* Once the pciVideoRec is found, determine if the device is supported
517 * by the driver. If it is, probe it!
518 */
519 for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
520 if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
521 && PCI_ID_COMPARE(devices[j].device_id, device_id)
522 && ((devices[j].device_class_mask & pPci->device_class)
523 == devices[j].device_class)) {
524 int entry;
525
526 /* Allow the same entity to be used more than once for
527 * devices with multiple screens per entity. This assumes
528 * implicitly that there will be a screen == 0 instance.
529 *
530 * FIXME Need to make sure that two different drivers don't
531 * FIXME claim the same screen > 0 instance.
532 */
533 if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci))
534 continue;
535
536 DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
537 drvp->driverName, pPci->bus, pPci->dev, pPci->func);
538
539 /* Allocate an entry in the lists to be returned */
540 entry = xf86ClaimPciSlot(pPci, drvp, device_id,
541 devList[i], devList[i]->active);
542
543 if ((entry == -1) && (devList[i]->screen > 0)) {
544 unsigned k;
545
546 for (k = 0; k < xf86NumEntities; k++) {
547 EntityPtr pEnt = xf86Entities[k];
548
549 if (pEnt->bus.type != BUS_PCI)
550 continue;
551 if (pEnt->bus.id.pci == pPci) {
552 entry = k;
553 xf86AddDevToEntity(k, devList[i]);
554 break;
555 }
556 }
557 }
558
559 if (entry != -1) {
560 if ((*drvp->PciProbe) (drvp, entry, pPci,
561 devices[j].match_data)) {
562 foundScreen = TRUE;
563 }
564 else
565 xf86UnclaimPciSlot(pPci, devList[i]);
566 }
567
568 break;
569 }
570 }
571 }
572 free(devList);
573
574 return foundScreen;
575}
576
577void
578xf86PciIsolateDevice(char *argument)
579{
580 int bus, device, func;
581
582 if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
583 xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
584 xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
585 xf86IsolateDevice.dev = device;
586 xf86IsolateDevice.func = func;
587 }
588 else
589 FatalError("Invalid isolated device specification\n");
590}
591
592static Bool
593pciDeviceHasBars(struct pci_device *pci)
594{
595 int i;
596
597 for (i = 0; i < 6; i++)
598 if (pci->regions[i].size)
599 return TRUE;
600
601 if (pci->rom_size)
602 return TRUE;
603
604 return FALSE;
605}
606
607struct Inst {
608 struct pci_device *pci;
609 GDevPtr dev;
610 Bool foundHW; /* PCIid in list of supported chipsets */
611 Bool claimed; /* BusID matches with a device section */
612 int chip;
613 int screen;
614};
615
616/**
617 * Find set of unclaimed devices matching a given vendor ID.
618 *
619 * Used by drivers to find as yet unclaimed devices matching the specified
620 * vendor ID.
621 *
622 * \param driverName Name of the driver. This is used to find Device
623 * sections in the config file.
624 * \param vendorID PCI vendor ID of associated devices. If zero, then
625 * the true vendor ID must be encoded in the \c PCIid
626 * fields of the \c PCIchipsets entries.
627 * \param chipsets Symbol table used to associate chipset names with
628 * PCI IDs.
629 * \param devList List of Device sections parsed from the config file.
630 * \param numDevs Number of entries in \c devList.
631 * \param drvp Pointer the driver's control structure.
632 * \param foundEntities Returned list of entity indicies associated with the
633 * driver.
634 *
635 * \returns
636 * The number of elements in returned in \c foundEntities on success or zero
637 * on failure.
638 *
639 * \todo
640 * This function does a bit more than short description says. Fill in some
641 * more of the details of its operation.
642 *
643 * \todo
644 * The \c driverName parameter is redundant. It is the same as
645 * \c DriverRec::driverName. In a future version of this function, remove
646 * that parameter.
647 */
648int
649xf86MatchPciInstances(const char *driverName, int vendorID,
650 SymTabPtr chipsets, PciChipsets * PCIchipsets,
651 GDevPtr * devList, int numDevs, DriverPtr drvp,
652 int **foundEntities)
653{
654 int i, j;
655 struct pci_device *pPci;
656 struct pci_device_iterator *iter;
657 struct Inst *instances = NULL;
658 int numClaimedInstances = 0;
659 int allocatedInstances = 0;
660 int numFound = 0;
661 SymTabRec *c;
662 PciChipsets *id;
663 int *retEntities = NULL;
664
665 *foundEntities = NULL;
666
667 /* Each PCI device will contribute at least one entry. Each device
668 * section can contribute at most one entry. The sum of the two is
669 * guaranteed to be larger than the maximum possible number of entries.
670 * Do this calculation and memory allocation once now to eliminate the
671 * need for realloc calls inside the loop.
672 */
673 if (!(xf86DoConfigure && xf86DoConfigurePass1)) {
674 unsigned max_entries = numDevs;
675
676 iter = pci_slot_match_iterator_create(NULL);
677 while ((pPci = pci_device_next(iter)) != NULL) {
678 max_entries++;
679 }
680
681 pci_iterator_destroy(iter);
682 instances = xnfalloc(max_entries * sizeof(struct Inst));
683 }
684
685 iter = pci_slot_match_iterator_create(NULL);
686 while ((pPci = pci_device_next(iter)) != NULL) {
687 unsigned device_class = pPci->device_class;
688 Bool foundVendor = FALSE;
689
690 /* Convert the pre-PCI 2.0 device class for a VGA adapter to the
691 * 2.0 version of the same class.
692 */
693 if (device_class == 0x00000101) {
694 device_class = 0x00030000;
695 }
696
697 /* Find PCI devices that match the given vendor ID. The vendor ID is
698 * either specified explicitly as a parameter to the function or
699 * implicitly encoded in the high bits of id->PCIid.
700 *
701 * The first device with a matching vendor is recorded, even if the
702 * device ID doesn't match. This is done because the Device section
703 * in the xorg.conf file can over-ride the device ID. A matching PCI
704 * ID might not be found now, but after the device ID over-ride is
705 * applied there /might/ be a match.
706 */
707 for (id = PCIchipsets; id->PCIid != -1; id++) {
708 const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16)
709 | vendorID;
710 const unsigned device_id = (id->PCIid & 0x0000FFFF);
711 const unsigned match_class = 0x00030000 | id->PCIid;
712
713 if ((vendor_id == pPci->vendor_id)
714 || ((vendorID == PCI_VENDOR_GENERIC) &&
715 (match_class == device_class))) {
716 if (!foundVendor && (instances != NULL)) {
717 ++allocatedInstances;
718 instances[allocatedInstances - 1].pci = pPci;
719 instances[allocatedInstances - 1].dev = NULL;
720 instances[allocatedInstances - 1].claimed = FALSE;
721 instances[allocatedInstances - 1].foundHW = FALSE;
722 instances[allocatedInstances - 1].screen = 0;
723 }
724
725 foundVendor = TRUE;
726
727 if ((device_id == pPci->device_id)
728 || ((vendorID == PCI_VENDOR_GENERIC)
729 && (match_class == device_class))) {
730 if (instances != NULL) {
731 instances[allocatedInstances - 1].foundHW = TRUE;
732 instances[allocatedInstances - 1].chip = id->numChipset;
733 }
734
735 if (xf86DoConfigure && xf86DoConfigurePass1) {
736 if (xf86CheckPciSlot(pPci)) {
737 GDevPtr pGDev =
738 xf86AddBusDeviceToConfigure(drvp->driverName,
739 BUS_PCI, pPci, -1);
740
741 if (pGDev) {
742 /* After configure pass 1, chipID and chipRev
743 * are treated as over-rides, so clobber them
744 * here.
745 */
746 pGDev->chipID = -1;
747 pGDev->chipRev = -1;
748 }
749
750 numFound++;
751 }
752 }
753 else {
754 numFound++;
755 }
756
757 break;
758 }
759 }
760 }
761 }
762
763 pci_iterator_destroy(iter);
764
765 /* In "probe only" or "configure" mode (signaled by instances being NULL),
766 * our work is done. Return the number of detected devices.
767 */
768 if (instances == NULL) {
769 return numFound;
770 }
771
772 /*
773 * This may be debatable, but if no PCI devices with a matching vendor
774 * type is found, return zero now. It is probably not desirable to
775 * allow the config file to override this.
776 */
777 if (allocatedInstances <= 0) {
778 free(instances);
779 return 0;
780 }
781
782 DebugF("%s instances found: %d\n", driverName, allocatedInstances);
783
784 /*
785 * Check for devices that need duplicated instances. This is required
786 * when there is more than one screen per entity.
787 *
788 * XXX This currently doesn't work for cases where the BusID isn't
789 * specified explicitly in the config file.
790 */
791
792 for (j = 0; j < numDevs; j++) {
793 if (devList[j]->screen > 0 && devList[j]->busID && *devList[j]->busID) {
794 for (i = 0; i < allocatedInstances; i++) {
795 pPci = instances[i].pci;
796 if (xf86ComparePciBusString(devList[j]->busID,
797 PCI_MAKE_BUS(pPci->domain,
798 pPci->bus), pPci->dev,
799 pPci->func)) {
800 allocatedInstances++;
801 instances[allocatedInstances - 1] = instances[i];
802 instances[allocatedInstances - 1].screen =
803 devList[j]->screen;
804 numFound++;
805 break;
806 }
807 }
808 }
809 }
810
811 for (i = 0; i < allocatedInstances; i++) {
812 GDevPtr dev = NULL;
813 GDevPtr devBus = NULL;
814
815 pPci = instances[i].pci;
816 for (j = 0; j < numDevs; j++) {
817 if (devList[j]->busID && *devList[j]->busID) {
818 if (xf86ComparePciBusString(devList[j]->busID,
819 PCI_MAKE_BUS(pPci->domain,
820 pPci->bus), pPci->dev,
821 pPci->func) &&
822 devList[j]->screen == instances[i].screen) {
823
824 if (devBus)
825 xf86MsgVerb(X_WARNING, 0,
826 "%s: More than one matching Device section for "
827 "instances\n\t(BusID: %s) found: %s\n",
828 driverName, devList[j]->busID,
829 devList[j]->identifier);
830 else
831 devBus = devList[j];
832 }
833 }
834 else {
835 /*
836 * if device section without BusID is found
837 * only assign to it to the primary device.
838 */
839 if (xf86IsPrimaryPci(pPci)) {
840 xf86Msg(X_PROBED, "Assigning device section with no busID"
841 " to primary device\n");
842 if (dev || devBus)
843 xf86MsgVerb(X_WARNING, 0,
844 "%s: More than one matching Device section "
845 "found: %s\n", driverName,
846 devList[j]->identifier);
847 else
848 dev = devList[j];
849 }
850 }
851 }
852 if (devBus)
853 dev = devBus; /* busID preferred */
854 if (!dev) {
855 if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) {
856 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
857 "for instance (BusID PCI:%u@%u:%u:%u) found\n",
858 driverName, pPci->domain, pPci->bus, pPci->dev,
859 pPci->func);
860 }
861 }
862 else {
863 numClaimedInstances++;
864 instances[i].claimed = TRUE;
865 instances[i].dev = dev;
866 }
867 }
868 DebugF("%s instances found: %d\n", driverName, numClaimedInstances);
869 /*
870 * Now check that a chipset or chipID override in the device section
871 * is valid. Chipset has precedence over chipID.
872 * If chipset is not valid ignore BusSlot completely.
873 */
874 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
875 MessageType from = X_PROBED;
876
877 if (!instances[i].claimed) {
878 continue;
879 }
880 if (instances[i].dev->chipset) {
881 for (c = chipsets; c->token >= 0; c++) {
882 if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0)
883 break;
884 }
885 if (c->token == -1) {
886 instances[i].claimed = FALSE;
887 numClaimedInstances--;
888 xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
889 "section \"%s\" isn't valid for this driver\n",
890 driverName, instances[i].dev->chipset,
891 instances[i].dev->identifier);
892 }
893 else {
894 instances[i].chip = c->token;
895
896 for (id = PCIchipsets; id->numChipset >= 0; id++) {
897 if (id->numChipset == instances[i].chip)
898 break;
899 }
900 if (id->numChipset >= 0) {
901 xf86Msg(X_CONFIG, "Chipset override: %s\n",
902 instances[i].dev->chipset);
903 from = X_CONFIG;
904 }
905 else {
906 instances[i].claimed = FALSE;
907 numClaimedInstances--;
908 xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
909 "section \"%s\" isn't a valid PCI chipset\n",
910 driverName, instances[i].dev->chipset,
911 instances[i].dev->identifier);
912 }
913 }
914 }
915 else if (instances[i].dev->chipID > 0) {
916 for (id = PCIchipsets; id->numChipset >= 0; id++) {
917 if (id->PCIid == instances[i].dev->chipID)
918 break;
919 }
920 if (id->numChipset == -1) {
921 instances[i].claimed = FALSE;
922 numClaimedInstances--;
923 xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device "
924 "section \"%s\" isn't valid for this driver\n",
925 driverName, instances[i].dev->chipID,
926 instances[i].dev->identifier);
927 }
928 else {
929 instances[i].chip = id->numChipset;
930
931 xf86Msg(X_CONFIG, "ChipID override: 0x%04X\n",
932 instances[i].dev->chipID);
933 from = X_CONFIG;
934 }
935 }
936 else if (!instances[i].foundHW) {
937 /*
938 * This means that there was no override and the PCI chipType
939 * doesn't match one that is supported
940 */
941 instances[i].claimed = FALSE;
942 numClaimedInstances--;
943 }
944 if (instances[i].claimed == TRUE) {
945 for (c = chipsets; c->token >= 0; c++) {
946 if (c->token == instances[i].chip)
947 break;
948 }
949 xf86Msg(from, "Chipset %s found\n", c->name);
950 }
951 }
952
953 /*
954 * Of the claimed instances, check that another driver hasn't already
955 * claimed its slot.
956 */
957 numFound = 0;
958 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
959 if (!instances[i].claimed)
960 continue;
961 pPci = instances[i].pci;
962
963 /*
964 * Allow the same entity to be used more than once for devices with
965 * multiple screens per entity. This assumes implicitly that there
966 * will be a screen == 0 instance.
967 *
968 * XXX Need to make sure that two different drivers don't claim
969 * the same screen > 0 instance.
970 */
971 if (instances[i].screen == 0 && !xf86CheckPciSlot(pPci))
972 continue;
973
974 DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
975 driverName, pPci->bus, pPci->dev, pPci->func);
976
977 /* Allocate an entry in the lists to be returned */
978 numFound++;
979 retEntities = xnfrealloc(retEntities, numFound * sizeof(int));
980 retEntities[numFound - 1] = xf86ClaimPciSlot(pPci, drvp,
981 instances[i].chip,
982 instances[i].dev,
983 instances[i].dev->active);
984 if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) {
985 for (j = 0; j < xf86NumEntities; j++) {
986 EntityPtr pEnt = xf86Entities[j];
987
988 if (pEnt->bus.type != BUS_PCI)
989 continue;
990 if (pEnt->bus.id.pci == pPci) {
991 retEntities[numFound - 1] = j;
992 xf86AddDevToEntity(j, instances[i].dev);
993 break;
994 }
995 }
996 }
997 }
998 free(instances);
999 if (numFound > 0) {
1000 *foundEntities = retEntities;
1001 }
1002
1003 return numFound;
1004}
1005
1006/*
1007 * xf86ConfigPciEntityInactive() -- This function can be used
1008 * to configure an inactive entity as well as to reconfigure an
1009 * previously active entity inactive. If the entity has been
1010 * assigned to a screen before it will be removed. If p_chip is
1011 * non-NULL all static resources listed there will be registered.
1012 */
1013static void
1014xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets * p_chip,
1015 EntityProc init, EntityProc enter,
1016 EntityProc leave, pointer private)
1017{
1018 ScrnInfoPtr pScrn;
1019
1020 if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1021 xf86RemoveEntityFromScreen(pScrn, pEnt->index);
1022
1023 /* shared resources are only needed when entity is active: remove */
1024 xf86SetEntityFuncs(pEnt->index, init, enter, leave, private);
1025}
1026
1027ScrnInfoPtr
1028xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1029 PciChipsets * p_chip, void *dummy, EntityProc init,
1030 EntityProc enter, EntityProc leave, pointer private)
1031{
1032 EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1033
1034 if (!pEnt)
1035 return pScrn;
1036
1037 if (!(pEnt->location.type == BUS_PCI)
1038 || !xf86GetPciInfoForEntity(entityIndex)) {
1039 free(pEnt);
1040 return pScrn;
1041 }
1042 if (!pEnt->active) {
1043 xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, leave, private);
1044 free(pEnt);
1045 return pScrn;
1046 }
1047
1048 if (!pScrn)
1049 pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
1050 if (xf86IsEntitySharable(entityIndex)) {
1051 xf86SetEntityShared(entityIndex);
1052 }
1053 xf86AddEntityToScreen(pScrn, entityIndex);
1054 if (xf86IsEntityShared(entityIndex)) {
1055 return pScrn;
1056 }
1057 free(pEnt);
1058
1059 xf86SetEntityFuncs(entityIndex, init, enter, leave, private);
1060
1061 return pScrn;
1062}
1063
1064/*
1065 * OBSOLETE ! xf86ConfigActivePciEntity() is an obsolete function.
1066 * It is likely to be removed. Don't use!
1067 */
1068Bool
1069xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex,
1070 PciChipsets * p_chip, void *dummy, EntityProc init,
1071 EntityProc enter, EntityProc leave, pointer private)
1072{
1073 EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1074
1075 if (!pEnt)
1076 return FALSE;
1077
1078 if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) {
1079 free(pEnt);
1080 return FALSE;
1081 }
1082 xf86AddEntityToScreen(pScrn, entityIndex);
1083
1084 free(pEnt);
1085 if (!xf86SetEntityFuncs(entityIndex, init, enter, leave, private))
1086 return FALSE;
1087
1088 return TRUE;
1089}
1090
1091int
1092xf86VideoPtrToDriverList(struct pci_device *dev,
1093 char *returnList[], int returnListMax)
1094{
1095 int i;
1096
1097 /* Add more entries here if we ever return more than 4 drivers for
1098 any device */
1099 const char *driverList[5] = { NULL, NULL, NULL, NULL, NULL };
1100
1101 switch (dev->vendor_id) {
1102 /* AMD Geode LX */
1103 case 0x1022:
1104 if (dev->device_id == 0x2081)
1105 driverList[0] = "geode";
1106 break;
1107 /* older Geode products acquired by AMD still carry an NSC vendor_id */
1108 case 0x100b:
1109 if (dev->device_id == 0x0030) {
1110 /* NSC Geode GX2 specifically */
1111 driverList[0] = "geode";
1112 /* GX2 support started its life in the NSC tree and was later
1113 forked by AMD for GEODE so we keep it as a backup */
1114 driverList[1] = "nsc";
1115 }
1116 else
1117 /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */
1118 driverList[0] = "nsc";
1119 break;
1120 /* Cyrix Geode GX1 */
1121 case 0x1078:
1122 if (dev->device_id == 0x0104)
1123 driverList[0] = "cyrix";
1124 break;
1125 case 0x1142:
1126 driverList[0] = "apm";
1127 break;
1128 case 0xedd8:
1129 driverList[0] = "ark";
1130 break;
1131 case 0x1a03:
1132 driverList[0] = "ast";
1133 break;
1134 case 0x1002:
1135 driverList[0] = "ati";
1136 break;
1137 case 0x102c:
1138 driverList[0] = "chips";
1139 break;
1140 case 0x1013:
1141 driverList[0] = "cirrus";
1142 break;
1143 case 0x3d3d:
1144 driverList[0] = "glint";
1145 break;
1146 case 0x105d:
1147 driverList[0] = "i128";
1148 break;
1149 case 0x8086:
1150 switch (dev->device_id)
1151 {
1152 /* Intel i740 */
1153 case 0x00d1:
1154 case 0x7800:
1155 driverList[0] = "i740";
1156 break;
1157 /* GMA500/Poulsbo */
1158 case 0x8108:
1159 case 0x8109:
1160 /* Try psb driver on Poulsbo - if available */
1161 driverList[0] = "psb";
1162 driverList[1] = "psb_drv";
1163 break;
1164 /* GMA600/Oaktrail */
1165 case 0x4100:
1166 case 0x4101:
1167 case 0x4102:
1168 case 0x4103:
1169 case 0x4104:
1170 case 0x4105:
1171 case 0x4106:
1172 case 0x4107:
1173 /* Atom E620/Oaktrail */
1174 case 0x4108:
1175 /* Medfield */
1176 case 0x0130:
1177 case 0x0131:
1178 case 0x0132:
1179 case 0x0133:
1180 case 0x0134:
1181 case 0x0135:
1182 case 0x0136:
1183 case 0x0137:
1184 /* GMA 3600/CDV */
1185 case 0x0be0:
1186 case 0x0be1:
1187 case 0x0be2:
1188 case 0x0be3:
1189 case 0x0be4:
1190 case 0x0be5:
1191 case 0x0be6:
1192 case 0x0be7:
1193 case 0x0be8:
1194 case 0x0be9:
1195 case 0x0bea:
1196 case 0x0beb:
1197 case 0x0bec:
1198 case 0x0bed:
1199 case 0x0bee:
1200 case 0x0bef:
1201 /* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */
1202 break;
1203 default:
1204 driverList[0] = "intel";
1205 break;
1206 }
1207 break;
1208 case 0x102b:
1209 driverList[0] = "mga";
1210 break;
1211 case 0x10c8:
1212 driverList[0] = "neomagic";
1213 break;
1214 case 0x10de:
1215 case 0x12d2:
1216 {
1217 int idx = 0;
1218
1219#ifdef __linux__
1220 driverList[idx++] = "nouveau";
1221#endif
1222 driverList[idx++] = "nv";
1223 break;
1224 }
1225 case 0x1106:
1226 driverList[0] = "openchrome";
1227 break;
1228 case 0x1b36:
1229 driverList[0] = "qxl";
1230 break;
1231 case 0x1163:
1232 driverList[0] = "rendition";
1233 break;
1234 case 0x5333:
1235 switch (dev->device_id) {
1236 case 0x88d0:
1237 case 0x88d1:
1238 case 0x88f0:
1239 case 0x8811:
1240 case 0x8812:
1241 case 0x8814:
1242 case 0x8901:
1243 driverList[0] = "s3";
1244 break;
1245 case 0x5631:
1246 case 0x883d:
1247 case 0x8a01:
1248 case 0x8a10:
1249 case 0x8c01:
1250 case 0x8c03:
1251 case 0x8904:
1252 case 0x8a13:
1253 driverList[0] = "s3virge";
1254 break;
1255 default:
1256 driverList[0] = "savage";
1257 break;
1258 }
1259 break;
1260 case 0x1039:
1261 driverList[0] = "sis";
1262 break;
1263 case 0x126f:
1264 driverList[0] = "siliconmotion";
1265 break;
1266 case 0x121a:
1267 if (dev->device_id < 0x0003)
1268 driverList[0] = "voodoo";
1269 else
1270 driverList[0] = "tdfx";
1271 break;
1272 case 0x1011:
1273 driverList[0] = "tga";
1274 break;
1275 case 0x1023:
1276 driverList[0] = "trident";
1277 break;
1278 case 0x100c:
1279 driverList[0] = "tseng";
1280 break;
1281 case 0x80ee:
1282 driverList[0] = "vboxvideo";
1283 break;
1284 case 0x15ad:
1285 driverList[0] = "vmware";
1286 break;
1287 case 0x18ca:
1288 if (dev->device_id == 0x47)
1289 driverList[0] = "xgixp";
1290 else
1291 driverList[0] = "xgi";
1292 break;
1293 default:
1294 break;
1295 }
1296 for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) {
1297 returnList[i] = xnfstrdup(driverList[i]);
1298 }
1299 return i; /* Number of entries added */
1300}
1301
1302#ifdef __linux__
1303static int
1304xchomp(char *line)
1305{
1306 size_t len = 0;
1307
1308 if (!line) {
1309 return 1;
1310 }
1311
1312 len = strlen(line);
1313 if (line[len - 1] == '\n' && len > 0) {
1314 line[len - 1] = '\0';
1315 }
1316 return 0;
1317}
1318
1319/* This function is used to provide a workaround for binary drivers that
1320 * don't export their PCI ID's properly. If distros don't end up using this
1321 * feature it can and should be removed because the symbol-based resolution
1322 * scheme should be the primary one */
1323void
1324xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip)
1325{
1326 DIR *idsdir;
1327 FILE *fp;
1328 struct dirent *direntry;
1329 char *line = NULL;
1330 size_t len;
1331 ssize_t read;
1332 char path_name[256], vendor_str[5], chip_str[5];
1333 uint16_t vendor, chip;
1334 int i, j;
1335
1336 idsdir = opendir(PCI_TXT_IDS_PATH);
1337 if (!idsdir)
1338 return;
1339
1340 xf86Msg(X_INFO,
1341 "Scanning %s directory for additional PCI ID's supported by the drivers\n",
1342 PCI_TXT_IDS_PATH);
1343 direntry = readdir(idsdir);
1344 /* Read the directory */
1345 while (direntry) {
1346 if (direntry->d_name[0] == '.') {
1347 direntry = readdir(idsdir);
1348 continue;
1349 }
1350 len = strlen(direntry->d_name);
1351 /* A tiny bit of sanity checking. We should probably do better */
1352 if (strncmp(&(direntry->d_name[len - 4]), ".ids", 4) == 0) {
1353 /* We need the full path name to open the file */
1354 snprintf(path_name, sizeof(path_name), "%s/%s",
1355 PCI_TXT_IDS_PATH, direntry->d_name);
1356 fp = fopen(path_name, "r");
1357 if (fp == NULL) {
1358 xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n",
1359 path_name);
1360 goto end;
1361 }
1362 /* Read the file */
1363#ifdef __GLIBC__
1364 while ((read = getline(&line, &len, fp)) != -1) {
1365#else
1366 while ((line = fgetln(fp, &len)) != (char *) NULL) {
1367#endif /* __GLIBC __ */
1368 xchomp(line);
1369 if (isdigit(line[0])) {
1370 strlcpy(vendor_str, line, sizeof(vendor_str));
1371 vendor = (int) strtol(vendor_str, NULL, 16);
1372 if ((strlen(&line[4])) == 0) {
1373 chip_str[0] = '\0';
1374 chip = -1;
1375 }
1376 else {
1377 /* Handle trailing whitespace */
1378 if (isspace(line[4])) {
1379 chip_str[0] = '\0';
1380 chip = -1;
1381 }
1382 else {
1383 /* Ok, it's a real ID */
1384 strlcpy(chip_str, &line[4], sizeof(chip_str));
1385 chip = (int) strtol(chip_str, NULL, 16);
1386 }
1387 }
1388 if (vendor == match_vendor && chip == match_chip) {
1389 i = 0;
1390 while (matches[i]) {
1391 i++;
1392 }
1393 matches[i] =
1394 (char *) malloc(sizeof(char) *
1395 strlen(direntry->d_name) - 3);
1396 if (!matches[i]) {
1397 xf86Msg(X_ERROR,
1398 "Could not allocate space for the module name. Exiting.\n");
1399 goto end;
1400 }
1401 /* hack off the .ids suffix. This should guard
1402 * against other problems, but it will end up
1403 * taking off anything after the first '.' */
1404 for (j = 0; j < (strlen(direntry->d_name) - 3); j++) {
1405 if (direntry->d_name[j] == '.') {
1406 matches[i][j] = '\0';
1407 break;
1408 }
1409 else {
1410 matches[i][j] = direntry->d_name[j];
1411 }
1412 }
1413 xf86Msg(X_INFO, "Matched %s from file name %s\n",
1414 matches[i], direntry->d_name);
1415 }
1416 }
1417 else {
1418 /* TODO Handle driver overrides here */
1419 }
1420 }
1421 fclose(fp);
1422 }
1423 direntry = readdir(idsdir);
1424 }
1425 end:
1426 free(line);
1427 closedir(idsdir);
1428}
1429#endif /* __linux__ */
1430
1431/**
1432 * @return The numbers of found devices that match with the current system
1433 * drivers.
1434 */
1435int
1436xf86PciMatchDriver(char *matches[], int nmatches)
1437{
1438 int i;
1439 struct pci_device *info = NULL;
1440 struct pci_device_iterator *iter;
1441
1442 /* Find the primary device, and get some information about it. */
1443 iter = pci_slot_match_iterator_create(NULL);
1444 while ((info = pci_device_next(iter)) != NULL) {
1445 if (xf86IsPrimaryPci(info)) {
1446 break;
1447 }
1448 }
1449
1450 pci_iterator_destroy(iter);
1451#ifdef __linux__
1452 if (info)
1453 xf86MatchDriverFromFiles(matches, info->vendor_id, info->device_id);
1454#endif
1455
1456 for (i = 0; (i < nmatches) && (matches[i]); i++) {
1457 /* find end of matches list */
1458 }
1459
1460 if ((info != NULL) && (i < nmatches)) {
1461 i += xf86VideoPtrToDriverList(info, &(matches[i]), nmatches - i);
1462 }
1463
1464 return i;
1465}
1466
1467Bool
1468xf86PciConfigure(void *busData, struct pci_device *pDev)
1469{
1470 struct pci_device *pVideo = NULL;
1471
1472 pVideo = (struct pci_device *) busData;
1473 if (pDev &&
1474 (pDev->domain == pVideo->domain) &&
1475 (pDev->bus == pVideo->bus) &&
1476 (pDev->dev == pVideo->dev) && (pDev->func == pVideo->func))
1477 return 0;
1478
1479 return 1;
1480}
1481
1482void
1483xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
1484 GDevRec * GDev, int *chipset)
1485{
1486 char busnum[8];
1487
1488 pVideo = (struct pci_device *) busData;
1489
1490 if (pVideo->bus < 256)
1491 snprintf(busnum, sizeof(busnum), "%d", pVideo->bus);
1492 else
1493 snprintf(busnum, sizeof(busnum), "%d@%d",
1494 pVideo->bus & 0x00ff, pVideo->bus >> 8);
1495
1496 XNFasprintf(&GDev->busID, "PCI:%s:%d:%d",
1497 busnum, pVideo->dev, pVideo->func);
1498
1499 GDev->chipID = pVideo->device_id;
1500 GDev->chipRev = pVideo->revision;
1501
1502 if (*chipset < 0)
1503 *chipset = (pVideo->vendor_id << 16) | pVideo->device_id;
1504}
1505
1506struct pci_io_handle *
1507xf86MapLegacyIO(struct pci_device *dev)
1508{
1509 return pci_legacy_open_io(dev, 0, 64 * 1024);
1510}
1511
1512void
1513xf86UnmapLegacyIO(struct pci_device *dev, struct pci_io_handle *handle)
1514{
1515 pci_device_close_io(dev, handle);
1516}