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