xserver: Branch 'master' - 10 commits

Keith Packard keithp at kemper.freedesktop.org
Fri Jul 6 12:29:12 PDT 2012


 config/config-backends.h                     |    1 
 config/config.c                              |   56 +++
 config/udev.c                                |  111 ++++++
 configure.ac                                 |   20 -
 dix/dispatch.c                               |  113 +++++-
 dix/dixutils.c                               |    6 
 dix/main.c                                   |   15 
 dix/privates.c                               |    4 
 hw/xfree86/common/Makefile.am                |    8 
 hw/xfree86/common/xf86.h                     |    8 
 hw/xfree86/common/xf86AutoConfig.c           |    9 
 hw/xfree86/common/xf86Bus.c                  |   22 +
 hw/xfree86/common/xf86Bus.h                  |    1 
 hw/xfree86/common/xf86Config.c               |   15 
 hw/xfree86/common/xf86Globals.c              |   11 
 hw/xfree86/common/xf86Helper.c               |  111 ++++--
 hw/xfree86/common/xf86Init.c                 |   42 ++
 hw/xfree86/common/xf86Priv.h                 |    2 
 hw/xfree86/common/xf86Privstr.h              |    2 
 hw/xfree86/common/xf86fbBus.c                |    4 
 hw/xfree86/common/xf86pciBus.c               |   41 +-
 hw/xfree86/common/xf86pciBus.h               |   10 
 hw/xfree86/common/xf86platformBus.c          |  489 +++++++++++++++++++++++++++
 hw/xfree86/common/xf86platformBus.h          |   64 +++
 hw/xfree86/common/xf86str.h                  |   12 
 hw/xfree86/os-support/linux/Makefile.am      |    2 
 hw/xfree86/os-support/linux/lnx_platform.c   |  179 +++++++++
 hw/xfree86/os-support/shared/platform_noop.c |   23 +
 hw/xfree86/os-support/xf86_OSproc.h          |    6 
 hw/xfree86/ramdac/xf86Cursor.c               |   31 -
 include/dix-config.h.in                      |    3 
 include/hotplug.h                            |   39 ++
 include/misc.h                               |    4 
 include/screenint.h                          |    9 
 include/scrnintstr.h                         |    4 
 include/xorg-config.h.in                     |    3 
 include/xorg-server.h.in                     |    3 
 render/glyph.c                               |    2 
 38 files changed, 1398 insertions(+), 87 deletions(-)

New commits:
commit 4d24192bd24fb20d16d0054d77bffda883faeb79
Merge: 7c9d8cb... 74b786f...
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jul 6 12:17:17 2012 -0700

    Merge remote-tracking branch 'airlied/for-keithp-stage1'

commit 74b786f7cee5723468bba251a2155a65770b2ad4
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:45:03 2012 +0100

    xfree86: add autoAddGPU option (v2)
    
    This option is to stop the X server adding non-primary devices as
    gpu screens.
    
    v2: fix per Keith's suggestion.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 3ec40fe..6b806a3 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/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/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index bb08917..7df7a80 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -126,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
 };
 
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
index e78cd40..e20be03 100644
--- a/hw/xfree86/common/xf86Privstr.h
+++ b/hw/xfree86/common/xf86Privstr.h
@@ -110,6 +110,8 @@ typedef struct {
 
     Bool dri2;
     MessageType dri2From;
+
+    Bool autoAddGPU;
 } xf86InfoRec, *xf86InfoPtr;
 
 #ifdef DPMSExtension
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 0cc6c0a..3bfb22e 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -373,6 +373,13 @@ xf86platformProbeDev(DriverPtr drvp)
             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;
 }
 
commit ef6686480ad1de6582b9ef5d13e5d4ffb3b3918c
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:30:39 2012 +0100

    xfree86: add platform bus hotplug support (v3)
    
    This provides add/remove support for platform devices at xfree86 ddx level.
    
    v2: cleanup properly if no driver found.
    
    v3: load the modesetting driver before checking driver list.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 50b7636..0cc6c0a 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -376,4 +376,107 @@ xf86platformProbeDev(DriverPtr drvp)
     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/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 15a3022..49afc24 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -47,6 +47,11 @@ 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
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 9c63ee5..76f5583 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -15,6 +15,8 @@
 #include "xf86platformBus.h"
 #include "xf86Bus.h"
 
