aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/config/config-backends.h1
-rw-r--r--xorg-server/config/config.c56
-rw-r--r--xorg-server/config/udev.c111
-rw-r--r--xorg-server/configure.ac20
-rw-r--r--xorg-server/dix/dispatch.c113
-rw-r--r--xorg-server/dix/dixutils.c6
-rw-r--r--xorg-server/dix/main.c15
-rw-r--r--xorg-server/dix/privates.c4
-rw-r--r--xorg-server/hw/xfree86/common/Makefile.am8
-rw-r--r--xorg-server/hw/xfree86/common/xf86.h8
-rw-r--r--xorg-server/hw/xfree86/common/xf86AutoConfig.c9
-rw-r--r--xorg-server/hw/xfree86/common/xf86Bus.c22
-rw-r--r--xorg-server/hw/xfree86/common/xf86Bus.h1
-rw-r--r--xorg-server/hw/xfree86/common/xf86Config.c15
-rw-r--r--xorg-server/hw/xfree86/common/xf86Globals.c11
-rw-r--r--xorg-server/hw/xfree86/common/xf86Helper.c111
-rw-r--r--xorg-server/hw/xfree86/common/xf86Init.c42
-rw-r--r--xorg-server/hw/xfree86/common/xf86Priv.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86Privstr.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86fbBus.c4
-rw-r--r--xorg-server/hw/xfree86/common/xf86pciBus.c41
-rw-r--r--xorg-server/hw/xfree86/common/xf86pciBus.h10
-rw-r--r--xorg-server/hw/xfree86/common/xf86platformBus.c489
-rw-r--r--xorg-server/hw/xfree86/common/xf86platformBus.h64
-rw-r--r--xorg-server/hw/xfree86/common/xf86str.h12
-rw-r--r--xorg-server/hw/xfree86/modes/xf86EdidModes.c13
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/Makefile.am2
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_platform.c179
-rw-r--r--xorg-server/hw/xfree86/os-support/shared/platform_noop.c23
-rw-r--r--xorg-server/hw/xfree86/os-support/xf86_OSproc.h6
-rw-r--r--xorg-server/hw/xfree86/ramdac/xf86Cursor.c31
-rw-r--r--xorg-server/include/dix-config.h.in3
-rw-r--r--xorg-server/include/hotplug.h39
-rw-r--r--xorg-server/include/misc.h4
-rw-r--r--xorg-server/include/screenint.h9
-rw-r--r--xorg-server/include/scrnintstr.h4
-rw-r--r--xorg-server/include/xorg-config.h.in3
-rw-r--r--xorg-server/include/xorg-server.h.in3
-rw-r--r--xorg-server/render/glyph.c2
39 files changed, 1408 insertions, 90 deletions
diff --git a/xorg-server/config/config-backends.h b/xorg-server/config/config-backends.h
index 62abc0a5f..6423701fc 100644
--- a/xorg-server/config/config-backends.h
+++ b/xorg-server/config/config-backends.h
@@ -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
diff --git a/xorg-server/config/config.c b/xorg-server/config/config.c
index 24e7ba7a0..d0889a394 100644
--- a/xorg-server/config/config.c
+++ b/xorg-server/config/config.c
@@ -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);
+ }
+}
diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c
index 1995184f3..5297b9009 100644
--- a/xorg-server/config/udev.c
+++ b/xorg-server/config/udev.c
@@ -52,6 +52,12 @@
static struct udev_monitor *udev_monitor;
+#ifdef CONFIG_UDEV_KMS
+static Bool
+config_udev_odev_setup_attribs(const char *path, const char *syspath,
+ config_odev_probe_proc_ptr probe_callback);
+#endif
+
static void
device_added(struct udev_device *udev_device)
{
@@ -85,6 +91,20 @@ device_added(struct udev_device *udev_device)
if (!SeatId && strcmp(dev_seat, "seat0"))
return;
+#ifdef CONFIG_UDEV_KMS
+ if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
+ const char *sysname = udev_device_get_sysname(udev_device);
+
+ if (strncmp(sysname, "card", 4) != 0)
+ return;
+
+ LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
+
+ config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+ return;
+ }
+#endif
+
if (!udev_device_get_property_value(udev_device, "ID_INPUT")) {
LogMessageVerb(X_INFO, 10,
"config/udev: ignoring device %s without "
@@ -240,6 +260,22 @@ device_removed(struct udev_device *device)
char *value;
const char *syspath = udev_device_get_syspath(device);
+#ifdef CONFIG_UDEV_KMS
+ if (!strcmp(udev_device_get_subsystem(device), "drm")) {
+ const char *sysname = udev_device_get_sysname(device);
+ const char *path = udev_device_get_devnode(device);
+
+ if (strncmp(sysname,"card", 4) != 0)
+ return;
+ ErrorF("removing GPU device %s %d\n", syspath, path);
+ if (!path)
+ return;
+
+ config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+ return;
+ }
+#endif
+
if (asprintf(&value, "udev:%s", syspath) == -1)
return;
@@ -296,6 +332,9 @@ config_udev_pre_init(void)
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
NULL);
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL); /* For Wacom serial devices */
+#ifdef CONFIG_UDEV_KMS
+ udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm", NULL); /* For output GPU devices */
+#endif
#ifdef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG
if (SeatId && strcmp(SeatId, "seat0"))
@@ -322,6 +361,9 @@ config_udev_init(void)
udev_enumerate_add_match_subsystem(enumerate, "input");
udev_enumerate_add_match_subsystem(enumerate, "tty");
+#ifdef CONFIG_UDEV_KMS
+ udev_enumerate_add_match_subsystem(enumerate, "drm");
+#endif
#ifdef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
if (SeatId && strcmp(SeatId, "seat0"))
@@ -366,3 +408,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
+
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index d5ddf6e10..d1358a224 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/configure.ac
@@ -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])
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c
index e78c71e1c..c1ffcb07c 100644
--- a/xorg-server/dix/dispatch.c
+++ b/xorg-server/dix/dispatch.c
@@ -3771,32 +3771,20 @@ with its screen number, a pointer to its ScreenRec, argc, and argv.
*/
-int
-AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
- int /*argc */ ,
- char ** /*argv */
- ), int argc, char **argv)
+static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
{
-
- int i;
int scanlinepad, format, depth, bitsPerPixel, j, k;
- ScreenPtr pScreen;
-
- i = screenInfo.numScreens;
- if (i == MAXSCREENS)
- return -1;
-
- pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
- if (!pScreen)
- return -1;
dixInitScreenSpecificPrivates(pScreen);
if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
- free(pScreen);
return -1;
}
pScreen->myNum = i;
+ if (gpu) {
+ pScreen->myNum += GPU_SCREEN_OFFSET;
+ pScreen->isGPU = TRUE;
+ }
pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
pScreen->CreateScreenResources = 0;
@@ -3831,7 +3819,33 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
PixmapWidthPaddingInfo[depth].notPower2 = 0;
}
}
+ return 0;
+}
+int
+AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+ int /*argc */ ,
+ char ** /*argv */
+ ), int argc, char **argv)
+{
+
+ int i;
+ ScreenPtr pScreen;
+ Bool ret;
+
+ i = screenInfo.numScreens;
+ if (i == MAXSCREENS)
+ return -1;
+
+ pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
+ if (!pScreen)
+ return -1;
+
+ ret = init_screen(pScreen, i, FALSE);
+ if (ret != 0) {
+ free(pScreen);
+ return ret;
+ }
/* This is where screen specific stuff gets initialized. Load the
screen structure, call the hardware, whatever.
This is also where the default colormap should be allocated and
@@ -3857,3 +3871,68 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
return i;
}
+
+int
+AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+ int /*argc */ ,
+ char ** /*argv */
+ ),
+ int argc, char **argv)
+{
+ int i;
+ ScreenPtr pScreen;
+ Bool ret;
+
+ i = screenInfo.numGPUScreens;
+ if (i == MAXGPUSCREENS)
+ return -1;
+
+ pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
+ if (!pScreen)
+ return -1;
+
+ ret = init_screen(pScreen, i, TRUE);
+ if (ret != 0) {
+ free(pScreen);
+ return ret;
+ }
+
+ /* This is where screen specific stuff gets initialized. Load the
+ screen structure, call the hardware, whatever.
+ This is also where the default colormap should be allocated and
+ also pixel values for blackPixel, whitePixel, and the cursor
+ Note that InitScreen is NOT allowed to modify argc, argv, or
+ any of the strings pointed to by argv. They may be passed to
+ multiple screens.
+ */
+ screenInfo.gpuscreens[i] = pScreen;
+ screenInfo.numGPUScreens++;
+ if (!(*pfnInit) (pScreen, argc, argv)) {
+ dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+ free(pScreen);
+ screenInfo.numGPUScreens--;
+ return -1;
+ }
+
+ update_desktop_dimensions();
+
+ return i;
+}
+
+void
+RemoveGPUScreen(ScreenPtr pScreen)
+{
+ int idx, j;
+ if (!pScreen->isGPU)
+ return;
+
+ idx = pScreen->myNum - GPU_SCREEN_OFFSET;
+ for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
+ screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
+ screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
+ }
+ screenInfo.numGPUScreens--;
+
+ free(pScreen);
+
+}
diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c
index b249a810b..3f24629b4 100644
--- a/xorg-server/dix/dixutils.c
+++ b/xorg-server/dix/dixutils.c
@@ -386,6 +386,9 @@ BlockHandler(pointer pTimeout, pointer pReadmask)
for (i = 0; i < screenInfo.numScreens; i++)
(*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i],
pTimeout, pReadmask);
+ for (i = 0; i < screenInfo.numGPUScreens; i++)
+ (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i],
+ pTimeout, pReadmask);
for (i = 0; i < numHandlers; i++)
if (!handlers[i].deleted)
(*handlers[i].BlockHandler) (handlers[i].blockData,
@@ -422,6 +425,9 @@ WakeupHandler(int result, pointer pReadmask)
for (i = 0; i < screenInfo.numScreens; i++)
(*screenInfo.screens[i]->WakeupHandler) (screenInfo.screens[i],
result, pReadmask);
+ for (i = 0; i < screenInfo.numGPUScreens; i++)
+ (*screenInfo.gpuscreens[i]->WakeupHandler) (screenInfo.gpuscreens[i],
+ result, pReadmask);
if (handlerDeleted) {
for (i = 0; i < numHandlers;)
if (handlers[i].deleted) {
diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c
index b8ee88f18..cdca10250 100644
--- a/xorg-server/dix/main.c
+++ b/xorg-server/dix/main.c
@@ -251,6 +251,12 @@ main(int argc, char *argv[], char *envp[])
FatalError("no screens found");
InitExtensions(argc, argv);
+ for (i = 0; i < screenInfo.numGPUScreens; i++) {
+ ScreenPtr pScreen = screenInfo.gpuscreens[i];
+ if (!CreateScratchPixmapsForScreen(pScreen))
+ FatalError("failed to create scratch pixmaps");
+ }
+
for (i = 0; i < screenInfo.numScreens; i++) {
ScreenPtr pScreen = screenInfo.screens[i];
@@ -385,6 +391,15 @@ main(int argc, char *argv[], char *envp[])
screenInfo.numScreens = i;
}
+ for (i = screenInfo.numGPUScreens - 1; i >= 0; i--) {
+ ScreenPtr pScreen = screenInfo.gpuscreens[i];
+ FreeScratchPixmapsForScreen(pScreen);
+ (*pScreen->CloseScreen) (pScreen);
+ dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+ free(pScreen);
+ screenInfo.numGPUScreens = i;
+ }
+
ReleaseClientIds(serverClient);
dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT);
serverClient->devPrivates = NULL;
diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c
index 04fa24ad3..497a2396e 100644
--- a/xorg-server/dix/privates.c
+++ b/xorg-server/dix/privates.c
@@ -233,6 +233,10 @@ fixupScreens(FixupFunc fixup, unsigned bytes)
for (s = 0; s < screenInfo.numScreens; s++)
if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
return FALSE;
+
+ for (s = 0; s < screenInfo.numGPUScreens; s++)
+ if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
+ return FALSE;
return TRUE;
}
diff --git a/xorg-server/hw/xfree86/common/Makefile.am b/xorg-server/hw/xfree86/common/Makefile.am
index 27921777d..65d98e694 100644
--- a/xorg-server/hw/xfree86/common/Makefile.am
+++ b/xorg-server/hw/xfree86/common/Makefile.am
@@ -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)
diff --git a/xorg-server/hw/xfree86/common/xf86.h b/xorg-server/hw/xfree86/common/xf86.h
index 129660d81..61169857f 100644
--- a/xorg-server/hw/xfree86/common/xf86.h
+++ b/xorg-server/hw/xfree86/common/xf86.h
@@ -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);
@@ -460,4 +465,7 @@ extern _X_EXPORT ScreenPtr xf86ScrnToScreen(ScrnInfoPtr pScrn);
#define XF86_SCRN_INTERFACE 1 /* define for drivers to use in api compat */
+/* flags passed to xf86 allocate screen */
+#define XF86_ALLOCATE_GPU_SCREEN 1
+
#endif /* _XF86_H */
diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
index d0eb0affb..271ce86b6 100644
--- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c
+++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
@@ -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)) {
diff --git a/xorg-server/hw/xfree86/common/xf86Bus.c b/xorg-server/hw/xfree86/common/xf86Bus.c
index 6c86f5e26..6de8409fc 100644
--- a/xorg-server/hw/xfree86/common/xf86Bus.c
+++ b/xorg-server/hw/xfree86/common/xf86Bus.c
@@ -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);
@@ -183,6 +189,10 @@ xf86BusConfig(void)
}
}
+ /* bind GPU conf screen to protocol screen 0 */
+ for (i = 0; i < xf86NumGPUScreens; i++)
+ xf86GPUScreens[i]->confScreen = xf86Screens[0]->confScreen;
+
/* If no screens left, return now. */
if (xf86NumScreens == 0) {
xf86Msg(X_ERROR,
@@ -202,6 +212,9 @@ xf86BusConfig(void)
void
xf86BusProbe(void)
{
+#ifdef XSERVER_PLATFORM_BUS
+ xf86platformProbe();
+#endif
#ifdef XSERVER_LIBPCIACCESS
xf86PciProbe();
#endif
@@ -238,6 +251,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 +285,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 +558,9 @@ xf86PostProbe(void)
#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
sbusSlotClaimed ||
#endif
+#ifdef XSERVER_PLATFORM_BUS
+ platformSlotClaimed ||
+#endif
#ifdef XSERVER_LIBPCIACCESS
pciSlotClaimed
#else
diff --git a/xorg-server/hw/xfree86/common/xf86Bus.h b/xorg-server/hw/xfree86/common/xf86Bus.h
index abf2efd1a..e83ba780a 100644
--- a/xorg-server/hw/xfree86/common/xf86Bus.h
+++ b/xorg-server/hw/xfree86/common/xf86Bus.h
@@ -42,6 +42,7 @@
#if defined(__sparc__) || defined(__sparc)
#include "xf86sbusBus.h"
#endif
+#include "xf86platformBus.h"
typedef struct {
DriverPtr driver;
diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c
index 3ec40fe9b..6b806a372 100644
--- a/xorg-server/hw/xfree86/common/xf86Config.c
+++ b/xorg-server/hw/xfree86/common/xf86Config.c
@@ -712,7 +712,8 @@ typedef enum {
FLAG_AUTO_ENABLE_DEVICES,
FLAG_GLX_VISUALS,
FLAG_DRI2,
- FLAG_USE_SIGIO
+ FLAG_USE_SIGIO,
+ FLAG_AUTO_ADD_GPU,
} FlagValues;
/**
@@ -770,6 +771,8 @@ static OptionInfoRec FlagOptions[] = {
{0}, FALSE},
{FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN,
{0}, FALSE},
+ {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
+ {0}, FALSE},
{-1, NULL, OPTV_NONE,
{0}, FALSE},
};
@@ -862,6 +865,16 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
xf86Msg(from, "%sutomatically enabling devices\n",
xf86Info.autoEnableDevices ? "A" : "Not a");
+ if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_GPU)) {
+ xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_GPU,
+ &xf86Info.autoAddGPU);
+ from = X_CONFIG;
+ }
+ else {
+ from = X_DEFAULT;
+ }
+ xf86Msg(from, "%sutomatically adding GPU devices\n",
+ xf86Info.autoAddGPU ? "A" : "Not a");
/*
* Set things up based on the config file information. Some of these
* settings may be overridden later when the command line options are
diff --git a/xorg-server/hw/xfree86/common/xf86Globals.c b/xorg-server/hw/xfree86/common/xf86Globals.c
index 0071004eb..7df7a80c4 100644
--- a/xorg-server/hw/xfree86/common/xf86Globals.c
+++ b/xorg-server/hw/xfree86/common/xf86Globals.c
@@ -51,6 +51,7 @@ DevPrivateKeyRec xf86CreateRootWindowKeyRec;
DevPrivateKeyRec xf86ScreenKeyRec;
ScrnInfoPtr *xf86Screens = NULL; /* List of ScrnInfos */
+ScrnInfoPtr *xf86GPUScreens = NULL; /* List of ScrnInfos */
const unsigned char byte_reversed[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
@@ -125,11 +126,16 @@ xf86InfoRec xf86Info = {
#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
.forceInputDevices = FALSE,
.autoAddDevices = TRUE,
- .autoEnableDevices = TRUE
+ .autoEnableDevices = TRUE,
#else
.forceInputDevices = TRUE,
.autoAddDevices = FALSE,
- .autoEnableDevices = FALSE
+ .autoEnableDevices = FALSE,
+#endif
+#if defined(CONFIG_UDEV_KMS)
+ .autoAddGPU = TRUE,
+#else
+ .autoAddGPU = FALSE,
#endif
};
@@ -153,6 +159,7 @@ int xf86NumDrivers = 0;
InputDriverPtr *xf86InputDriverList = NULL;
int xf86NumInputDrivers = 0;
int xf86NumScreens = 0;
+int xf86NumGPUScreens = 0;
const char *xf86VisualNames[] = {
"StaticGray",
diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c
index 5ef1dabfb..f681a8577 100644
--- a/xorg-server/hw/xfree86/common/xf86Helper.c
+++ b/xorg-server/hw/xfree86/common/xf86Helper.c
@@ -167,29 +167,43 @@ ScrnInfoPtr
xf86AllocateScreen(DriverPtr drv, int flags)
{
int i;
+ ScrnInfoPtr pScrn;
- if (xf86Screens == NULL)
- xf86NumScreens = 0;
-
- i = xf86NumScreens++;
- xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
- xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
- xf86Screens[i]->scrnIndex = i; /* Changes when a screen is removed */
- xf86Screens[i]->origIndex = i; /* This never changes */
- xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion),
- xf86ScrnInfoPrivateCount);
+ if (flags & XF86_ALLOCATE_GPU_SCREEN) {
+ if (xf86GPUScreens == NULL)
+ xf86NumGPUScreens = 0;
+ i = xf86NumGPUScreens++;
+ xf86GPUScreens = xnfrealloc(xf86GPUScreens, xf86NumGPUScreens * sizeof(ScrnInfoPtr));
+ xf86GPUScreens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
+ pScrn = xf86GPUScreens[i];
+ pScrn->scrnIndex = i + GPU_SCREEN_OFFSET; /* Changes when a screen is removed */
+ pScrn->is_gpu = TRUE;
+ } else {
+ if (xf86Screens == NULL)
+ xf86NumScreens = 0;
+
+ i = xf86NumScreens++;
+ xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
+ xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
+ pScrn = xf86Screens[i];
+
+ pScrn->scrnIndex = i; /* Changes when a screen is removed */
+ }
+
+ pScrn->origIndex = pScrn->scrnIndex; /* This never changes */
+ pScrn->privates = xnfcalloc(sizeof(DevUnion), xf86ScrnInfoPrivateCount);
/*
* EnableDisableFBAccess now gets initialized in InitOutput()
- * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess;
+ * pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
*/
- xf86Screens[i]->drv = drv;
+ pScrn->drv = drv;
drv->refCount++;
- xf86Screens[i]->module = DuplicateModule(drv->module, NULL);
+ pScrn->module = DuplicateModule(drv->module, NULL);
- xf86Screens[i]->DriverFunc = drv->driverFunc;
+ pScrn->DriverFunc = drv->driverFunc;
- return xf86Screens[i];
+ return pScrn;
}
/*
@@ -202,10 +216,17 @@ xf86DeleteScreen(ScrnInfoPtr pScrn)
{
int i;
int scrnIndex;
-
- /* First check if the screen is valid */
- if (xf86NumScreens == 0 || xf86Screens == NULL)
- return;
+ Bool is_gpu = FALSE;
+ if (pScrn->is_gpu) {
+ /* First check if the screen is valid */
+ if (xf86NumGPUScreens == 0 || xf86GPUScreens == NULL)
+ return;
+ is_gpu = TRUE;
+ } else {
+ /* First check if the screen is valid */
+ if (xf86NumScreens == 0 || xf86Screens == NULL)
+ return;
+ }
if (!pScrn)
return;
@@ -237,12 +258,23 @@ xf86DeleteScreen(ScrnInfoPtr pScrn)
/* Move the other entries down, updating their scrnIndex fields */
- xf86NumScreens--;
+ if (is_gpu) {
+ xf86NumGPUScreens--;
+ scrnIndex -= GPU_SCREEN_OFFSET;
+ for (i = scrnIndex; i < xf86NumGPUScreens; i++) {
+ xf86GPUScreens[i] = xf86GPUScreens[i + 1];
+ xf86GPUScreens[i]->scrnIndex = i + GPU_SCREEN_OFFSET;
+ /* Also need to take care of the screen layout settings */
+ }
+ }
+ else {
+ xf86NumScreens--;
- for (i = scrnIndex; i < xf86NumScreens; i++) {
- xf86Screens[i] = xf86Screens[i + 1];
- xf86Screens[i]->scrnIndex = i;
- /* Also need to take care of the screen layout settings */
+ for (i = scrnIndex; i < xf86NumScreens; i++) {
+ xf86Screens[i] = xf86Screens[i + 1];
+ xf86Screens[i]->scrnIndex = i;
+ /* Also need to take care of the screen layout settings */
+ }
}
}
@@ -266,6 +298,14 @@ xf86AllocateScrnInfoPrivateIndex(void)
memset(&nprivs[idx], 0, sizeof(DevUnion));
pScr->privates = nprivs;
}
+ for (i = 0; i < xf86NumGPUScreens; i++) {
+ pScr = xf86GPUScreens[i];
+ nprivs = xnfrealloc(pScr->privates,
+ xf86ScrnInfoPrivateCount * sizeof(DevUnion));
+ /* Zero the new private */
+ memset(&nprivs[idx], 0, sizeof(DevUnion));
+ pScr->privates = nprivs;
+ }
return idx;
}
@@ -1058,6 +1098,11 @@ xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
xf86Screens[scrnIndex]->name)
LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
xf86Screens[scrnIndex]->name, scrnIndex);
+ else if (scrnIndex >= GPU_SCREEN_OFFSET &&
+ scrnIndex < GPU_SCREEN_OFFSET + xf86NumGPUScreens &&
+ xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name)
+ LogHdrMessageVerb(type, verb, format, args, "%s(G%d): ",
+ xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name, scrnIndex - GPU_SCREEN_OFFSET);
else
LogVMessageVerb(type, verb, format, args);
}
@@ -1833,13 +1878,23 @@ xf86MotionHistoryAllocate(InputInfoPtr pInfo)
ScrnInfoPtr
xf86ScreenToScrn(ScreenPtr pScreen)
{
- assert(pScreen->myNum < xf86NumScreens);
- return xf86Screens[pScreen->myNum];
+ if (pScreen->isGPU) {
+ assert(pScreen->myNum - GPU_SCREEN_OFFSET < xf86NumGPUScreens);
+ return xf86GPUScreens[pScreen->myNum - GPU_SCREEN_OFFSET];
+ } else {
+ assert(pScreen->myNum < xf86NumScreens);
+ return xf86Screens[pScreen->myNum];
+ }
}
ScreenPtr
xf86ScrnToScreen(ScrnInfoPtr pScrn)
{
- assert(pScrn->scrnIndex < screenInfo.numScreens);
- return screenInfo.screens[pScrn->scrnIndex];
+ if (pScrn->is_gpu) {
+ assert(pScrn->scrnIndex - GPU_SCREEN_OFFSET < screenInfo.numGPUScreens);
+ return screenInfo.gpuscreens[pScrn->scrnIndex - GPU_SCREEN_OFFSET];
+ } else {
+ assert(pScrn->scrnIndex < screenInfo.numScreens);
+ return screenInfo.screens[pScrn->scrnIndex];
+ }
}
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c
index 1f5a382b7..aa17a58fd 100644
--- a/xorg-server/hw/xfree86/common/xf86Init.c
+++ b/xorg-server/hw/xfree86/common/xf86Init.c
@@ -593,6 +593,18 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
if (!xf86Screens[i]->configured)
xf86DeleteScreen(xf86Screens[i--]);
+ for (i = 0; i < xf86NumGPUScreens; i++) {
+ xf86VGAarbiterScrnInit(xf86GPUScreens[i]);
+ xf86VGAarbiterLock(xf86GPUScreens[i]);
+ if (xf86GPUScreens[i]->PreInit &&
+ xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0))
+ xf86GPUScreens[i]->configured = TRUE;
+ xf86VGAarbiterUnlock(xf86GPUScreens[i]);
+ }
+ for (i = 0; i < xf86NumGPUScreens; i++)
+ if (!xf86GPUScreens[i]->configured)
+ xf86DeleteScreen(xf86GPUScreens[i--]);
+
/*
* If no screens left, return now.
*/
@@ -818,6 +830,36 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
!dixRegisterPrivateKey(&xf86CreateRootWindowKeyRec, PRIVATE_SCREEN, 0))
FatalError("Cannot register DDX private keys");
+ for (i = 0; i < xf86NumGPUScreens; i++) {
+ ScrnInfoPtr pScrn = xf86GPUScreens[i];
+ xf86VGAarbiterLock(pScrn);
+
+ /*
+ * Almost everything uses these defaults, and many of those that
+ * don't, will wrap them.
+ */
+ pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
+#ifdef XFreeXDGA
+ pScrn->SetDGAMode = xf86SetDGAMode;
+#endif
+ pScrn->DPMSSet = NULL;
+ pScrn->LoadPalette = NULL;
+ pScrn->SetOverscan = NULL;
+ pScrn->DriverFunc = NULL;
+ pScrn->pScreen = NULL;
+ scr_index = AddGPUScreen(pScrn->ScreenInit, argc, argv);
+ xf86VGAarbiterUnlock(pScrn);
+ if (scr_index == i) {
+ dixSetPrivate(&screenInfo.gpuscreens[scr_index]->devPrivates,
+ xf86ScreenKey, xf86GPUScreens[i]);
+ pScrn->pScreen = screenInfo.gpuscreens[scr_index];
+ /* The driver should set this, but make sure it is set anyway */
+ pScrn->vtSema = TRUE;
+ } else {
+ FatalError("AddScreen/ScreenInit failed for gpu driver %d %d\n", i, scr_index);
+ }
+ }
+
for (i = 0; i < xf86NumScreens; i++) {
xf86VGAarbiterLock(xf86Screens[i]);
/*
diff --git a/xorg-server/hw/xfree86/common/xf86Priv.h b/xorg-server/hw/xfree86/common/xf86Priv.h
index 42a3b30f0..c9f2e7eb8 100644
--- a/xorg-server/hw/xfree86/common/xf86Priv.h
+++ b/xorg-server/hw/xfree86/common/xf86Priv.h
@@ -95,6 +95,8 @@ extern _X_EXPORT Bool xorgHWAccess;
extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
+extern ScrnInfoPtr *xf86GPUScreens; /* List of pointers to ScrnInfoRecs */
+extern int xf86NumGPUScreens;
#ifndef DEFAULT_VERBOSE
#define DEFAULT_VERBOSE 0
#endif
diff --git a/xorg-server/hw/xfree86/common/xf86Privstr.h b/xorg-server/hw/xfree86/common/xf86Privstr.h
index e78cd407d..e20be03a9 100644
--- a/xorg-server/hw/xfree86/common/xf86Privstr.h
+++ b/xorg-server/hw/xfree86/common/xf86Privstr.h
@@ -110,6 +110,8 @@ typedef struct {
Bool dri2;
MessageType dri2From;
+
+ Bool autoAddGPU;
} xf86InfoRec, *xf86InfoPtr;
#ifdef DPMSExtension
diff --git a/xorg-server/hw/xfree86/common/xf86fbBus.c b/xorg-server/hw/xfree86/common/xf86fbBus.c
index 1e5162332..303b9c2f5 100644
--- a/xorg-server/hw/xfree86/common/xf86fbBus.c
+++ b/xorg-server/hw/xfree86/common/xf86fbBus.c
@@ -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;
diff --git a/xorg-server/hw/xfree86/common/xf86pciBus.c b/xorg-server/hw/xfree86/common/xf86pciBus.c
index d758260b6..a2c18ebf2 100644
--- a/xorg-server/hw/xfree86/common/xf86pciBus.c
+++ b/xorg-server/hw/xfree86/common/xf86pciBus.c
@@ -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;
diff --git a/xorg-server/hw/xfree86/common/xf86pciBus.h b/xorg-server/hw/xfree86/common/xf86pciBus.h
index 56ec6e9e7..4972c3688 100644
--- a/xorg-server/hw/xfree86/common/xf86pciBus.h
+++ b/xorg-server/hw/xfree86/common/xf86pciBus.h
@@ -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 */
diff --git a/xorg-server/hw/xfree86/common/xf86platformBus.c b/xorg-server/hw/xfree86/common/xf86platformBus.c
new file mode 100644
index 000000000..3bfb22e83
--- /dev/null
+++ b/xorg-server/hw/xfree86/common/xf86platformBus.c
@@ -0,0 +1,489 @@
+/*
+ * 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>
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef XSERVER_PLATFORM_BUS
+#include <errno.h>
+
+#include <pciaccess.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "os.h"
+#include "hotplug.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Priv.h"
+#include "xf86str.h"
+#include "xf86Bus.h"
+#include "Pci.h"
+#include "xf86platformBus.h"
+
+int platformSlotClaimed;
+
+int xf86_num_platform_devices;
+
+static struct xf86_platform_device *xf86_platform_devices;
+
+int
+xf86_add_platform_device(struct OdevAttributes *attribs)
+{
+ xf86_platform_devices = xnfrealloc(xf86_platform_devices,
+ (sizeof(struct xf86_platform_device)
+ * (xf86_num_platform_devices + 1)));
+
+ xf86_platform_devices[xf86_num_platform_devices].attribs = attribs;
+ xf86_platform_devices[xf86_num_platform_devices].pdev = NULL;
+
+ xf86_num_platform_devices++;
+ return 0;
+}
+
+int
+xf86_remove_platform_device(int dev_index)
+{
+ int j;
+
+ config_odev_free_attribute_list(xf86_platform_devices[dev_index].attribs);
+
+ for (j = dev_index; j < xf86_num_platform_devices - 1; j++)
+ memcpy(&xf86_platform_devices[j], &xf86_platform_devices[j + 1], sizeof(struct xf86_platform_device));
+ xf86_num_platform_devices--;
+ return 0;
+}
+
+Bool
+xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
+{
+ struct xf86_platform_device *device = &xf86_platform_devices[index];
+
+ return config_odev_add_attribute(device->attribs, attrib_id, attrib_name);
+}
+
+char *
+xf86_get_platform_attrib(int index, int attrib_id)
+{
+ struct xf86_platform_device *device = &xf86_platform_devices[index];
+ struct OdevAttribute *oa;
+
+ xorg_list_for_each_entry(oa, &device->attribs->list, member) {
+ if (oa->attrib_id == attrib_id)
+ return oa->attrib_name;
+ }
+ return NULL;
+}
+
+char *
+xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id)
+{
+ struct OdevAttribute *oa;
+
+ xorg_list_for_each_entry(oa, &device->attribs->list, member) {
+ if (oa->attrib_id == attrib_id)
+ return oa->attrib_name;
+ }
+ return NULL;
+}
+
+
+/*
+ * xf86IsPrimaryPlatform() -- return TRUE if primary device
+ * is a platform device and it matches this one.
+ */
+
+static Bool
+xf86IsPrimaryPlatform(struct xf86_platform_device *plat)
+{
+ return ((primaryBus.type == BUS_PLATFORM) && (plat == primaryBus.id.plat));
+}
+
+static void
+platform_find_pci_info(struct xf86_platform_device *pd, char *busid)
+{
+ struct pci_slot_match devmatch;
+ struct pci_device *info;
+ struct pci_device_iterator *iter;
+ int ret;
+
+ ret = sscanf(busid, "pci:%04x:%02x:%02x.%u",
+ &devmatch.domain, &devmatch.bus, &devmatch.dev,
+ &devmatch.func);
+ if (ret != 4)
+ return;
+
+ iter = pci_slot_match_iterator_create(&devmatch);
+ info = pci_device_next(iter);
+ if (info) {
+ pd->pdev = info;
+ pci_device_probe(info);
+ if (pci_device_is_boot_vga(info)) {
+ primaryBus.type = BUS_PLATFORM;
+ primaryBus.id.plat = pd;
+ }
+ }
+ pci_iterator_destroy(iter);
+
+}
+
+static Bool
+xf86_check_platform_slot(const struct xf86_platform_device *pd)
+{
+ int i;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ const EntityPtr u = xf86Entities[i];
+
+ if (pd->pdev && u->bus.type == BUS_PCI)
+ return !MATCH_PCI_DEVICES(pd->pdev, u->bus.id.pci);
+ if ((u->bus.type == BUS_PLATFORM) && (pd == u->bus.id.plat)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * @return The numbers of found devices that match with the current system
+ * drivers.
+ */
+int
+xf86PlatformMatchDriver(char *matches[], int nmatches)
+{
+ int i, j = 0;
+ struct pci_device *info = NULL;
+ int pass = 0;
+
+ for (pass = 0; pass < 2; pass++) {
+ for (i = 0; i < xf86_num_platform_devices; i++) {
+
+ if (xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 1))
+ continue;
+ else if (!xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 0))
+ continue;
+
+ info = xf86_platform_devices[i].pdev;
+#ifdef __linux__
+ if (info)
+ xf86MatchDriverFromFiles(matches, info->vendor_id, info->device_id);
+#endif
+
+ for (j = 0; (j < nmatches) && (matches[j]); j++) {
+ /* find end of matches list */
+ }
+
+ if ((info != NULL) && (j < nmatches)) {
+ j += xf86VideoPtrToDriverList(info, &(matches[j]), nmatches - j);
+ }
+ }
+ }
+ return j;
+}
+
+int
+xf86platformProbe(void)
+{
+ int i;
+ Bool pci = TRUE;
+
+ if (!xf86scanpci()) {
+ pci = FALSE;
+ }
+
+ config_odev_probe(&xf86PlatformDeviceProbe);
+ for (i = 0; i < xf86_num_platform_devices; i++) {
+ char *busid = xf86_get_platform_attrib(i, ODEV_ATTRIB_BUSID);
+
+ if (pci && (strncmp(busid, "pci:", 4) == 0)) {
+ platform_find_pci_info(&xf86_platform_devices[i], busid);
+ }
+ }
+ return 0;
+}
+
+static int
+xf86ClaimPlatformSlot(struct xf86_platform_device * d, DriverPtr drvp,
+ int chipset, GDevPtr dev, Bool active)
+{
+ EntityPtr p = NULL;
+ int num;
+
+ if (xf86_check_platform_slot(d)) {
+ num = xf86AllocateEntity();
+ p = xf86Entities[num];
+ p->driver = drvp;
+ p->chipset = chipset;
+ p->bus.type = BUS_PLATFORM;
+ p->bus.id.plat = d;
+ p->active = active;
+ p->inUse = FALSE;
+ if (dev)
+ xf86AddDevToEntity(num, dev);
+
+ platformSlotClaimed++;
+ return num;
+ }
+ else
+ return -1;
+}
+
+static int
+xf86UnclaimPlatformSlot(struct xf86_platform_device *d, GDevPtr dev)
+{
+ int i;
+
+ for (i = 0; i < xf86NumEntities; i++) {
+ const EntityPtr p = xf86Entities[i];
+
+ if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat == d)) {
+ if (dev)
+ xf86RemoveDevFromEntity(i, dev);
+ platformSlotClaimed--;
+ p->bus.type = BUS_NONE;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
+#define END_OF_MATCHES(m) \
+ (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
+
+static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
+ GDevPtr gdev, int flags, intptr_t match_data)
+{
+ Bool foundScreen = FALSE;
+ int entity;
+
+ if (gdev->screen == 0 && !xf86_check_platform_slot(dev))
+ return FALSE;
+
+ entity = xf86ClaimPlatformSlot(dev, drvp, 0,
+ gdev, gdev->active);
+
+ if ((entity == -1) && (gdev->screen > 0)) {
+ unsigned nent;
+
+ for (nent = 0; nent < xf86NumEntities; nent++) {
+ EntityPtr pEnt = xf86Entities[nent];
+
+ if (pEnt->bus.type != BUS_PLATFORM)
+ continue;
+ if (pEnt->bus.id.plat == dev) {
+ entity = nent;
+ xf86AddDevToEntity(nent, gdev);
+ break;
+ }
+ }
+ }
+ if (entity != -1) {
+ if (drvp->platformProbe(drvp, entity, flags, dev, match_data))
+ foundScreen = TRUE;
+ else
+ xf86UnclaimPlatformSlot(dev, gdev);
+ }
+ return foundScreen;
+}
+
+static Bool
+probeSingleDevice(struct xf86_platform_device *dev, DriverPtr drvp, GDevPtr gdev, int flags)
+{
+ int k;
+ Bool foundScreen = FALSE;
+ struct pci_device *pPci;
+ const struct pci_id_match *const devices = drvp->supported_devices;
+
+ if (dev->pdev && devices) {
+ int device_id = dev->pdev->device_id;
+ pPci = dev->pdev;
+ for (k = 0; !END_OF_MATCHES(devices[k]); k++) {
+ if (PCI_ID_COMPARE(devices[k].vendor_id, pPci->vendor_id)
+ && PCI_ID_COMPARE(devices[k].device_id, device_id)
+ && ((devices[k].device_class_mask & pPci->device_class)
+ == devices[k].device_class)) {
+ foundScreen = doPlatformProbe(dev, drvp, gdev, flags, devices[k].match_data);
+ if (foundScreen)
+ break;
+ }
+ }
+ }
+ else if (dev->pdev && !devices)
+ return FALSE;
+ else
+ foundScreen = doPlatformProbe(dev, drvp, gdev, flags, 0);
+ return foundScreen;
+}
+
+int
+xf86platformProbeDev(DriverPtr drvp)
+{
+ Bool foundScreen = FALSE;
+ GDevPtr *devList;
+ const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList);
+ int i, j;
+
+ /* find the main device or any device specificed in xorg.conf */
+ for (i = 0; i < numDevs; i++) {
+ for (j = 0; j < xf86_num_platform_devices; j++) {
+ if (devList[i]->busID && *devList[i]->busID) {
+ if (xf86PlatformDeviceCheckBusID(&xf86_platform_devices[j], devList[i]->busID))
+ break;
+ }
+ else {
+ if (xf86_platform_devices[j].pdev) {
+ if (xf86IsPrimaryPlatform(&xf86_platform_devices[j]))
+ break;
+ }
+ }
+ }
+
+ if (j == xf86_num_platform_devices)
+ continue;
+
+ foundScreen = probeSingleDevice(&xf86_platform_devices[j], drvp, devList[i], 0);
+ if (!foundScreen)
+ continue;
+ }
+
+ /* if autoaddgpu devices is enabled then go find a few more and add them as GPU screens */
+ if (xf86Info.autoAddGPU && numDevs) {
+ for (j = 0; j < xf86_num_platform_devices; j++) {
+ probeSingleDevice(&xf86_platform_devices[j], drvp, devList[0], PLATFORM_PROBE_GPU_SCREEN);
+ }
+ }
+
+ return foundScreen;
+}
+
+int
+xf86platformAddDevice(int index)
+{
+ int i, old_screens, scr_index;
+ DriverPtr drvp = NULL;
+ int entity;
+ screenLayoutPtr layout;
+ static char *hotplug_driver_name = "modesetting";
+
+ /* force load the driver for now */
+ xf86LoadOneModule(hotplug_driver_name, NULL);
+
+ for (i = 0; i < xf86NumDrivers; i++) {
+ if (!xf86DriverList[i])
+ continue;
+
+ if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) {
+ drvp = xf86DriverList[i];
+ break;
+ }
+ }
+ if (i == xf86NumDrivers)
+ return -1;
+
+ old_screens = xf86NumGPUScreens;
+ entity = xf86ClaimPlatformSlot(&xf86_platform_devices[index],
+ drvp, 0, 0, 0);
+ if (!drvp->platformProbe(drvp, entity, PLATFORM_PROBE_GPU_SCREEN, &xf86_platform_devices[index], 0)) {
+ xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
+ }
+ if (old_screens == xf86NumGPUScreens)
+ return -1;
+ i = old_screens;
+
+ for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
+ layout++) {
+ xf86GPUScreens[i]->confScreen = layout->screen;
+ break;
+ }
+
+ if (xf86GPUScreens[i]->PreInit &&
+ xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0))
+ xf86GPUScreens[i]->configured = TRUE;
+
+ if (!xf86GPUScreens[i]->configured) {
+ ErrorF("hotplugged device %d didn't configure\n", i);
+ xf86DeleteScreen(xf86GPUScreens[i]);
+ return -1;
+ }
+
+ scr_index = AddGPUScreen(xf86GPUScreens[i]->ScreenInit, 0, NULL);
+
+ dixSetPrivate(&xf86GPUScreens[i]->pScreen->devPrivates,
+ xf86ScreenKey, xf86GPUScreens[i]);
+
+ CreateScratchPixmapsForScreen(xf86GPUScreens[i]->pScreen);
+
+ return 0;
+}
+
+void
+xf86platformRemoveDevice(int index)
+{
+ EntityPtr entity;
+ int ent_num, i, j;
+ Bool found;
+
+ for (ent_num = 0; ent_num < xf86NumEntities; ent_num++) {
+ entity = xf86Entities[ent_num];
+ if (entity->bus.type == BUS_PLATFORM &&
+ entity->bus.id.plat == &xf86_platform_devices[index])
+ break;
+ }
+ if (ent_num == xf86NumEntities)
+ goto out;
+
+ found = FALSE;
+ for (i = 0; i < xf86NumGPUScreens; i++) {
+ for (j = 0; j < xf86GPUScreens[i]->numEntities; j++)
+ if (xf86GPUScreens[i]->entityList[j] == ent_num) {
+ found = TRUE;
+ break;
+ }
+ if (found)
+ break;
+ }
+ if (!found) {
+ ErrorF("failed to find screen to remove\n");
+ goto out;
+ }
+
+ xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen);
+
+ RemoveGPUScreen(xf86GPUScreens[i]->pScreen);
+ xf86DeleteScreen(xf86GPUScreens[i]);
+
+ xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
+
+ xf86_remove_platform_device(index);
+
+ out:
+ return;
+}
+#endif
diff --git a/xorg-server/hw/xfree86/common/xf86platformBus.h b/xorg-server/hw/xfree86/common/xf86platformBus.h
new file mode 100644
index 000000000..49afc247b
--- /dev/null
+++ b/xorg-server/hw/xfree86/common/xf86platformBus.h
@@ -0,0 +1,64 @@
+/*
+ * 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 int
+xf86platformAddDevice(int index);
+extern void
+xf86platformRemoveDevice(int index);
+
+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
diff --git a/xorg-server/hw/xfree86/common/xf86str.h b/xorg-server/hw/xfree86/common/xf86str.h
index a1404c3aa..6bd6a6218 100644
--- a/xorg-server/hw/xfree86/common/xf86str.h
+++ b/xorg-server/hw/xfree86/common/xf86str.h
@@ -311,6 +311,7 @@ struct _SymTabRec;
struct _PciChipsets;
struct pci_device;
+struct xf86_platform_device;
typedef struct _DriverRec {
int driverVersion;
@@ -325,9 +326,16 @@ 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
+ */
+#define PLATFORM_PROBE_GPU_SCREEN 1
+
+/*
* AddDriver flags
*/
#define HaveDriverFuncs 1
@@ -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;
@@ -802,6 +813,7 @@ typedef struct _ScrnInfoRec {
*/
funcPointer reservedFuncs[NUM_RESERVED_FUNCS];
+ Bool is_gpu;
} ScrnInfoRec;
typedef struct {
diff --git a/xorg-server/hw/xfree86/modes/xf86EdidModes.c b/xorg-server/hw/xfree86/modes/xf86EdidModes.c
index 8aa82d114..258ada5b4 100644
--- a/xorg-server/hw/xfree86/modes/xf86EdidModes.c
+++ b/xorg-server/hw/xfree86/modes/xf86EdidModes.c
@@ -723,7 +723,13 @@ static const struct {
1920, 1200, 75, 0}, {
1920, 1200, 85, 0}, {
1920, 1440, 60, 0}, {
-1920, 1440, 75, 0},};
+ 1920, 1440, 75, 0},
+ /* fill up last byte */
+ {
+ 0,0,0,0}, {
+ 0,0,0,0}, {
+ 0,0,0,0}, {
+ 0,0,0,0}, };
static DisplayModePtr
DDCModesFromEstIII(unsigned char *est)
@@ -732,10 +738,11 @@ DDCModesFromEstIII(unsigned char *est)
int i, j, m;
for (i = 0; i < 6; i++) {
- for (j = 7; j > 0; j--) {
+ for (j = 7; j >= 0; j--) {
if (est[i] & (1 << j)) {
m = (i * 8) + (7 - j);
- modes = xf86ModesAdd(modes,
+ if (EstIIIModes[m].w)
+ modes = xf86ModesAdd(modes,
FindDMTMode(EstIIIModes[m].w,
EstIIIModes[m].h,
EstIIIModes[m].r,
diff --git a/xorg-server/hw/xfree86/os-support/linux/Makefile.am b/xorg-server/hw/xfree86/os-support/linux/Makefile.am
index 36748df2c..61175b386 100644
--- a/xorg-server/hw/xfree86/os-support/linux/Makefile.am
+++ b/xorg-server/hw/xfree86/os-support/linux/Makefile.am
@@ -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 \
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c b/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c
new file mode 100644
index 000000000..76f5583dd
--- /dev/null
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c
@@ -0,0 +1,179 @@
+#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"
+
+#include "hotplug.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);
+}
+
+void NewGPUDeviceRequest(struct OdevAttributes *attribs)
+{
+ int old_num = xf86_num_platform_devices;
+ int ret;
+ xf86PlatformDeviceProbe(attribs);
+
+ if (old_num == xf86_num_platform_devices)
+ return;
+
+ ret = xf86platformAddDevice(xf86_num_platform_devices-1);
+ if (ret == -1)
+ xf86_remove_platform_device(xf86_num_platform_devices-1);
+
+ ErrorF("xf86: found device %d\n", xf86_num_platform_devices);
+ return;
+}
+
+void DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
+{
+ struct OdevAttribute *attrib;
+ int index;
+ char *syspath = NULL;
+
+ xorg_list_for_each_entry(attrib, &attribs->list, member) {
+ if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
+ syspath = attrib->attrib_name;
+ break;
+ }
+ }
+
+ for (index = 0; index < xf86_num_platform_devices; index++) {
+ char *dspath;
+ dspath = xf86_get_platform_attrib(index, ODEV_ATTRIB_SYSPATH);
+ if (!strcmp(syspath, dspath))
+ break;
+ }
+
+ if (index == xf86_num_platform_devices)
+ goto out;
+
+ ErrorF("xf86: remove device %d %s\n", index, syspath);
+
+ xf86platformRemoveDevice(index);
+out:
+ config_odev_free_attribute_list(attribs);
+}
+
+#endif
diff --git a/xorg-server/hw/xfree86/os-support/shared/platform_noop.c b/xorg-server/hw/xfree86/os-support/shared/platform_noop.c
new file mode 100644
index 000000000..199ae5e8e
--- /dev/null
+++ b/xorg-server/hw/xfree86/os-support/shared/platform_noop.c
@@ -0,0 +1,23 @@
+
+#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
+xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
+{
+ return FALSE;
+}
+
+void xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
+{
+
+}
+#endif
diff --git a/xorg-server/hw/xfree86/os-support/xf86_OSproc.h b/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
index e171146dd..2f0172e15 100644
--- a/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
+++ b/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
@@ -221,6 +221,12 @@ extern _X_EXPORT void xf86InitVidMem(void);
#endif /* XF86_OS_PRIVS */
+#ifdef XSERVER_PLATFORM_BUS
+#include "hotplug.h"
+void
+xf86PlatformDeviceProbe(struct OdevAttributes *attribs);
+#endif
+
_XFUNCPROTOEND
#endif /* NO_OSLIB_PROTOTYPES */
#endif /* _XF86_OSPROC_H */
diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
index 15e2ada78..8b91e0574 100644
--- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
+++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
@@ -336,28 +336,19 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
if (!infoPtr->pScrn->vtSema)
ScreenPriv->SavedCursor = pCurs;
- if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
+ if (infoPtr->pScrn->vtSema &&
+ (ScreenPriv->ForceHWCursorCount ||
+ ((
#ifdef ARGB_CURSOR
- pCurs->
- bits->
- argb
- &&
- infoPtr->
- UseHWCursorARGB
- &&
- (*infoPtr->
- UseHWCursorARGB)
- (pScreen,
- pCurs))
- ||
- (pCurs->
- bits->
- argb
- == 0
- &&
+ pCurs->bits->argb &&
+ infoPtr->UseHWCursorARGB &&
+ (*infoPtr->UseHWCursorARGB)(pScreen, pCurs)) ||
+ (pCurs->bits->argb == 0 &&
#endif
- (pCurs->bits->height <= infoPtr->MaxHeight) && (pCurs->bits->width <= infoPtr->MaxWidth) && (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, pCurs)))))) {
-
+ (pCurs->bits->height <= infoPtr->MaxHeight) &&
+ (pCurs->bits->width <= infoPtr->MaxWidth) &&
+ (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, pCurs)))))) {
+
if (ScreenPriv->SWCursor) /* remove the SW cursor */
(*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
NullCursor, x, y);
diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in
index 3c9bbafeb..77681a953 100644
--- a/xorg-server/include/dix-config.h.in
+++ b/xorg-server/include/dix-config.h.in
@@ -390,6 +390,9 @@
/* Use libudev for input hotplug */
#undef CONFIG_UDEV
+/* Use libudev for kms enumeration */
+#undef CONFIG_UDEV_KMS
+
/* Use udev_monitor_filter_add_match_tag() */
#undef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG
diff --git a/xorg-server/include/hotplug.h b/xorg-server/include/hotplug.h
index f3eeea21d..96b078d48 100644
--- a/xorg-server/include/hotplug.h
+++ b/xorg-server/include/hotplug.h
@@ -26,8 +26,47 @@
#ifndef HOTPLUG_H
#define HOTPLUG_H
+#include "list.h"
+
extern _X_EXPORT void config_pre_init(void);
extern _X_EXPORT void config_init(void);
extern _X_EXPORT void config_fini(void);
+struct OdevAttribute {
+ struct xorg_list member;
+ int attrib_id;
+ char *attrib_name;
+};
+
+struct OdevAttributes {
+ struct xorg_list list;
+};
+
+struct OdevAttributes *
+config_odev_allocate_attribute_list(void);
+
+void
+config_odev_free_attribute_list(struct OdevAttributes *attribs);
+
+Bool
+config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
+ const char *attrib_name);
+
+void
+config_odev_free_attributes(struct OdevAttributes *attribs);
+
+/* path to kernel device node - Linux e.g. /dev/dri/card0 */
+#define ODEV_ATTRIB_PATH 1
+/* system device path - Linux e.g. /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 */
+#define ODEV_ATTRIB_SYSPATH 2
+/* DRI-style bus id */
+#define ODEV_ATTRIB_BUSID 3
+
+typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
+void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
+
+#ifdef CONFIG_UDEV_KMS
+void NewGPUDeviceRequest(struct OdevAttributes *attribs);
+void DeleteGPUDeviceRequest(struct OdevAttributes *attribs);
+#endif
#endif /* HOTPLUG_H */
diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h
index 04327ac98..07864d26e 100644
--- a/xorg-server/include/misc.h
+++ b/xorg-server/include/misc.h
@@ -93,10 +93,14 @@ static double __inline trunc(double d)
#ifndef MAXSCREENS
#define MAXSCREENS 16
#endif
+#ifndef MAXGPUSCREENS
+#define MAXGPUSCREENS 16
+#endif
#define MAXCLIENTS 1024
#define MAXEXTENSIONS 128
#define MAXFORMATS 8
#define MAXDEVICES 40 /* input devices */
+#define GPU_SCREEN_OFFSET 256
/* 128 event opcodes for core + extension events, excluding GE */
#define MAXEVENTS 128
diff --git a/xorg-server/include/screenint.h b/xorg-server/include/screenint.h
index 6b0cc70ee..8205f6363 100644
--- a/xorg-server/include/screenint.h
+++ b/xorg-server/include/screenint.h
@@ -62,6 +62,15 @@ extern _X_EXPORT int AddScreen(Bool (* /*pfnInit */ )(
int /*argc */ ,
char ** /*argv */ );
+
+extern _X_EXPORT int AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+ int /*argc */ ,
+ char ** /*argv */
+ ),
+ int argc, char **argv);
+
+extern _X_EXPORT void RemoveGPUScreen(ScreenPtr pScreen);
+
typedef struct _ColormapRec *ColormapPtr;
#endif /* SCREENINT_H */
diff --git a/xorg-server/include/scrnintstr.h b/xorg-server/include/scrnintstr.h
index 746ff92e3..6602534a3 100644
--- a/xorg-server/include/scrnintstr.h
+++ b/xorg-server/include/scrnintstr.h
@@ -481,6 +481,8 @@ typedef struct _Screen {
* malicious users to steal framebuffer's content if that would be the
* default */
Bool canDoBGNoneRoot;
+
+ Bool isGPU;
} ScreenRec;
static inline RegionPtr
@@ -498,6 +500,8 @@ typedef struct _ScreenInfo {
PixmapFormatRec formats[MAXFORMATS];
int numScreens;
ScreenPtr screens[MAXSCREENS];
+ int numGPUScreens;
+ ScreenPtr gpuscreens[MAXGPUSCREENS];
int x; /* origin */
int y; /* origin */
int width; /* total width of all screens together */
diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in
index 2cc416ae7..a71b25d72 100644
--- a/xorg-server/include/xorg-config.h.in
+++ b/xorg-server/include/xorg-config.h.in
@@ -136,4 +136,7 @@
/* Have getresuid */
#undef HAVE_GETRESUID
+/* Have X server platform bus support */
+#undef XSERVER_PLATFORM_BUS
+
#endif /* _XORG_CONFIG_H_ */
diff --git a/xorg-server/include/xorg-server.h.in b/xorg-server/include/xorg-server.h.in
index 8086f32ae..c0761f78a 100644
--- a/xorg-server/include/xorg-server.h.in
+++ b/xorg-server/include/xorg-server.h.in
@@ -205,6 +205,9 @@
/* X Access Control Extension */
#undef XACE
+/* Have X server platform bus support */
+#undef XSERVER_PLATFORM_BUS
+
#ifdef _LP64
#define _XSERVER64 1
#endif
diff --git a/xorg-server/render/glyph.c b/xorg-server/render/glyph.c
index acb573fe6..c121e64a2 100644
--- a/xorg-server/render/glyph.c
+++ b/xorg-server/render/glyph.c
@@ -687,6 +687,8 @@ miGlyphs(CARD8 op,
PicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen)
{
+ if (pScreen->isGPU)
+ return NULL;
return GlyphPicture(glyph)[pScreen->myNum];
}