Commit cf664713 authored by Dave Airlie's avatar Dave Airlie

xfree86: use udev to provide device enumeration for kms devices (v10)

On Linux in order for future hotplug work, we are required to interface
to udev to detect device creation/removal. In order to try and get
some earlier testing on this, this patch adds the ability to use
udev for device enumeration on Linux.

At startup the list of drm/kms devices is probed and this info is
used to load drivers.

A new driver probing method is introduced that passes the udev
device info to the driver for probing.

The probing integrates with the pci probing code and will fallback
to the pci probe and old school probe functions in turn.

The flags parameter to the probe function will be used later
to provide hotplug and gpu screen flags for the driver to behave
in a different way.

This patch changes the driver ABI, all drivers should at least
be set with a NULL udev probe function after this commit.

v2: rename to platform bus, now with 100% less udev specific,

this version passes config_odev_attribs around which are an array
of id/string pairs, then the udev code can attach the set of attribs
it understands, the OS specific code can attach its attrib, and then
the core/drivers can lookup the required attribs.

also add MATCH_PCI_DEVICES macro.

This version is mainly to address concerns raised by ajax.

v3: Address comments from Peter.
fix whitespace that snuck in.
rework to use a linked list with some core functions that
xf86 wraps.

v4: add free list, fix struct whitespace.
ajax this address most of your issues?

v5: drop probe ifdef, fix logic issue

v6: some overhaul after more testing.

Implement primaryBus for platform devices.
document hotplug.h dev attribs - drop sysname attrib
fix build with udev kms disabled
make probing work like the PCI probe code,
   match against bus id if one exists, or primary device.

RFC: add new bus id support "PLAT:syspath". we probably
want to match on this a bit different, or use a different
property maybe. I was mainly wanting this for use with
specifying usb devices in xorg.conf directly, but PLAT:path
could also work I suppose.

v6.1: add missing noop platform function

v7: fix two interactions with pci probing and slot claiming, prevents
pci and platform trying to load two drivers for same slot.

v8: test with zaphod mode on -ati driver, fixup resulting issue
clean up common probe code into another function, change busid
matching to allow dropping end of strings.

v9: fix platform probing logic so it actually works.
v9.1: fix pdev init to NULL properly.

v10: address most of Keith's concerns.