+#include "hotplug.h"
+
 static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path)
 {
@@ -127,4 +129,51 @@ 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
commit b27cf30995e05da11e827ec41060051673336a7b
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:29:56 2012 +0100

    xserver/config: add udev/drm hotplug callbacks. (v2)
    
    This adds callbacks into the ddx for udev gpu hotplug.
    
    v2: fix some strncmp returns.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/config/udev.c b/config/udev.c
index efa8d32..5297b90 100644
--- a/config/udev.c
+++ b/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"))
diff --git a/include/hotplug.h b/include/hotplug.h
index 5000762..96b078d 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -65,4 +65,8 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 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 */
commit 53b66c084fbf5bf47f8121632fabdc39b9fe8337
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:18:10 2012 +0100

    xfree86: add DDX gpu screen support. (v3)
    
    This just adds the structures and interfaces required for adding/deleteing
    gpu screens at the DDX level. The platform probe can pass a new flag
    to the driver, so they can call xf86AllocateScreen and pass back the new
    gpu screen flag.
    
    It also calls the gpu screens preinit and screeninit routines at
    startup.
    
    v2: fix delete screen use after free.
    
    v3: split out pScrn into separate patch
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index 88a219c..6116985 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -465,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/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index d0cfb2b..6de8409 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -189,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,
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 0071004..bb08917 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/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,
@@ -153,6 +154,7 @@ int xf86NumDrivers = 0;
 InputDriverPtr *xf86InputDriverList = NULL;
 int xf86NumInputDrivers = 0;
 int xf86NumScreens = 0;
+int xf86NumGPUScreens = 0;
 
 const char *xf86VisualNames[] = {
     "StaticGray",
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 18f30b7..f681a85 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -169,15 +169,28 @@ 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);
-    pScrn = xf86Screens[i];
-    pScrn->scrnIndex = i;      /* Changes when a screen is removed */
-    pScrn->origIndex = i;      /* This never changes */
+    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()
@@ -203,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;
@@ -238,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 */
+        }
     }
 }
 
@@ -267,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;
 }
 
@@ -1059,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);
 }
@@ -1834,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/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 1f5a382..aa17a58 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/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/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 42a3b30..c9f2e7e 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/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/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index e12dcc4..6bd6a62 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/hw/xfree86/common/xf86str.h
@@ -332,9 +332,9 @@ typedef struct _DriverRec {
 
 /*
  * platform probe flags
- * no flags are defined yet - but drivers should fail to load if a flag they
- * don't understand is passed.
  */
+#define PLATFORM_PROBE_GPU_SCREEN 1
+
 /*
  *  AddDriver flags
  */
@@ -813,6 +813,7 @@ typedef struct _ScrnInfoRec {
      */
     funcPointer reservedFuncs[NUM_RESERVED_FUNCS];
 
+    Bool is_gpu;
 } ScrnInfoRec;
 
 typedef struct {
commit 726d467b534a30d8cbaafb858339c638c9f83195
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jun 25 11:51:26 2012 +0100

    xf86: cleanup helper code to use a pointer. (v1.1)
    
    This is in preparation for gpu screens in here, just use
    a pScrn pointer to point at the new screen.
    
    suggested by Keith.
    v1.1: fix spacing as suggested by Aaron.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 5ef1dab..18f30b7 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -167,6 +167,7 @@ ScrnInfoPtr
 xf86AllocateScreen(DriverPtr drv, int flags)
 {
     int i;
+    ScrnInfoPtr pScrn;
 
     if (xf86Screens == NULL)
         xf86NumScreens = 0;
@@ -174,22 +175,22 @@ xf86AllocateScreen(DriverPtr drv, int flags)
     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);
+    pScrn = xf86Screens[i];
+    pScrn->scrnIndex = i;      /* Changes when a screen is removed */
+    pScrn->origIndex = i;      /* 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;
 }
 
 /*
commit 9d179818293b466ec6f1777f0b792e1fbbeb318c
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:09:38 2012 +0100

    dix: introduce gpu screens. (v5)
    
    This patch introduces gpu screens into screenInfo. It adds interfaces
    for adding and removing gpu screens, along with adding private fixup,
    block handler support, and scratch pixmap init.
    
    GPU screens have a myNum that is offset by GPU_SCREEN_OFFSET (256),
    this is used for logging etc.
    
    RemoveGPUScreen isn't used until "xfree86: add platform bus hotplug support".
    
    v2: no glyph pictures for GPU screens for now.
    v3: introduce MAXGPUSCREENS, fix return value check
    v4: fixup myNum when renumbering screens (ajax)
    v5: drop cursor privates for now.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 39d791d..fa39728 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3724,7 +3724,7 @@ with its screen number, a pointer to its ScreenRec, argc, and argv.
 
 */
 
-static int init_screen(ScreenPtr pScreen, int i)
+static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
 {
     int scanlinepad, format, depth, bitsPerPixel, j, k;
 
@@ -3734,6 +3734,10 @@ static int init_screen(ScreenPtr pScreen, int i)
         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;
@@ -3790,7 +3794,7 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
     if (!pScreen)
         return -1;
 
-    ret = init_screen(pScreen, i);
+    ret = init_screen(pScreen, i, FALSE);
     if (ret != 0) {
         free(pScreen);
         return ret;
@@ -3820,3 +3824,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/dix/dixutils.c b/dix/dixutils.c
index b249a81..3f24629 100644
--- a/dix/dixutils.c
+++ b/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/dix/main.c b/dix/main.c
index 9524189..42f517d 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -207,6 +207,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];
 
@@ -336,6 +342,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/dix/privates.c b/dix/privates.c
index b58085f..740ead7 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -222,6 +222,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/include/misc.h b/include/misc.h
index aa62f6a..6bea82f 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -83,10 +83,14 @@ OF THIS SOFTWARE.
 #ifndef MAXSCREENS
 #define MAXSCREENS	16
 #endif
+#ifndef MAXGPUSCREENS
+#define MAXGPUSCREENS	16
+#endif
 #define MAXCLIENTS	256
 #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/include/screenint.h b/include/screenint.h
index 6b0cc70..8205f63 100644
--- a/include/screenint.h
+++ b/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/include/scrnintstr.h b/include/scrnintstr.h
index 7af2bf5..bcac475 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -477,6 +477,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
@@ -494,6 +496,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/render/glyph.c b/render/glyph.c
index acb573f..c121e64 100644
--- a/render/glyph.c
+++ b/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];
 }
 
commit 3478af3374abffa0c226ee077fda1fcfc0751e74
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 5 17:01:21 2012 +0100

    screen: split out screen init code. (v2)
    
    This is a precursor for reusing this code to init gpu screens.
    
    v2: fixup int check as per Keith's review.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 7d2d3b7..39d791d 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3724,29 +3724,13 @@ 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)
 {
-
-    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;
@@ -3784,7 +3768,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);
+    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
commit cf66471353ac5899383b573a3cfca407e90d501e
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue May 8 14:26:47 2012 +0100

    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 at redhat.com>
    v5 was Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/config/config-backends.h b/config/config-backends.h
index 62abc0a..6423701 100644
--- a/config/config-backends.h
+++ b/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/config/config.c b/config/config.c
index 24e7ba7..d0889a3 100644
--- a/config/config.c
+++ b/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/config/udev.c b/config/udev.c
index 1995184..efa8d32 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -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
+
diff --git a/configure.ac b/configure.ac
index d5ddf6e..d1358a2 100644
--- a/configure.ac
+++ b/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/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
index 2792177..65d98e6 100644
--- a/hw/xfree86/common/Makefile.am
+++ b/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/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index 129660d..88a219c 100644
--- a/hw/xfree86/common/xf86.h
+++ b/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);
 
diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index d0eb0af..271ce86 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/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/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 6c86f5e..d0cfb2b 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/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);
@@ -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
diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h
index abf2efd..e83ba78 100644
--- a/hw/xfree86/common/xf86Bus.h
+++ b/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/hw/xfree86/common/xf86fbBus.c b/hw/xfree86/common/xf86fbBus.c
index 1e51623..303b9c2 100644
--- a/hw/xfree86/common/xf86fbBus.c
+++ b/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/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
index d758260..a2c18eb 100644
--- a/hw/xfree86/common/xf86pciBus.c
+++ b/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/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h
index 56ec6e9..4972c36 100644
--- a/hw/xfree86/common/xf86pciBus.h
+++ b/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/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
new file mode 100644
index 0000000..50b7636
--- /dev/null
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -0,0 +1,379 @@
+/*
+ * 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 at 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;
+    }
+
+    return foundScreen;
+}
+
+#endif
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
new file mode 100644
index 0000000..15a3022
--- /dev/null
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -0,0 +1,59 @@
+/*
+ * 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 at 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
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index a1404c3..e12dcc4 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/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
+ * no flags are defined yet - but drivers should fail to load if a flag they
+ * don't understand is passed.
+ */
+/*
  *  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;
 
diff --git a/hw/xfree86/os-support/linux/Makefile.am b/hw/xfree86/os-support/linux/Makefile.am
index 36748df..61175b3 100644
--- a/hw/xfree86/os-support/linux/Makefile.am
+++ b/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/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
new file mode 100644
index 0000000..9c63ee5
--- /dev/null
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -0,0 +1,130 @@
+#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
diff --git a/hw/xfree86/os-support/shared/platform_noop.c b/hw/xfree86/os-support/shared/platform_noop.c
new file mode 100644
index 0000000..199ae5e
--- /dev/null
+++ b/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/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h
index e171146..2f0172e 100644
--- a/hw/xfree86/os-support/xf86_OSproc.h
+++ b/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/include/dix-config.h.in b/include/dix-config.h.in
index 3c9bbaf..77681a9 100644
--- a/include/dix-config.h.in
+++ b/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/include/hotplug.h b/include/hotplug.h
index f3eeea2..5000762 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -26,8 +26,43 @@
 #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);
+
 #endif                          /* HOTPLUG_H */
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 2cc416a..a71b25d 100644
--- a/include/xorg-config.h.in
+++ b/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/include/xorg-server.h.in b/include/xorg-server.h.in
index 8086f32..c0761f7 100644
--- a/include/xorg-server.h.in
+++ b/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
commit 2c52d776a42a28bb3e1463edf0cfe0672d0c08a9
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 19 16:01:08 2012 +0100

    xf86: cursor code got mangled by indenting
    
    This fixes some really ugly code that got mangled by the indenting.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 15e2ada..8b91e05 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/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);


More information about the xorg-commit mailing list