v4 was thanks to Reviewed-by: Adam Jackson <ajax@redhat.com>
v5 was Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Keith Packard's avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 2c52d776
......@@ -36,6 +36,7 @@ BOOL device_is_duplicate(const char *config_info);
int config_udev_pre_init(void);
int config_udev_init(void);
void config_udev_fini(void);
void config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback);
#else
#ifdef CONFIG_NEED_DBUS
......
......@@ -85,6 +85,14 @@ config_fini(void)
#endif
}
void
config_odev_probe(config_odev_probe_proc_ptr probe_callback)
{
#if defined(CONFIG_UDEV_KMS)
config_udev_odev_probe(probe_callback);
#endif
}
static void
remove_device(const char *backend, DeviceIntPtr dev)
{
......@@ -133,3 +141,51 @@ device_is_duplicate(const char *config_info)
return FALSE;
}
struct OdevAttributes *
config_odev_allocate_attribute_list(void)
{
struct OdevAttributes *attriblist;
attriblist = malloc(sizeof(struct OdevAttributes));
if (!attriblist)
return NULL;
xorg_list_init(&attriblist->list);
return attriblist;
}
void
config_odev_free_attribute_list(struct OdevAttributes *attribs)
{
config_odev_free_attributes(attribs);
free(attribs);
}
Bool
config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
const char *attrib_name)
{
struct OdevAttribute *oa;
oa = malloc(sizeof(struct OdevAttribute));
if (!oa)
return FALSE;
oa->attrib_id = attrib;
oa->attrib_name = strdup(attrib_name);
xorg_list_append(&oa->member, &attribs->list);
return TRUE;
}
void
config_odev_free_attributes(struct OdevAttributes *attribs)
{
struct OdevAttribute *iter, *safe;
xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
xorg_list_del(&iter->member);
free(iter->attrib_name);
free(iter);
}
}
......@@ -366,3 +366,72 @@ config_udev_fini(void)
udev_monitor = NULL;
udev_unref(udev);
}
#ifdef CONFIG_UDEV_KMS
static Bool
config_udev_odev_setup_attribs(const char *path, const char *syspath,
config_odev_probe_proc_ptr probe_callback)
{
struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
int ret;
if (!attribs)
return FALSE;
ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_PATH, path);
if (ret == FALSE)
goto fail;
ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSPATH, syspath);
if (ret == FALSE)
goto fail;
/* ownership of attribs is passed to probe layer */
probe_callback(attribs);
return TRUE;
fail:
config_odev_free_attributes(attribs);
free(attribs);
return FALSE;
}
void
config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *device;
udev = udev_monitor_get_udev(udev_monitor);
enumerate = udev_enumerate_new(udev);
if (!enumerate)
return;
udev_enumerate_add_match_subsystem(enumerate, "drm");
udev_enumerate_add_match_sysname(enumerate, "card[0-9]*");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(device, devices) {
const char *syspath = udev_list_entry_get_name(device);
struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
const char *path = udev_device_get_devnode(udev_device);
const char *sysname = udev_device_get_sysname(udev_device);
if (!path || !syspath)
goto no_probe;
else if (strcmp(udev_device_get_subsystem(udev_device), "drm") != 0)
goto no_probe;
else if (strncmp(sysname, "card", 4) != 0)
goto no_probe;
config_udev_odev_setup_attribs(path, syspath, probe_callback);
no_probe:
udev_device_unref(udev_device);
}
udev_enumerate_unref(enumerate);
return;
}
#endif
......@@ -615,6 +615,7 @@ AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extensi
AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no])
AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes])
AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto])
AC_ARG_ENABLE(config-udev-kms, AS_HELP_STRING([--enable-config-udev-kms], [Build udev kms support (default: auto)]), [CONFIG_UDEV_KMS=$enableval], [CONFIG_UDEV_KMS=auto])
AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no])
AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto])
AC_ARG_ENABLE(config-wscons, AS_HELP_STRING([--enable-config-wscons], [Build wscons config support (default: auto)]), [CONFIG_WSCONS=$enableval], [CONFIG_WSCONS=auto])
......@@ -704,6 +705,7 @@ case $host_os in
CONFIG_DBUS_API=no
CONFIG_HAL=no
CONFIG_UDEV=no
CONFIG_UDEV_KMS=no
DGA=no
DRI2=no
INT10MODULE=no
......@@ -838,11 +840,16 @@ AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes])
if test "x$CONFIG_UDEV" = xyes; then
CONFIG_DBUS_API=no
CONFIG_HAL=no
if test "x$CONFIG_UDEV_KMS" = xauto; then
CONFIG_UDEV_KMS="$HAVE_LIBUDEV"
fi
if ! test "x$HAVE_LIBUDEV" = xyes; then
AC_MSG_ERROR([udev configuration API requested, but libudev is not installed])
fi
AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug])
if test "x$CONFIG_UDEV_KMS" = xyes; then
AC_DEFINE(CONFIG_UDEV_KMS, 1, [Use libudev for kms enumeration])
fi
SAVE_LIBS=$LIBS
SAVE_CFLAGS=$CFLAGS
CFLAGS=$UDEV_CFLAGS
......@@ -852,6 +859,7 @@ if test "x$CONFIG_UDEV" = xyes; then
LIBS=$SAVE_LIBS
CFLAGS=$SAVE_CFLAGS
fi
AM_CONDITIONAL(CONFIG_UDEV_KMS, [test "x$CONFIG_UDEV_KMS" = xyes])
dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas
dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
......@@ -1099,7 +1107,7 @@ case "$DRI2,$HAVE_DRI2PROTO" in
esac
AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
if test "x$DRI" = xyes || test "x$DRI2" = xyes; then
if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
if test "x$DRM" = xyes; then
AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support])
PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
......@@ -1650,7 +1658,7 @@ if test "x$XORG" = xyes; then
PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS)
SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $LIBPCIACCESS"
XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS"
XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS $LIBDRM_LIBS"
XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS"
AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci manipulation])
......@@ -1668,6 +1676,10 @@ if test "x$XORG" = xyes; then
fi
AC_MSG_RESULT([$PCI])
if test "x$CONFIG_UDEV_KMS" = xyes; then
AC_DEFINE(XSERVER_PLATFORM_BUS, 1, [X server supports platform device enumeration])
fi
AC_MSG_RESULT([$XSERVER_PLATFORM_BUS])
dnl ===================================================================
dnl ==================== end of PCI configuration =====================
dnl ===================================================================
......@@ -1856,7 +1868,7 @@ AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes])
AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes])
AM_CONDITIONAL([DGA], [test "x$DGA" = xyes])
AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes])
AM_CONDITIONAL([XORG_BUS_PLATFORM], [test "x$CONFIG_UDEV_KMS" = xyes])
dnl XWin DDX
AC_MSG_CHECKING([whether to build XWin DDX])
......
......@@ -22,9 +22,13 @@ if DGA
DGASOURCES = xf86DGA.c
endif
if XORG_BUS_PLATFORM
PLATSOURCES = xf86platformBus.c
endif
RANDRSOURCES = xf86RandR.c
BUSSOURCES = xf86fbBus.c xf86noBus.c $(PCI_SOURCES) $(SBUS_SOURCES)
BUSSOURCES = xf86fbBus.c xf86noBus.c $(PCI_SOURCES) $(SBUS_SOURCES) $(PLATSOURCES)
MODEDEFSOURCES = $(srcdir)/vesamodes $(srcdir)/extramodes
......@@ -56,7 +60,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \
xf86PciInfo.h xf86Priv.h xf86Privstr.h \
xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \
$(XVSDKINCS) $(XF86VMODE_SDK) xorgVersion.h \
xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h
xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h xf86platformBus.h
DISTCLEANFILES = xf86Build.h
CLEANFILES = $(BUILT_SOURCES)
......
......@@ -71,6 +71,11 @@ extern _X_EXPORT Bool fbSlotClaimed;
#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
extern _X_EXPORT Bool sbusSlotClaimed;
#endif
#if defined(XSERVER_PLATFORM_BUS)
extern _X_EXPORT int platformSlotClaimed;
#endif
extern _X_EXPORT confDRIRec xf86ConfigDRI;
extern _X_EXPORT Bool xf86DRI2Enabled(void);
......
......@@ -198,10 +198,13 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
}
i = 0;
#ifdef XSERVER_PLATFORM_BUS
i = xf86PlatformMatchDriver(matches, nmatches);
#endif
#ifdef sun
/* Check for driver type based on /dev/fb type and if valid, use
it instead of PCI bus probe results */
if (xf86Info.consoleFd >= 0) {
if (xf86Info.consoleFd >= 0 && (i < (nmatches - 1))) {
struct vis_identifier visid;
const char *cp;
extern char xf86SolarisFbDev[PATH_MAX];
......@@ -251,6 +254,7 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
}
#endif
#ifdef __sparc__
if (i < (nmatches - 1))
{
char *sbusDriver = sparcDriverName();
......@@ -259,7 +263,8 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
}
#endif
#ifdef XSERVER_LIBPCIACCESS
i = xf86PciMatchDriver(matches, nmatches);
if (i < (nmatches - 1))
i = xf86PciMatchDriver(matches, nmatches);
#endif
/* Fallback to platform default hardware */
if (i < (nmatches - 1)) {
......
......@@ -77,8 +77,14 @@ xf86CallDriverProbe(DriverPtr drv, Bool detect_only)
{
Bool foundScreen = FALSE;
#ifdef XSERVER_PLATFORM_BUS
if (drv->platformProbe != NULL) {
foundScreen = xf86platformProbeDev(drv);
}
#endif
#ifdef XSERVER_LIBPCIACCESS
if (drv->PciProbe != NULL) {
if (!foundScreen && (drv->PciProbe != NULL)) {
if (xf86DoConfigure && xf86DoConfigurePass1) {
assert(detect_only);
foundScreen = xf86PciAddMatchingDev(drv);
......@@ -202,6 +208,9 @@ xf86BusConfig(void)
void
xf86BusProbe(void)
{
#ifdef XSERVER_PLATFORM_BUS
xf86platformProbe();
#endif
#ifdef XSERVER_LIBPCIACCESS
xf86PciProbe();
#endif
......@@ -238,6 +247,8 @@ StringToBusType(const char *busID, const char **retID)
ret = BUS_PCI;
if (!xf86NameCmp(p, "sbus"))
ret = BUS_SBUS;
if (!xf86NameCmp(p, "platform"))
ret = BUS_PLATFORM;
if (ret != BUS_NONE)
if (retID)
*retID = busID + strlen(p) + 1;
......@@ -270,6 +281,8 @@ xf86IsEntityPrimary(int entityIndex)
return pEnt->bus.id.pci == primaryBus.id.pci;
case BUS_SBUS:
return pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum;
case BUS_PLATFORM:
return pEnt->bus.id.plat == primaryBus.id.plat;
default:
return FALSE;
}
......@@ -541,6 +554,9 @@ xf86PostProbe(void)
#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
sbusSlotClaimed ||
#endif
#ifdef XSERVER_PLATFORM_BUS
platformSlotClaimed ||
#endif
#ifdef XSERVER_LIBPCIACCESS
pciSlotClaimed
#else
......
......@@ -42,6 +42,7 @@
#if defined(__sparc__) || defined(__sparc)
#include "xf86sbusBus.h"
#endif
#include "xf86platformBus.h"
typedef struct {
DriverPtr driver;
......
......@@ -54,6 +54,10 @@ xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active)
EntityPtr p;
int num;
#ifdef XSERVER_PLATFORM_BUS
if (platformSlotClaimed)
return -1;
#endif
#ifdef XSERVER_LIBPCIACCESS
if (pciSlotClaimed)
return -1;
......
......@@ -110,7 +110,7 @@ xf86PciProbe(void)
xf86PciVideoInfo[num - 1] = info;
pci_device_probe(info);
if (pci_device_is_boot_vga(info)) {
if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) {
primaryBus.type = BUS_PCI;
primaryBus.id.pci = info;
}
......@@ -352,7 +352,15 @@ xf86ComparePciBusString(const char *busID, int bus, int device, int func)
Bool
xf86IsPrimaryPci(struct pci_device *pPci)
{
return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci));
if (primaryBus.type == BUS_PCI)
return pPci == primaryBus.id.pci;
#ifdef XSERVER_PLATFORM_BUS
if (primaryBus.type == BUS_PLATFORM)
if (primaryBus.id.plat->pdev)
if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci))
return TRUE;
#endif
return FALSE;
}
/*
......@@ -367,7 +375,15 @@ xf86GetPciInfoForEntity(int entityIndex)
return NULL;
p = xf86Entities[entityIndex];
return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL;
switch (p->bus.type) {
case BUS_PCI:
return p->bus.id.pci;
case BUS_PLATFORM:
return p->bus.id.plat->pdev;
default:
break;
}
return NULL;
}
/*
......@@ -400,6 +416,13 @@ xf86CheckPciSlot(const struct pci_device *d)
if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
return FALSE;
}
#ifdef XSERVER_PLATFORM_BUS
if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) {
struct pci_device *ud = p->bus.id.plat->pdev;
if (MATCH_PCI_DEVICES(ud, d))
return FALSE;
}
#endif
}
return TRUE;
}
......@@ -1065,8 +1088,8 @@ xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex,
return TRUE;
}
static int
videoPtrToDriverList(struct pci_device *dev,
int
xf86VideoPtrToDriverList(struct pci_device *dev,
char *returnList[], int returnListMax)
{
int i;
......@@ -1249,8 +1272,8 @@ xchomp(char *line)
* don't export their PCI ID's properly. If distros don't end up using this
* feature it can and should be removed because the symbol-based resolution
* scheme should be the primary one */
static void
matchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip)
void
xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip)
{
DIR *idsdir;
FILE *fp;
......@@ -1379,7 +1402,7 @@ xf86PciMatchDriver(char *matches[], int nmatches)
pci_iterator_destroy(iter);
#ifdef __linux__
if (info)
matchDriverFromFiles(matches, info->vendor_id, info->device_id);
xf86MatchDriverFromFiles(matches, info->vendor_id, info->device_id);
#endif
for (i = 0; (i < nmatches) && (matches[i]); i++) {
......@@ -1387,7 +1410,7 @@ xf86PciMatchDriver(char *matches[], int nmatches)
}
if ((info != NULL) && (i < nmatches)) {
i += videoPtrToDriverList(info, &(matches[i]), nmatches - i);
i += xf86VideoPtrToDriverList(info, &(matches[i]), nmatches - i);
}
return i;
......
......@@ -42,4 +42,14 @@ Bool xf86PciConfigure(void *busData, struct pci_device *pDev);
void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
GDevRec * GDev, int *chipset);
#define MATCH_PCI_DEVICES(x, y) (((x)->domain == (y)->domain) && \
((x)->bus == (y)->bus) && \
((x)->func == (y)->func) && \
((x)->dev == (y)->dev))
void
xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip);
int
xf86VideoPtrToDriverList(struct pci_device *dev,
char *returnList[], int returnListMax);
#endif /* _XF86_PCI_BUS_H */
This diff is collapsed.
/*
* Copyright © 2012 Red Hat.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Dave Airlie <airlied@redhat.com>
*/
#ifndef XF86_PLATFORM_BUS_H
#define XF86_PLATFORM_BUS_H
#include "hotplug.h"
struct xf86_platform_device {
struct OdevAttributes *attribs;
/* for PCI devices */
struct pci_device *pdev;
};
#ifdef XSERVER_PLATFORM_BUS
int xf86platformProbe(void);
int xf86platformProbeDev(DriverPtr drvp);
extern int xf86_num_platform_devices;
extern char *
xf86_get_platform_attrib(int index, int attrib_id);
extern int
xf86_add_platform_device(struct OdevAttributes *attribs);
extern int
xf86_remove_platform_device(int dev_index);
extern Bool
xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
extern _X_EXPORT char *
xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id);
extern _X_EXPORT Bool
xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
extern _X_EXPORT int
xf86PlatformMatchDriver(char *matches[], int nmatches);
#endif
#endif
......@@ -311,6 +311,7 @@ struct _SymTabRec;
struct _PciChipsets;
struct pci_device;
struct xf86_platform_device;
typedef struct _DriverRec {
int driverVersion;
......@@ -325,8 +326,15 @@ typedef struct _DriverRec {
const struct pci_id_match *supported_devices;
Bool (*PciProbe) (struct _DriverRec * drv, int entity_num,
struct pci_device * dev, intptr_t match_data);
Bool (*platformProbe) (struct _DriverRec * drv, int entity_num, int flags,
struct xf86_platform_device * dev, intptr_t match_data);
} DriverRec, *DriverPtr;
/*
* platform probe flags
* no flags are defined yet - but drivers should fail to load if a flag they
* don't understand is passed.
*/
/*
* AddDriver flags
*/
......@@ -343,6 +351,7 @@ typedef struct _DriverRec {
#undef BUS_NONE
#undef BUS_PCI
#undef BUS_SBUS
#undef BUS_PLATFORM
#undef BUS_last
#endif
......@@ -350,6 +359,7 @@ typedef enum {
BUS_NONE,
BUS_PCI,
BUS_SBUS,
BUS_PLATFORM,
BUS_last /* Keep last */
} BusType;
......@@ -362,6 +372,7 @@ typedef struct _bus {
union {
struct pci_device *pci;
SbusBusId sbus;
struct xf86_platform_device *plat;
} id;
} BusRec, *BusPtr;
......
......@@ -22,7 +22,7 @@ XORG_CFLAGS += -DHAVE_APM
endif
liblinux_la_SOURCES = lnx_init.c lnx_video.c \
lnx_agp.c lnx_kmod.c lnx_bell.c \
lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \
$(srcdir)/../shared/bios_mmap.c \
$(srcdir)/../shared/VTsw_usl.c \
$(srcdir)/../shared/posix_tty.c \
......
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#ifdef XSERVER_PLATFORM_BUS
#include <xf86drm.h>
#include <fcntl.h>
#include <unistd.h>
/* Linux platform device support */
#include "xf86_OSproc.h"
#include "xf86.h"
#include "xf86platformBus.h"
#include "xf86Bus.h"
static Bool
get_drm_info(struct OdevAttributes *attribs, char *path)
{
drmSetVersion sv;
char *buf;
int fd;
fd = open(path, O_RDWR, O_CLOEXEC);
if (fd == -1)
return FALSE;
sv.drm_di_major = 1;
sv.drm_di_minor = 4;
sv.drm_dd_major = -1; /* Don't care */
sv.drm_dd_minor = -1; /* Don't care */
if (drmSetInterfaceVersion(fd, &sv)) {
ErrorF("setversion 1.4 failed\n");
return FALSE;
}
xf86_add_platform_device(attribs);
buf = drmGetBusid(fd);
xf86_add_platform_device_attrib(xf86_num_platform_devices - 1,
ODEV_ATTRIB_BUSID, buf);
drmFreeBusid(buf);
close(fd);
return TRUE;
}
Bool
xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
{
struct OdevAttribute *attrib;
const char *syspath = NULL;
BusType bustype;
const char *id;
xorg_list_for_each_entry(attrib, &device->attribs->list, member) {
if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
syspath = attrib->attrib_name;
break;
}
}
if (!syspath)
return FALSE;
bustype = StringToBusType(busid, &id);
if (bustype == BUS_PCI) {
struct pci_device *pPci = device->pdev;
if (xf86ComparePciBusString(busid,
((pPci->domain << 8)
| pPci->bus),
pPci->dev, pPci->func)) {
return TRUE;
}
}
else if (bustype == BUS_PLATFORM) {
/* match on the minimum string */
int len = strlen(id);
if (strlen(syspath) < strlen(id))
len = strlen(syspath);
if (strncmp(id, syspath, len))
return FALSE;
return TRUE;
}
return FALSE;
}
void
xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
{
struct OdevAttribute *attrib;
int i;
char *path = NULL;
Bool ret;
xorg_list_for_each_entry(attrib, &attribs->list, member) {
if (attrib->attrib_id == ODEV_ATTRIB_PATH) {
path = attrib->attrib_name;
break;
}
}
if (!path)
goto out_free;
for (i = 0; i < xf86_num_platform_devices; i++) {
char *dpath;
dpath = xf86_get_platform_attrib(i, ODEV_ATTRIB_PATH);
if (!strcmp(path, dpath))
break;
}
if (i != xf86_num_platform_devices)
goto out_free;
LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n",
path);
ret = get_drm_info(attribs, path);
if (ret == FALSE)
goto out_free;
return;
out_free:
config_odev_free_attribute_list(attribs);
}
#endif
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#ifdef XSERVER_PLATFORM_BUS
/* noop platform device support */
#include "xf86_OSproc.h"
#include "xf86.h"
#include "xf86platformBus.h"
Bool