xserver: Branch 'master' - 6 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Oct 27 15:32:10 PDT 2014


 hw/xfree86/dri2/dri2.c                           |   62 +
 hw/xfree86/dri2/pci_ids/i810_pci_ids.h           |    4 
 hw/xfree86/dri2/pci_ids/i915_pci_ids.h           |   15 
 hw/xfree86/dri2/pci_ids/i965_pci_ids.h           |  115 +++
 hw/xfree86/dri2/pci_ids/pci_id_driver_map.h      |   80 ++
 hw/xfree86/dri2/pci_ids/r200_pci_ids.h           |   24 
 hw/xfree86/dri2/pci_ids/r300_pci_ids.h           |  227 ++++++
 hw/xfree86/dri2/pci_ids/r600_pci_ids.h           |  327 ++++++++
 hw/xfree86/dri2/pci_ids/radeon_pci_ids.h         |   23 
 hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h       |  157 ++++
 hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h         |    1 
 hw/xfree86/drivers/modesetting/Makefile.am       |    6 
 hw/xfree86/drivers/modesetting/dri2.c            |  863 +++++++++++++++++++++++
 hw/xfree86/drivers/modesetting/driver.c          |   27 
 hw/xfree86/drivers/modesetting/driver.h          |   44 +
 hw/xfree86/drivers/modesetting/drmmode_display.c |   25 
 hw/xfree86/drivers/modesetting/drmmode_display.h |   31 
 hw/xfree86/drivers/modesetting/vblank.c          |  383 ++++++++++
 18 files changed, 2406 insertions(+), 8 deletions(-)

New commits:
commit 5adc20179e9818d51e1cd79bfc8a8271786c3949
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Oct 27 15:28:14 2014 -0700

    modesetting: Skip kernel work-around on error in crtc to kernel msc
    
    ms_crtc_msc_to_kernel_msc attempts to work around kernel
    inconsistencies in reporting msc values by comparing the expected
    value with the reported value. If the kernel fails to
    actually provide its current values, then just skip the work around
    steps as there's really nothing better we can do.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 35cadb2..5031ef8 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -228,17 +228,18 @@ ms_crtc_msc_to_kernel_msc(xf86CrtcPtr crtc, uint64_t expect)
     uint64_t ust;
     int64_t diff;
 
-    ms_get_crtc_ust_msc(crtc, &ust, &msc);
-    diff = expect - msc;
-
-    /* We're way off here, assume that the kernel has lost its mind
-     * and smack the vblank back to something sensible
-     */
-    if (diff < -MAX_VBLANK_OFFSET || MAX_VBLANK_OFFSET < diff) {
-        drmmode_crtc->vblank_offset += (int32_t) diff;
-        if (drmmode_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
-            drmmode_crtc->vblank_offset < MAX_VBLANK_OFFSET)
-            drmmode_crtc->vblank_offset = 0;
+    if (ms_get_crtc_ust_msc(crtc, &ust, &msc) == Success) {
+        diff = expect - msc;
+
+        /* We're way off here, assume that the kernel has lost its mind
+         * and smack the vblank back to something sensible
+         */
+        if (diff < -MAX_VBLANK_OFFSET || MAX_VBLANK_OFFSET < diff) {
+            drmmode_crtc->vblank_offset += (int32_t) diff;
+            if (drmmode_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
+                drmmode_crtc->vblank_offset < MAX_VBLANK_OFFSET)
+                drmmode_crtc->vblank_offset = 0;
+        }
     }
     return (uint32_t) (expect - drmmode_crtc->vblank_offset);
 }
commit 59b12c454d9c4b5a26c6ad87c53abc671b15ce37
Merge: 5574a0a cac4b06
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Oct 27 14:48:55 2014 -0700

    Merge remote-tracking branch 'anholt/modesetting-dri2-no-pageflip'

commit cac4b064f9f66435430f61568c6a516c54bf3c40
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 17:23:38 2013 -0800

    modesetting: Add support for DRI2 with glamor.
    
    This is derived from the intel driver DRI2 code, with swapchain and
    pageflipping dropped, functions renamed, and vblank event management
    shared code moved to a vblank.c for reuse by Present.
    
    This allows AIGLX to load, which means that you get appropriate
    visuals exposed in GL, along with many extensions under
    direct-rendering that require presence in GLX (which aren't supported
    in glxdriswrast.c).
    
    v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
        Drop triple-buffering, which was totally broken in practice (I'll
        try to fix this later).  Fix up some style nits.  Document the
        general flow of pageflipping and why, rename the DRI2 frame event
        type enums to reflect what they're for, and handle them in a
        single switch statement so you can understand the state machine
        more easily.
    v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
        (not that the normal 2D driver is stable with pageflipping for
        me), and I won't get it fixed before the merge window.  It now
        passes all of the OML_sync_control tests from Jamey and Theo
        (except for occasional warns in timing -fullscreen -divisor 2).
    v4: Fix doxygen at the top of vblank.c
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am
index e6834e2..5b08600 100644
--- a/hw/xfree86/drivers/modesetting/Makefile.am
+++ b/hw/xfree86/drivers/modesetting/Makefile.am
@@ -30,6 +30,7 @@ AM_CPPFLAGS = \
 	$(XORG_INCS) \
 	-I$(top_srcdir)/glamor \
 	-I$(srcdir)/../../ddc \
+	-I$(srcdir)/../../dri2 \
 	-I$(srcdir)/../../i2c \
 	-I$(srcdir)/../../modes \
 	-I$(srcdir)/../../parser \
@@ -42,10 +43,13 @@ modesetting_drv_la_LIBADD = $(UDEV_LIBS) $(DRM_LIBS)
 modesetting_drv_ladir = @moduledir@/drivers
 
 modesetting_drv_la_SOURCES = \
+	 dri2.c \
 	 driver.c \
 	 driver.h \
 	 drmmode_display.c \
-	 drmmode_display.h
+	 drmmode_display.h \
+	 vblank.c \
+	 $(NULL)
 
 drivermandir = $(DRIVER_MAN_DIR)
 driverman_PRE = modesetting.man
diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c
new file mode 100644
index 0000000..6c88060
--- /dev/null
+++ b/hw/xfree86/drivers/modesetting/dri2.c
@@ -0,0 +1,863 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ * Copyright © 2014 Broadcom
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ */
+
+/**
+ * @file dri2.c
+ *
+ * Implements generic support for DRI2 on KMS, using glamor pixmaps
+ * for color buffer management (no support for other aux buffers), and
+ * the DRM vblank ioctls.
+ *
+ * This doesn't implement pageflipping yet.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <time.h>
+#include "list.h"
+#include "xf86.h"
+#include "driver.h"
+#include "dri2.h"
+
+#ifdef GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include "glamor.h"
+
+enum ms_dri2_frame_event_type {
+    MS_DRI2_QUEUE_SWAP,
+    MS_DRI2_WAIT_MSC,
+};
+
+typedef struct ms_dri2_frame_event {
+    ScreenPtr screen;
+
+    DrawablePtr drawable;
+    ClientPtr client;
+    enum ms_dri2_frame_event_type type;
+    int frame;
+    xf86CrtcPtr crtc;
+
+    struct xorg_list drawable_resource, client_resource;
+
+    /* for swaps & flips only */
+    DRI2SwapEventPtr event_complete;
+    void *event_data;
+    DRI2BufferPtr front;
+    DRI2BufferPtr back;
+} ms_dri2_frame_event_rec, *ms_dri2_frame_event_ptr;
+
+typedef struct {
+    int refcnt;
+    PixmapPtr pixmap;
+} ms_dri2_buffer_private_rec, *ms_dri2_buffer_private_ptr;
+
+static DevPrivateKeyRec ms_dri2_client_key;
+static RESTYPE frame_event_client_type, frame_event_drawable_type;
+static int ms_dri2_server_generation;
+
+struct ms_dri2_resource {
+    XID id;
+    RESTYPE type;
+    struct xorg_list list;
+};
+
+static struct ms_dri2_resource *
+ms_get_resource(XID id, RESTYPE type)
+{
+    struct ms_dri2_resource *resource;
+    void *ptr;
+
+    ptr = NULL;
+    dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess);
+    if (ptr)
+        return ptr;
+
+    resource = malloc(sizeof(*resource));
+    if (resource == NULL)
+        return NULL;
+
+    if (!AddResource(id, type, resource)) {
+        free(resource);
+        return NULL;
+    }
+
+    resource->id = id;
+    resource->type = type;
+    xorg_list_init(&resource->list);
+    return resource;
+}
+
+static inline PixmapPtr
+get_drawable_pixmap(DrawablePtr drawable)
+{
+    ScreenPtr screen = drawable->pScreen;
+
+    if (drawable->type == DRAWABLE_PIXMAP)
+        return (PixmapPtr) drawable;
+    else
+        return screen->GetWindowPixmap((WindowPtr) drawable);
+}
+
+static PixmapPtr
+get_front_buffer(DrawablePtr drawable)
+{
+    PixmapPtr pixmap;
+
+    pixmap = get_drawable_pixmap(drawable);
+    pixmap->refcnt++;
+
+    return pixmap;
+}
+
+static DRI2Buffer2Ptr
+ms_dri2_create_buffer(DrawablePtr drawable, unsigned int attachment,
+                      unsigned int format)
+{
+    ScreenPtr screen = drawable->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    DRI2Buffer2Ptr buffer;
+    PixmapPtr pixmap;
+    uint32_t size;
+    uint16_t pitch;
+    ms_dri2_buffer_private_ptr private;
+
+    buffer = calloc(1, sizeof *buffer);
+    if (buffer == NULL)
+        return NULL;
+
+    private = calloc(1, sizeof(*private));
+    if (private == NULL) {
+        free(buffer);
+        return NULL;
+    }
+
+    pixmap = NULL;
+    if (attachment == DRI2BufferFrontLeft)
+        pixmap = get_front_buffer(drawable);
+
+    if (pixmap == NULL) {
+        int pixmap_width = drawable->width;
+        int pixmap_height = drawable->height;
+        int pixmap_cpp = (format != 0) ? format : drawable->depth;
+
+        /* Assume that non-color-buffers require special
+         * device-specific handling.  Mesa currently makes no requests
+         * for non-color aux buffers.
+         */
+        switch (attachment) {
+        case DRI2BufferAccum:
+        case DRI2BufferBackLeft:
+        case DRI2BufferBackRight:
+        case DRI2BufferFakeFrontLeft:
+        case DRI2BufferFakeFrontRight:
+        case DRI2BufferFrontLeft:
+        case DRI2BufferFrontRight:
+            break;
+
+        case DRI2BufferStencil:
+        case DRI2BufferDepth:
+        case DRI2BufferDepthStencil:
+        case DRI2BufferHiz:
+        default:
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "Request for DRI2 buffer attachment %d unsupported\n",
+                       attachment);
+            free(private);
+            free(buffer);
+            return NULL;
+        }
+
+        pixmap = screen->CreatePixmap(screen,
+                                      pixmap_width,
+                                      pixmap_height,
+                                      pixmap_cpp,
+                                      0);
+        if (pixmap == NULL) {
+            if (pixmap)
+                screen->DestroyPixmap(pixmap);
+            free(private);
+            free(buffer);
+            return NULL;
+        }
+    }
+
+    buffer->attachment = attachment;
+    buffer->cpp = pixmap->drawable.bitsPerPixel / 8;
+    buffer->format = format;
+    /* The buffer's flags field is unused by the client drivers in
+     * Mesa currently.
+     */
+    buffer->flags = 0;
+
+    buffer->name = glamor_name_from_pixmap(pixmap, &pitch, &size);
+    buffer->pitch = pitch;
+    if (buffer->name == -1) {
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                   "Failed to get DRI2 name for pixmap\n");
+        screen->DestroyPixmap(pixmap);
+        free(private);
+        free(buffer);
+        return NULL;
+    }
+
+    buffer->driverPrivate = private;
+    private->refcnt = 1;
+    private->pixmap = pixmap;
+
+    return buffer;
+}
+
+static void
+ms_dri2_reference_buffer(DRI2Buffer2Ptr buffer)
+{
+    if (buffer) {
+        ms_dri2_buffer_private_ptr private = buffer->driverPrivate;
+        private->refcnt++;
+    }
+}
+
+static void ms_dri2_destroy_buffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
+{
+    if (!buffer)
+        return;
+
+    if (buffer->driverPrivate) {
+        ms_dri2_buffer_private_ptr private = buffer->driverPrivate;
+        if (--private->refcnt == 0) {
+            ScreenPtr screen = private->pixmap->drawable.pScreen;
+            screen->DestroyPixmap(private->pixmap);
+            free(private);
+            free(buffer);
+        }
+    } else {
+        free(buffer);
+    }
+}
+
+static void
+ms_dri2_copy_region(DrawablePtr drawable, RegionPtr pRegion,
+                    DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer)
+{
+    ms_dri2_buffer_private_ptr src_priv = sourceBuffer->driverPrivate;
+    ms_dri2_buffer_private_ptr dst_priv = destBuffer->driverPrivate;
+    PixmapPtr src_pixmap = src_priv->pixmap;
+    PixmapPtr dst_pixmap = dst_priv->pixmap;
+    ScreenPtr screen = drawable->pScreen;
+    DrawablePtr src = (sourceBuffer->attachment == DRI2BufferFrontLeft)
+        ? drawable : &src_pixmap->drawable;
+    DrawablePtr dst = (destBuffer->attachment == DRI2BufferFrontLeft)
+        ? drawable : &dst_pixmap->drawable;
+    RegionPtr pCopyClip;
+    GCPtr gc;
+
+    gc = GetScratchGC(dst->depth, screen);
+    if (!gc)
+        return;
+
+    pCopyClip = REGION_CREATE(screen, NULL, 0);
+    REGION_COPY(screen, pCopyClip, pRegion);
+    (*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0);
+    ValidateGC(dst, gc);
+
+    /* It's important that this copy gets submitted before the direct
+     * rendering client submits rendering for the next frame, but we
+     * don't actually need to submit right now.  The client will wait
+     * for the DRI2CopyRegion reply or the swap buffer event before
+     * rendering, and we'll hit the flush callback chain before those
+     * messages are sent.  We submit our batch buffers from the flush
+     * callback chain so we know that will happen before the client
+     * tries to render again.
+     */
+    gc->ops->CopyArea(src, dst, gc,
+                      0, 0,
+                      drawable->width, drawable->height,
+                      0, 0);
+
+    FreeScratchGC(gc);
+}
+
+static uint64_t
+gettime_us(void)
+{
+    struct timespec tv;
+
+    if (clock_gettime(CLOCK_MONOTONIC, &tv))
+        return 0;
+
+    return (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000;
+}
+
+/**
+ * Get current frame count and frame count timestamp, based on drawable's
+ * crtc.
+ */
+static int
+ms_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
+{
+    int ret;
+    xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw);
+
+    /* Drawable not displayed, make up a *monotonic* value */
+    if (crtc == NULL) {
+        *ust = gettime_us();
+        *msc = 0;
+        return TRUE;
+    }
+
+    ret = ms_get_crtc_ust_msc(crtc, ust, msc);
+
+    if (ret)
+        return FALSE;
+
+    return TRUE;
+}
+
+static XID
+get_client_id(ClientPtr client)
+{
+    XID *ptr = dixGetPrivateAddr(&client->devPrivates, &ms_dri2_client_key);
+    if (*ptr == 0)
+        *ptr = FakeClientID(client->index);
+    return *ptr;
+}
+
+/*
+ * Hook this frame event into the server resource
+ * database so we can clean it up if the drawable or
+ * client exits while the swap is pending
+ */
+static Bool
+ms_dri2_add_frame_event(ms_dri2_frame_event_ptr info)
+{
+    struct ms_dri2_resource *resource;
+
+    resource = ms_get_resource(get_client_id(info->client),
+                               frame_event_client_type);
+    if (resource == NULL)
+        return FALSE;
+
+    xorg_list_add(&info->client_resource, &resource->list);
+
+    resource = ms_get_resource(info->drawable->id, frame_event_drawable_type);
+    if (resource == NULL) {
+        xorg_list_del(&info->client_resource);
+        return FALSE;
+    }
+
+    xorg_list_add(&info->drawable_resource, &resource->list);
+
+    return TRUE;
+}
+
+static void
+ms_dri2_del_frame_event(ms_dri2_frame_event_rec *info)
+{
+    xorg_list_del(&info->client_resource);
+    xorg_list_del(&info->drawable_resource);
+
+    if (info->front)
+        ms_dri2_destroy_buffer(NULL, info->front);
+    if (info->back)
+        ms_dri2_destroy_buffer(NULL, info->back);
+
+    free(info);
+}
+
+static void
+ms_dri2_blit_swap(DrawablePtr drawable,
+                  DRI2BufferPtr dst,
+                  DRI2BufferPtr src)
+{
+    BoxRec box;
+    RegionRec region;
+
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = drawable->width;
+    box.y2 = drawable->height;
+    REGION_INIT(pScreen, &region, &box, 0);
+
+    ms_dri2_copy_region(drawable, &region, dst, src);
+}
+
+static void
+ms_dri2_frame_event_handler(uint64_t msc,
+                            uint64_t usec,
+                            void *data)
+{
+    ms_dri2_frame_event_ptr frame_info = data;
+    DrawablePtr drawable = frame_info->drawable;
+    ScreenPtr screen = frame_info->screen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    uint32_t tv_sec = usec / 1000000;
+    uint32_t tv_usec = usec % 1000000;
+
+    if (!drawable) {
+        ms_dri2_del_frame_event(frame_info);
+        return;
+    }
+
+    switch (frame_info->type) {
+    case MS_DRI2_QUEUE_SWAP:
+        ms_dri2_blit_swap(drawable, frame_info->front, frame_info->back);
+        DRI2SwapComplete(frame_info->client, drawable, msc, tv_sec, tv_usec,
+                         DRI2_BLIT_COMPLETE,
+                         frame_info->client ? frame_info->event_complete : NULL,
+                         frame_info->event_data);
+        break;
+
+    case MS_DRI2_WAIT_MSC:
+        if (frame_info->client)
+            DRI2WaitMSCComplete(frame_info->client, drawable,
+                                msc, tv_sec, tv_usec);
+        break;
+
+    default:
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "%s: unknown vblank event (type %d) received\n", __func__,
+                   frame_info->type);
+        break;
+    }
+
+    ms_dri2_del_frame_event(frame_info);
+}
+
+static void
+ms_dri2_frame_event_abort(void *data)
+{
+    ms_dri2_frame_event_ptr frame_info = data;
+
+    ms_dri2_del_frame_event(frame_info);
+}
+
+/**
+ * Request a DRM event when the requested conditions will be satisfied.
+ *
+ * We need to handle the event and ask the server to wake up the client when
+ * we receive it.
+ */
+static int
+ms_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
+                          CARD64 divisor, CARD64 remainder)
+{
+    ScreenPtr screen = draw->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    ms_dri2_frame_event_ptr wait_info;
+    drmVBlank vbl;
+    int ret;
+    xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw);
+    drmmode_crtc_private_ptr drmmode_crtc;
+    CARD64 current_msc, current_ust, request_msc;
+    uint32_t seq;
+
+    /* Drawable not visible, return immediately */
+    if (!crtc)
+        goto out_complete;
+    drmmode_crtc = crtc->driver_private;
+
+    wait_info = calloc(1, sizeof(*wait_info));
+    if (!wait_info)
+        goto out_complete;
+
+    wait_info->screen = screen;
+    wait_info->drawable = draw;
+    wait_info->client = client;
+    wait_info->type = MS_DRI2_WAIT_MSC;
+
+    if (!ms_dri2_add_frame_event(wait_info)) {
+        free(wait_info);
+        wait_info = NULL;
+        goto out_complete;
+    }
+
+    /* Get current count */
+    ret = ms_get_crtc_ust_msc(crtc, &current_ust, &current_msc);
+
+    /*
+     * If divisor is zero, or current_msc is smaller than target_msc,
+     * we just need to make sure target_msc passes  before waking up the
+     * client.
+     */
+    if (divisor == 0 || current_msc < target_msc) {
+        /* If target_msc already reached or passed, set it to
+         * current_msc to ensure we return a reasonable value back
+         * to the caller. This keeps the client from continually
+         * sending us MSC targets from the past by forcibly updating
+         * their count on this call.
+         */
+        seq = ms_drm_queue_alloc(crtc, wait_info,
+                                 ms_dri2_frame_event_handler,
+                                 ms_dri2_frame_event_abort);
+        if (!seq)
+            goto out_free;
+
+        if (current_msc >= target_msc)
+            target_msc = current_msc;
+        vbl.request.type = (DRM_VBLANK_ABSOLUTE |
+                            DRM_VBLANK_EVENT |
+                            drmmode_crtc->vblank_pipe);
+        vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, target_msc);
+        vbl.request.signal = (unsigned long)seq;
+
+        ret = drmWaitVBlank(ms->fd, &vbl);
+        if (ret) {
+            static int limit = 5;
+            if (limit) {
+                xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                           "%s:%d get vblank counter failed: %s\n",
+                           __FUNCTION__, __LINE__,
+                           strerror(errno));
+                limit--;
+            }
+            goto out_free;
+        }
+
+        wait_info->frame = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence);
+        DRI2BlockClient(client, draw);
+        return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * so we queue an event that will satisfy the divisor/remainder equation.
+     */
+    vbl.request.type =
+        DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
+
+    request_msc = current_msc - (current_msc % divisor) +
+        remainder;
+    /*
+     * If calculated remainder is larger than requested remainder,
+     * it means we've passed the last point where
+     * seq % divisor == remainder, so we need to wait for the next time
+     * that will happen.
+     */
+    if ((current_msc % divisor) >= remainder)
+        request_msc += divisor;
+
+    seq = ms_drm_queue_alloc(crtc, wait_info,
+                             ms_dri2_frame_event_handler,
+                             ms_dri2_frame_event_abort);
+    if (!seq)
+        goto out_free;
+
+    vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, request_msc);
+    vbl.request.signal = (unsigned long)seq;
+
+    ret = drmWaitVBlank(ms->fd, &vbl);
+    if (ret) {
+        static int limit = 5;
+        if (limit) {
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "%s:%d get vblank counter failed: %s\n",
+                       __FUNCTION__, __LINE__,
+                       strerror(errno));
+            limit--;
+        }
+        goto out_free;
+    }
+
+    wait_info->frame = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence);
+    DRI2BlockClient(client, draw);
+
+    return TRUE;
+
+ out_free:
+    ms_dri2_del_frame_event(wait_info);
+ out_complete:
+    DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+    return TRUE;
+}
+
+/**
+ * ScheduleSwap is responsible for requesting a DRM vblank event for
+ * the appropriate frame, or executing the swap immediately if it
+ * doesn't need to wait.
+ *
+ * When the swap is complete, the driver should call into the server so it
+ * can send any swap complete events that have been requested.
+ */
+static int
+ms_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
+                      DRI2BufferPtr front, DRI2BufferPtr back,
+                      CARD64 *target_msc, CARD64 divisor,
+                      CARD64 remainder, DRI2SwapEventPtr func, void *data)
+{
+    ScreenPtr screen = draw->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    drmVBlank vbl;
+    int ret;
+    xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw);
+    drmmode_crtc_private_ptr drmmode_crtc;
+    ms_dri2_frame_event_ptr frame_info = NULL;
+    uint64_t current_msc, current_ust;
+    uint64_t request_msc;
+    uint32_t seq;
+
+    /* Drawable not displayed... just complete the swap */
+    if (!crtc)
+        goto blit_fallback;
+    drmmode_crtc = crtc->driver_private;
+
+    frame_info = calloc(1, sizeof(*frame_info));
+    if (!frame_info)
+        goto blit_fallback;
+
+    frame_info->screen = screen;
+    frame_info->drawable = draw;
+    frame_info->client = client;
+    frame_info->event_complete = func;
+    frame_info->event_data = data;
+    frame_info->front = front;
+    frame_info->back = back;
+    frame_info->crtc = crtc;
+    frame_info->type = MS_DRI2_QUEUE_SWAP;
+
+    if (!ms_dri2_add_frame_event(frame_info)) {
+        free(frame_info);
+        frame_info = NULL;
+        goto blit_fallback;
+    }
+
+    ms_dri2_reference_buffer(front);
+    ms_dri2_reference_buffer(back);
+
+    ret = ms_get_crtc_ust_msc(crtc, &current_ust, &current_msc);
+
+    /*
+     * If divisor is zero, or current_msc is smaller than target_msc
+     * we just need to make sure target_msc passes before initiating
+     * the swap.
+     */
+    if (divisor == 0 || current_msc < *target_msc) {
+        /* We need to use DRM_VBLANK_NEXTONMISS to avoid unreliable
+         * timestamping later on.
+         */
+        vbl.request.type = (DRM_VBLANK_ABSOLUTE |
+                            DRM_VBLANK_NEXTONMISS |
+                            DRM_VBLANK_EVENT |
+                            drmmode_crtc->vblank_pipe);
+
+        /* If target_msc already reached or passed, set it to
+         * current_msc to ensure we return a reasonable value back
+         * to the caller. This makes swap_interval logic more robust.
+         */
+        if (current_msc >= *target_msc)
+            *target_msc = current_msc;
+
+        seq = ms_drm_queue_alloc(crtc, frame_info,
+                                 ms_dri2_frame_event_handler,
+                                 ms_dri2_frame_event_abort);
+        if (!seq)
+            goto blit_fallback;
+
+        vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, *target_msc);
+        vbl.request.signal = (unsigned long)seq;
+
+        ret = drmWaitVBlank(ms->fd, &vbl);
+        if (ret) {
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "divisor 0 get vblank counter failed: %s\n",
+                       strerror(errno));
+            goto blit_fallback;
+        }
+
+        *target_msc = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence);
+        frame_info->frame = *target_msc;
+
+        return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * and we need to queue an event that will satisfy the divisor/remainder
+     * equation.
+     */
+    vbl.request.type = (DRM_VBLANK_ABSOLUTE |
+                        DRM_VBLANK_NEXTONMISS |
+                        DRM_VBLANK_EVENT |
+                        drmmode_crtc->vblank_pipe);
+
+    request_msc = current_msc - (current_msc % divisor) +
+        remainder;
+
+    /*
+     * If the calculated deadline vbl.request.sequence is smaller than
+     * or equal to current_msc, it means we've passed the last point
+     * when effective onset frame seq could satisfy
+     * seq % divisor == remainder, so we need to wait for the next time
+     * this will happen.
+
+     * This comparison takes the DRM_VBLANK_NEXTONMISS delay into account.
+     */
+    if (request_msc <= current_msc)
+        request_msc += divisor;
+
+
+    seq = ms_drm_queue_alloc(crtc, frame_info,
+                             ms_dri2_frame_event_handler,
+                             ms_dri2_frame_event_abort);
+    if (!seq)
+        goto blit_fallback;
+
+    vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, request_msc);
+    vbl.request.signal = (unsigned long)seq;
+
+    ret = drmWaitVBlank(ms->fd, &vbl);
+    if (ret) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "final get vblank counter failed: %s\n",
+                   strerror(errno));
+        goto blit_fallback;
+    }
+
+    *target_msc = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence);
+    frame_info->frame = *target_msc;
+
+    return TRUE;
+
+ blit_fallback:
+    ms_dri2_blit_swap(draw, front, back);
+    DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+    if (frame_info)
+        ms_dri2_del_frame_event(frame_info);
+    *target_msc = 0; /* offscreen, so zero out target vblank count */
+    return TRUE;
+}
+
+static int
+ms_dri2_frame_event_client_gone(void *data, XID id)
+{
+    struct ms_dri2_resource *resource = data;
+
+    while (!xorg_list_is_empty(&resource->list)) {
+        ms_dri2_frame_event_ptr info =
+            xorg_list_first_entry(&resource->list,
+                                  ms_dri2_frame_event_rec,
+                                  client_resource);
+
+        xorg_list_del(&info->client_resource);
+        info->client = NULL;
+    }
+    free(resource);
+
+    return Success;
+}
+
+static int
+ms_dri2_frame_event_drawable_gone(void *data, XID id)
+{
+    struct ms_dri2_resource *resource = data;
+
+    while (!xorg_list_is_empty(&resource->list)) {
+        ms_dri2_frame_event_ptr info =
+            xorg_list_first_entry(&resource->list,
+                                  ms_dri2_frame_event_rec,
+                                  drawable_resource);
+
+        xorg_list_del(&info->drawable_resource);
+        info->drawable = NULL;
+    }
+    free(resource);
+
+    return Success;
+}
+
+static Bool
+ms_dri2_register_frame_event_resource_types(void)
+{
+    frame_event_client_type =
+        CreateNewResourceType(ms_dri2_frame_event_client_gone,
+                              "Frame Event Client");
+    if (!frame_event_client_type)
+        return FALSE;
+
+    frame_event_drawable_type =
+        CreateNewResourceType(ms_dri2_frame_event_drawable_gone,
+                              "Frame Event Drawable");
+    if (!frame_event_drawable_type)
+        return FALSE;
+
+    return TRUE;
+}
+
+Bool
+ms_dri2_screen_init(ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    DRI2InfoRec info;
+
+    if (!glamor_supports_pixmap_import_export(screen)) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "DRI2: glamor lacks support for pixmap import/export\n");
+    }
+
+    if (!xf86LoaderCheckSymbol("DRI2Version"))
+        return FALSE;
+
+    if (!dixRegisterPrivateKey(&ms_dri2_client_key,
+                               PRIVATE_CLIENT, sizeof(XID)))
+        return FALSE;
+
+    if (serverGeneration != ms_dri2_server_generation) {
+        ms_dri2_server_generation = serverGeneration;
+        if (!ms_dri2_register_frame_event_resource_types()) {
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "Cannot register DRI2 frame event resources\n");
+            return FALSE;
+        }
+    }
+
+    memset(&info, '\0', sizeof(info));
+    info.fd = ms->fd;
+    info.driverName = NULL; /* Compat field, unused. */
+    info.deviceName = drmGetDeviceNameFromFd(ms->fd);
+
+    info.version = 4;
+    info.CreateBuffer = ms_dri2_create_buffer;
+    info.DestroyBuffer = ms_dri2_destroy_buffer;
+    info.CopyRegion = ms_dri2_copy_region;
+    info.ScheduleSwap = ms_dri2_schedule_swap;
+    info.GetMSC = ms_dri2_get_msc;
+    info.ScheduleWaitMSC = ms_dri2_schedule_wait_msc;
+
+    /* These two will be filled in by dri2.c */
+    info.numDrivers = 0;
+    info.driverNames = NULL;
+
+    return DRI2ScreenInit(screen, &info);
+}
+
+void
+ms_dri2_close_screen(ScreenPtr screen)
+{
+    DRI2CloseScreen(screen);
+}
+
+#endif /* GLAMOR */
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index c62147a..e0391db 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -788,7 +788,9 @@ PreInit(ScrnInfoPtr pScrn, int flags)
 
     try_enable_glamor(pScrn);
 
-    if (!ms->glamor) {
+    if (ms->glamor) {
+        xf86LoadSubModule(pScrn, "dri2");
+    } else {
         Bool prefer_shadow = TRUE;
 
         ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value);
@@ -1107,6 +1109,21 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
     if (serverGeneration == 1)
         xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
+    if (!ms_vblank_screen_init(pScreen)) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "Failed to initialize vblank support.\n");
+        return FALSE;
+    }
+
+#ifdef GLAMOR
+    if (ms->glamor) {
+        if (!ms_dri2_screen_init(pScreen)) {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Failed to initialize the DRI2 extension.\n");
+        }
+    }
+#endif
+
     return EnterVT(pScrn);
 }
 
@@ -1172,6 +1189,14 @@ CloseScreen(ScreenPtr pScreen)
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     modesettingPtr ms = modesettingPTR(pScrn);
 
+#ifdef GLAMOR
+    if (ms->glamor) {
+        ms_dri2_close_screen(pScreen);
+    }
+#endif
+
+    ms_vblank_close_screen(pScreen);
+
     if (ms->damage) {
         DamageUnregister(ms->damage);
         DamageDestroy(ms->damage);
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 35f2419..9eda1c4 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <drm.h>
 #include <xf86drm.h>
+#include <xf86Crtc.h>
 #include <damage.h>
 
 #include "drmmode_display.h"
@@ -42,6 +43,26 @@ typedef struct {
     ScrnInfoPtr pScrn_2;
 } EntRec, *EntPtr;
 
+typedef void (*ms_drm_handler_proc)(uint64_t frame,
+                                    uint64_t usec,
+                                    void *data);
+
+typedef void (*ms_drm_abort_proc)(void *data);
+
+/**
+ * A tracked handler for an event that will hopefully be generated by
+ * the kernel, and what to do when it is encountered.
+ */
+struct ms_drm_queue {
+    struct xorg_list list;
+    xf86CrtcPtr crtc;
+    uint32_t seq;
+    void *data;
+    ScrnInfoPtr scrn;
+    ms_drm_handler_proc handler;
+    ms_drm_abort_proc abort;
+};
+
 typedef struct _modesettingRec {
     int fd;
 
@@ -70,6 +91,8 @@ typedef struct _modesettingRec {
 
     drmmode_rec drmmode;
 
+    drmEventContext event_context;
+
     DamagePtr damage;
     Bool dirty_enabled;
 
@@ -78,3 +101,24 @@ typedef struct _modesettingRec {
 } modesettingRec, *modesettingPtr;
 
 #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
+
+uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
+                            void *data,
+                            ms_drm_handler_proc handler,
+                            ms_drm_abort_proc abort);
+
+xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
+xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
+                             xf86CrtcPtr desired, BoxPtr crtc_box_ret);
+
+int ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
+
+uint32_t ms_crtc_msc_to_kernel_msc(xf86CrtcPtr crtc, uint64_t expect);
+uint64_t ms_kernel_msc_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence);
+
+
+Bool ms_dri2_screen_init(ScreenPtr screen);
+void ms_dri2_close_screen(ScreenPtr screen);
+
+Bool ms_vblank_screen_init(ScreenPtr screen);
+void ms_vblank_close_screen(ScreenPtr screen);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index d8d1b44..ef9009e 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -582,6 +582,17 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
     .shadow_create = drmmode_shadow_create,
 };
 
+static uint32_t
+drmmode_crtc_vblank_pipe(int crtc_id)
+{
+    if (crtc_id > 1)
+        return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
+    else if (crtc_id > 0)
+        return DRM_VBLANK_SECONDARY;
+    else
+        return 0;
+}
+
 static void
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 {
@@ -596,6 +607,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
     drmmode_crtc->mode_crtc =
         drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
     drmmode_crtc->drmmode = drmmode;
+    drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
     crtc->driver_private = drmmode_crtc;
 }
 
@@ -1183,6 +1195,11 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
     xf86DrvMsg(scrn->scrnIndex, X_INFO,
                "Allocate new frame buffer %dx%d stride\n", width, height);
 
+    if (drmmode->triple_buffer_pixmap) {
+        screen->DestroyPixmap(drmmode->triple_buffer_pixmap);
+        drmmode->triple_buffer_pixmap = NULL;
+    }
+
     old_width = scrn->virtualX;
     old_height = scrn->virtualY;
     old_pitch = drmmode->front_bo->pitch;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index c7e7ef0..987608c 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -43,6 +43,7 @@ struct dumb_bo {
 typedef struct {
     int fd;
     unsigned fb_id;
+    unsigned old_fb_id;
     drmModeResPtr mode_res;
     drmModeFBPtr mode_fb;
     int cpp;
@@ -58,17 +59,42 @@ typedef struct {
     Bool shadow_enable;
     void *shadow_fb;
 
+    /**
+     * A screen-sized pixmap when we're doing triple-buffered DRI2
+     * pageflipping.
+     *
+     * One is shared between all drawables that flip to the front
+     * buffer, and it only gets reallocated when root pixmap size
+     * changes.
+     */
+    PixmapPtr triple_buffer_pixmap;
+
+    /** The GEM name for triple_buffer_pixmap */
+    uint32_t triple_buffer_name;
+
     DevPrivateKeyRec pixmapPrivateKeyRec;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
-    int hw_id;
+    uint32_t vblank_pipe;
     struct dumb_bo *cursor_bo;
     unsigned rotate_fb_id;
     uint16_t lut_r[256], lut_g[256], lut_b[256];
     DamagePtr slave_damage;
+
+    /**
+     * @{ MSC (vblank count) handling for the PRESENT extension.
+     *
+     * The kernel's vblank counters are 32 bits and apparently full of
+     * lies, and we need to give a reliable 64-bit msc for GL, so we
+     * have to track and convert to a userland-tracked 64-bit msc.
+     */
+    int32_t vblank_offset;
+    uint32_t msc_prev;
+    uint64_t msc_high;
+    /** @} */
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
new file mode 100644
index 0000000..35cadb2
--- /dev/null
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/** @file vblank.c
+ *
+ * Support for tracking the DRM's vblank events.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <unistd.h>
+#include <xf86.h>
+#include <xf86Crtc.h>
+#include <poll.h>
+#include "driver.h"
+#include "drmmode_display.h"
+
+/**
+ * Tracking for outstanding events queued to the kernel.
+ *
+ * Each list entry is a struct ms_drm_queue, which has a uint32_t
+ * value generated from drm_seq that identifies the event and a
+ * reference back to the crtc/screen associated with the event.  It's
+ * done this way rather than in the screen because we want to be able
+ * to drain the list of event handlers that should be called at server
+ * regen time, even though we don't close the drm fd and have no way
+ * to actually drain the kernel events.
+ */
+static struct xorg_list ms_drm_queue;
+static uint32_t ms_drm_seq;
+
+struct ms_pageflip {
+    ScreenPtr screen;
+    Bool crtc_for_msc_ust;
+};
+
+static void ms_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
+{
+    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+    if (dest->x1 >= dest->x2) {
+        dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+        return;
+    }
+
+    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+    if (dest->y1 >= dest->y2)
+        dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
+
+static void ms_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
+    if (crtc->enabled) {
+        crtc_box->x1 = crtc->x;
+        crtc_box->x2 =
+            crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
+        crtc_box->y1 = crtc->y;
+        crtc_box->y2 =
+            crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
+    } else
+        crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int ms_box_area(BoxPtr box)
+{
+    return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+
+xf86CrtcPtr
+ms_covering_crtc(ScrnInfoPtr scrn,
+                 BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CrtcPtr crtc, best_crtc;
+    int coverage, best_coverage;
+    int c;
+    BoxRec crtc_box, cover_box;
+
+    best_crtc = NULL;
+    best_coverage = 0;
+    crtc_box_ret->x1 = 0;
+    crtc_box_ret->x2 = 0;
+    crtc_box_ret->y1 = 0;
+    crtc_box_ret->y2 = 0;
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+        crtc = xf86_config->crtc[c];
+
+        /* If the CRTC is off, treat it as not covering */
+        if (!crtc->enabled)
+            continue;
+
+        ms_crtc_box(crtc, &crtc_box);
+        ms_box_intersect(&cover_box, &crtc_box, box);
+        coverage = ms_box_area(&cover_box);
+        if (coverage && crtc == desired) {
+            *crtc_box_ret = crtc_box;
+            return crtc;
+        }
+        if (coverage > best_coverage) {
+            *crtc_box_ret = crtc_box;
+            best_crtc = crtc;
+            best_coverage = coverage;
+        }
+    }
+    return best_crtc;
+}
+
+xf86CrtcPtr
+ms_dri2_crtc_covering_drawable(DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    BoxRec box, crtcbox;
+    xf86CrtcPtr crtc;
+
+    box.x1 = pDraw->x;
+    box.y1 = pDraw->y;
+    box.x2 = box.x1 + pDraw->width;
+    box.y2 = box.y1 + pDraw->height;
+
+    crtc = ms_covering_crtc(pScrn, &box, NULL, &crtcbox);
+
+    /* Make sure the CRTC is valid and this is the real front buffer */
+    if (crtc != NULL && !crtc->rotatedData)
+        return crtc;
+
+    return NULL;
+}
+
+static Bool
+ms_get_kernel_ust_msc(xf86CrtcPtr crtc,
+                      uint32_t *msc, uint64_t *ust)
+{
+    ScreenPtr screen = crtc->randr_crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmVBlank vbl;
+    int ret;
+
+    /* Get current count */
+    vbl.request.type = DRM_VBLANK_RELATIVE | drmmode_crtc->vblank_pipe;
+    vbl.request.sequence = 0;
+    vbl.request.signal = 0;
+    ret = drmWaitVBlank(ms->fd, &vbl);
+    if (ret) {
+        *msc = 0;
+        *ust = 0;
+        return FALSE;
+    } else {
+        *msc = vbl.reply.sequence;
+        *ust = (CARD64) vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec;
+        return TRUE;
+    }
+}
+
+/**
+ * Convert a 32-bit kernel MSC sequence number to a 64-bit local sequence
+ * number, adding in the vblank_offset and high 32 bits, and dealing
+ * with 64-bit wrapping
+ */
+uint64_t
+ms_kernel_msc_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
+{
+    drmmode_crtc_private_rec *drmmode_crtc = crtc->driver_private;
+    sequence += drmmode_crtc->vblank_offset;
+
+    if ((int32_t) (sequence - drmmode_crtc->msc_prev) < -0x40000000)
+        drmmode_crtc->msc_high += 0x100000000L;
+    drmmode_crtc->msc_prev = sequence;
+    return drmmode_crtc->msc_high + sequence;
+}
+
+int
+ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+    uint32_t kernel_msc;
+
+    if (!ms_get_kernel_ust_msc(crtc, &kernel_msc, ust))
+        return BadMatch;
+    *msc = ms_kernel_msc_to_crtc_msc(crtc, kernel_msc);
+
+    return Success;
+}
+
+#define MAX_VBLANK_OFFSET       1000
+
+/**
+ * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number,
+ * removing the high 32 bits and subtracting out the vblank_offset term.
+ *
+ * This also updates the vblank_offset when it notices that the value should
+ * change.
+ */
+uint32_t
+ms_crtc_msc_to_kernel_msc(xf86CrtcPtr crtc, uint64_t expect)
+{
+    drmmode_crtc_private_rec *drmmode_crtc = crtc->driver_private;
+    uint64_t msc;
+    uint64_t ust;
+    int64_t diff;
+
+    ms_get_crtc_ust_msc(crtc, &ust, &msc);
+    diff = expect - msc;
+
+    /* We're way off here, assume that the kernel has lost its mind
+     * and smack the vblank back to something sensible
+     */
+    if (diff < -MAX_VBLANK_OFFSET || MAX_VBLANK_OFFSET < diff) {
+        drmmode_crtc->vblank_offset += (int32_t) diff;
+        if (drmmode_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
+            drmmode_crtc->vblank_offset < MAX_VBLANK_OFFSET)
+            drmmode_crtc->vblank_offset = 0;
+    }
+    return (uint32_t) (expect - drmmode_crtc->vblank_offset);
+}
+
+/**
+ * Check for pending DRM events and process them.
+ */
+static void
+ms_drm_wakeup_handler(void *data, int err, void *mask)
+{
+    ScreenPtr screen = data;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    fd_set *read_mask = mask;
+
+    if (data == NULL || err < 0)
+        return;
+
+    if (FD_ISSET(ms->fd, read_mask))
+        drmHandleEvent(ms->fd, &ms->event_context);
+}
+
+/*
+ * Enqueue a potential drm response; when the associated response
+ * appears, we've got data to pass to the handler from here
+ */
+uint32_t
+ms_drm_queue_alloc(xf86CrtcPtr crtc,
+                   void *data,
+                   ms_drm_handler_proc handler,
+                   ms_drm_abort_proc abort)
+{
+    ScreenPtr screen = crtc->randr_crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct ms_drm_queue *q;
+
+    q = calloc(1, sizeof(struct ms_drm_queue));
+
+    if (!q)
+        return 0;
+    if (!ms_drm_seq)
+        ++ms_drm_seq;
+    q->seq = ms_drm_seq++;
+    q->scrn = scrn;
+    q->crtc = crtc;
+    q->data = data;
+    q->handler = handler;
+    q->abort = abort;
+
+    xorg_list_add(&q->list, &ms_drm_queue);
+
+    return q->seq;
+}
+
+/**
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+ms_drm_abort_one(struct ms_drm_queue *q)
+{
+        xorg_list_del(&q->list);
+        q->abort(q->data);
+        free(q);
+}
+
+/**
+ * Abort all queued entries on a specific scrn, used
+ * when resetting the X server
+ */
+static void
+ms_drm_abort_scrn(ScrnInfoPtr scrn)
+{
+    struct ms_drm_queue *q, *tmp;
+
+    xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) {
+        if (q->scrn == scrn)
+            ms_drm_abort_one(q);
+    }
+}
+
+/*
+ * General DRM kernel handler. Looks for the matching sequence number in the
+ * drm event queue and calls the handler for it.
+ */
+static void
+ms_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec,
+               void *user_ptr)
+{
+    struct ms_drm_queue *q, *tmp;
+    uint32_t user_data = (uint32_t) (intptr_t) user_ptr;
+
+    xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) {
+        if (q->seq == user_data) {
+            uint64_t msc;
+
+            msc = ms_kernel_msc_to_crtc_msc(q->crtc, frame);
+            xorg_list_del(&q->list);
+            q->handler(msc, (uint64_t) sec * 1000000 + usec, q->data);
+            free(q);
+            break;
+        }
+    }
+}
+
+Bool
+ms_vblank_screen_init(ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    xorg_list_init(&ms_drm_queue);
+
+    ms->event_context.version = DRM_EVENT_CONTEXT_VERSION;
+    ms->event_context.vblank_handler = ms_drm_handler;
+    ms->event_context.page_flip_handler = ms_drm_handler;
+
+    /* We need to re-register the DRM fd for the synchronisation
+     * feedback on every server generation, so perform the
+     * registration within ScreenInit and not PreInit.
+     */
+    AddGeneralSocket(ms->fd);
+    RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+                                   ms_drm_wakeup_handler, screen);
+
+    return TRUE;
+}
+
+void
+ms_vblank_close_screen(ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    ms_drm_abort_scrn(scrn);
+
+    RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+                                 ms_drm_wakeup_handler, screen);
+    RemoveGeneralSocket(ms->fd);
+}
commit 7064b00d478646cb428e427df2d3f91d7022c582
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 00:25:37 2013 -0800

    modesetting: Export two functions I want to reuse from DRI2/Present.
    
    This renames dumb_get_bo_from_handle(), since it wasn't using a handle
    (GEM terminology) but a dmabuf fd.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index d959837..d8d1b44 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -116,7 +116,7 @@ dumb_bo_unmap(int fd, struct dumb_bo *bo)
 }
 #endif
 
-static int
+int
 dumb_bo_destroy(int fd, struct dumb_bo *bo)
 {
     struct drm_mode_destroy_dumb arg;
@@ -137,8 +137,8 @@ dumb_bo_destroy(int fd, struct dumb_bo *bo)
     return 0;
 }
 
-static struct dumb_bo *
-dumb_get_bo_from_handle(int fd, int handle, int pitch, int size)
+struct dumb_bo *
+dumb_get_bo_from_fd(int fd, int handle, int pitch, int size)
 {
     struct dumb_bo *bo;
     int ret;
@@ -164,7 +164,7 @@ drmmode_SetSlaveBO(PixmapPtr ppix,
     msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
 
     ppriv->backing_bo =
-        dumb_get_bo_from_handle(drmmode->fd, fd_handle, pitch, size);
+        dumb_get_bo_from_fd(drmmode->fd, fd_handle, pitch, size);
     if (!ppriv->backing_bo)
         return FALSE;
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 438743b..c7e7ef0 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -121,6 +121,9 @@ Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode,
                              int *depth, int *bpp);
+struct dumb_bo *dumb_get_bo_from_fd(int drm_fd, int fd, int pitch, int size);
+int dumb_bo_destroy(int fd, struct dumb_bo *bo);
+
 
 #ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
 #define DRM_CAP_DUMB_PREFERRED_DEPTH 3
commit 34a98c8103a6f725283d0d1ee4084bf387b93019
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Oct 8 04:12:49 2014 -0700

    dri2: Automatically fill in the driver name if the DDX doesn't provide it.
    
    This will be used by the modesetting driver to support DRI2 across all
    hardware that can support glamor, and could potentially be used by
    other drivers that have to support DRI2 on sets of hardware with
    multiple Mesa drivers.
    
    This logic is the same as what's present in the Mesa driver loader,
    except for the lack of nouveau_vieux support (which requires a
    predicate on the device).
    
    v2: Fix duplicated assignment of info->driverName.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 6459f11..c8fcd62 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -1410,6 +1410,59 @@ get_prime_id(void)
     return -1;
 }
 
+#include "pci_ids/pci_id_driver_map.h"
+
+static char *
+dri2_probe_driver_name(ScreenPtr pScreen, DRI2InfoPtr info)
+{
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+    struct pci_device *pdev = NULL;
+    int i, j;
+
+    if (pEnt)
+        pdev = xf86GetPciInfoForEntity(pEnt->index);
+
+    /* For non-PCI devices, just assume that the 3D driver is named
+     * the same as the kernel driver.  This is currently true for vc4
+     * and msm (freedreno).
+     */
+    if (!pdev) {
+        drmVersionPtr version = drmGetVersion(info->fd);
+        char *kernel_driver;
+
+        if (!version) {
+            xf86DrvMsg(pScreen->myNum, X_ERROR,
+                       "[DRI2] Couldn't drmGetVersion() on non-PCI device, "
+                       "no driver name found.\n");
+            return NULL;
+        }
+
+        kernel_driver = strndup(version->name, version->name_len);
+        drmFreeVersion(version);
+        return kernel_driver;
+    }
+
+    for (i = 0; driver_map[i].driver; i++) {
+        if (pdev->vendor_id != driver_map[i].vendor_id)
+            continue;
+
+        if (driver_map[i].num_chips_ids == -1)
+            return strdup(driver_map[i].driver);
+
+        for (j = 0; j < driver_map[i].num_chips_ids; j++) {
+            if (driver_map[i].chip_ids[j] == pdev->device_id)
+                return strdup(driver_map[i].driver);
+        }
+    }
+
+    xf86DrvMsg(pScreen->myNum, X_ERROR,
+               "[DRI2] No driver mapping found for PCI device "
+               "0x%04x / 0x%04x\n",
+               pdev->vendor_id, pdev->device_id);
+    return NULL;
+}
+
 Bool
 DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 {
@@ -1524,7 +1577,14 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         ds->driverNames = malloc(sizeof(*ds->driverNames));
         if (!ds->driverNames)
             goto err_out;
-        ds->driverNames[0] = info->driverName;
+
+        if (info->driverName) {
+            ds->driverNames[0] = info->driverName;
+        } else {
+            ds->driverNames[0] = dri2_probe_driver_name(pScreen, info);
+            if (!ds->driverNames[0])
+                return FALSE;
+        }
     }
     else {
         ds->numDrivers = info->numDrivers;
commit 470d97e1d176981dbd8087c621e54caab0d6c73c
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 31 13:52:49 2013 -0800

    dri2: Import a copy of Mesa's PCI ID -> driver name mappings.
    
    This comes from Mesa commit acdcef6788beaa2a1532e13ff84c3e246b8025ed
    
    Previously, each driver had to tell DRI2 what GL driver object should
    be loaded.  Originally for a 2D driver that was a matter of giving the
    constant string for the vendor name, same as the driver's name.  For a
    driver that's trying to handle multiple generations of hardware with
    different Mesa driver filenames, the driver had to bake in a mapping
    from PCI ID to the appropriate driver name in Mesa, which seems like a
    pretty awful layering violation (and one that was fixed with DRI3)
    
    As of January, Mesa now handles the mapping from a DRI fd to the
    driver name on its own, but the AIGLX loader still relies on DRI2 for
    choosing the filename.  Instead of propagating the PCI ID list from
    each 2D driver to the modesetting driver, import a central copy of the
    PCI ID list so that drivers can stop handling this themselves.  (Some
    day, when AIGLX transitions to EGL, we can drop the DRI2 filename
    setup entirely).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/dri2/pci_ids/i810_pci_ids.h b/hw/xfree86/dri2/pci_ids/i810_pci_ids.h
new file mode 100644
index 0000000..7f68192
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/i810_pci_ids.h
@@ -0,0 +1,4 @@
+CHIPSET(0x7121, I810, i8xx)
+CHIPSET(0x7123, I810_DC100, i8xx)
+CHIPSET(0x7125, I810_E, i8xx)
+CHIPSET(0x1132, I815, i8xx)
diff --git a/hw/xfree86/dri2/pci_ids/i915_pci_ids.h b/hw/xfree86/dri2/pci_ids/i915_pci_ids.h
new file mode 100644
index 0000000..7d51975
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/i915_pci_ids.h
@@ -0,0 +1,15 @@
+CHIPSET(0x3577, I830_M,   "Intel(R) 830M")
+CHIPSET(0x2562, 845_G,    "Intel(R) 845G")
+CHIPSET(0x3582, I855_GM,  "Intel(R) 852GM/855GM")
+CHIPSET(0x2572, I865_G,   "Intel(R) 865G")
+CHIPSET(0x2582, I915_G,   "Intel(R) 915G")
+CHIPSET(0x258A, E7221_G,  "Intel(R) E7221G (i915)")
+CHIPSET(0x2592, I915_GM,  "Intel(R) 915GM")
+CHIPSET(0x2772, I945_G,   "Intel(R) 945G")
+CHIPSET(0x27A2, I945_GM,  "Intel(R) 945GM")
+CHIPSET(0x27AE, I945_GME, "Intel(R) 945GME")
+CHIPSET(0x29B2, Q35_G,    "Intel(R) Q35")
+CHIPSET(0x29C2, G33_G,    "Intel(R) G33")
+CHIPSET(0x29D2, Q33_G,    "Intel(R) Q33")
+CHIPSET(0xA011, IGD_GM,   "Intel(R) IGD")
+CHIPSET(0xA001, IGD_G,    "Intel(R) IGD")
diff --git a/hw/xfree86/dri2/pci_ids/i965_pci_ids.h b/hw/xfree86/dri2/pci_ids/i965_pci_ids.h
new file mode 100644
index 0000000..2e04301
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/i965_pci_ids.h
@@ -0,0 +1,115 @@
+CHIPSET(0x29A2, i965,    "Intel(R) 965G")
+CHIPSET(0x2992, i965,    "Intel(R) 965Q")
+CHIPSET(0x2982, i965,    "Intel(R) 965G")
+CHIPSET(0x2972, i965,    "Intel(R) 946GZ")
+CHIPSET(0x2A02, i965,    "Intel(R) 965GM")
+CHIPSET(0x2A12, i965,    "Intel(R) 965GME/GLE")
+CHIPSET(0x2A42, g4x,     "Mobile Intel® GM45 Express Chipset")
+CHIPSET(0x2E02, g4x,     "Intel(R) Integrated Graphics Device")
+CHIPSET(0x2E12, g4x,     "Intel(R) Q45/Q43")
+CHIPSET(0x2E22, g4x,     "Intel(R) G45/G43")
+CHIPSET(0x2E32, g4x,     "Intel(R) G41")
+CHIPSET(0x2E42, g4x,     "Intel(R) B43")
+CHIPSET(0x2E92, g4x,     "Intel(R) B43")
+CHIPSET(0x0042, ilk,     "Intel(R) Ironlake Desktop")
+CHIPSET(0x0046, ilk,     "Intel(R) Ironlake Mobile")
+CHIPSET(0x0102, snb_gt1, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0112, snb_gt2, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0122, snb_gt2, "Intel(R) Sandybridge Desktop")
+CHIPSET(0x0106, snb_gt1, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x0116, snb_gt2, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x0126, snb_gt2, "Intel(R) Sandybridge Mobile")
+CHIPSET(0x010A, snb_gt1, "Intel(R) Sandybridge Server")
+CHIPSET(0x0152, ivb_gt1, "Intel(R) Ivybridge Desktop")
+CHIPSET(0x0162, ivb_gt2, "Intel(R) Ivybridge Desktop")
+CHIPSET(0x0156, ivb_gt1, "Intel(R) Ivybridge Mobile")
+CHIPSET(0x0166, ivb_gt2, "Intel(R) Ivybridge Mobile")
+CHIPSET(0x015a, ivb_gt1, "Intel(R) Ivybridge Server")
+CHIPSET(0x016a, ivb_gt2, "Intel(R) Ivybridge Server")
+CHIPSET(0x0402, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0412, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0422, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0406, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0416, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0426, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x040A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x041A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x042A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x040B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x041B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x042B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x040E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x041E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x042E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0C02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0C06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0C0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0C1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0C2A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x0C0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0C1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0C2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0C0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0C1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0C2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0A02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0A06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0A0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0A1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0A2A, hsw_gt3, "Intel(R) Haswell Server")
+CHIPSET(0x0A0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0A1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0A2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0A0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0A1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0A2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D02, hsw_gt1, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D12, hsw_gt2, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D22, hsw_gt3, "Intel(R) Haswell Desktop")
+CHIPSET(0x0D06, hsw_gt1, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D16, hsw_gt2, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D26, hsw_gt3, "Intel(R) Haswell Mobile")
+CHIPSET(0x0D0A, hsw_gt1, "Intel(R) Haswell Server")
+CHIPSET(0x0D1A, hsw_gt2, "Intel(R) Haswell Server")
+CHIPSET(0x0D2A, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D0B, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0D1B, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0D2B, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0D0E, hsw_gt1, "Intel(R) Haswell")
+CHIPSET(0x0D1E, hsw_gt2, "Intel(R) Haswell")
+CHIPSET(0x0D2E, hsw_gt3, "Intel(R) Haswell")
+CHIPSET(0x0F31, byt,     "Intel(R) Bay Trail")
+CHIPSET(0x0F32, byt,     "Intel(R) Bay Trail")
+CHIPSET(0x0F33, byt,     "Intel(R) Bay Trail")
+CHIPSET(0x0157, byt,     "Intel(R) Bay Trail")
+CHIPSET(0x0155, byt,     "Intel(R) Bay Trail")
+CHIPSET(0x1602, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x1606, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x160A, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x160B, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x160D, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x160E, bdw_gt1, "Intel(R) Broadwell GT1")
+CHIPSET(0x1612, bdw_gt2, "Intel(R) HD Graphics 5600 (Broadwell GT2)")
+CHIPSET(0x1616, bdw_gt2, "Intel(R) HD Graphics 5500 (Broadwell GT2)")
+CHIPSET(0x161A, bdw_gt2, "Intel(R) Broadwell GT2")
+CHIPSET(0x161B, bdw_gt2, "Intel(R) Broadwell GT2")
+CHIPSET(0x161D, bdw_gt2, "Intel(R) Broadwell GT2")
+CHIPSET(0x161E, bdw_gt2, "Intel(R) HD Graphics 5300 (Broadwell GT2)")
+CHIPSET(0x1622, bdw_gt3, "Intel(R) Iris Pro 6200 (Broadwell GT3e)")
+CHIPSET(0x1626, bdw_gt3, "Intel(R) HD Graphics 6000 (Broadwell GT3)")
+CHIPSET(0x162A, bdw_gt3, "Intel(R) Iris Pro P6300 (Broadwell GT3e)")
+CHIPSET(0x162B, bdw_gt3, "Intel(R) Iris 6100 (Broadwell GT3)")
+CHIPSET(0x162D, bdw_gt3, "Intel(R) Broadwell GT3")
+CHIPSET(0x162E, bdw_gt3, "Intel(R) Broadwell GT3")
+CHIPSET(0x22B0, chv,     "Intel(R) Cherryview")
+CHIPSET(0x22B1, chv,     "Intel(R) Cherryview")
+CHIPSET(0x22B2, chv,     "Intel(R) Cherryview")
+CHIPSET(0x22B3, chv,     "Intel(R) Cherryview")
diff --git a/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h b/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h
new file mode 100644
index 0000000..8a97c6f
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h
@@ -0,0 +1,80 @@
+#ifndef _PCI_ID_DRIVER_MAP_H_
+#define _PCI_ID_DRIVER_MAP_H_
+
+#include <stddef.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+static const int i915_chip_ids[] = {
+#define CHIPSET(chip, desc, name) chip,
+#include "pci_ids/i915_pci_ids.h"
+#undef CHIPSET
+};
+
+static const int i965_chip_ids[] = {
+#define CHIPSET(chip, family, name) chip,
+#include "pci_ids/i965_pci_ids.h"
+#undef CHIPSET
+};
+
+#ifndef DRIVER_MAP_GALLIUM_ONLY
+static const int r100_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/radeon_pci_ids.h"
+#undef CHIPSET
+};
+
+static const int r200_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/r200_pci_ids.h"
+#undef CHIPSET
+};
+#endif
+
+static const int r300_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/r300_pci_ids.h"
+#undef CHIPSET
+};
+
+static const int r600_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/r600_pci_ids.h"
+#undef CHIPSET
+};
+
+static const int radeonsi_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/radeonsi_pci_ids.h"
+#undef CHIPSET
+};
+
+static const int vmwgfx_chip_ids[] = {
+#define CHIPSET(chip, name, family) chip,
+#include "pci_ids/vmwgfx_pci_ids.h"
+#undef CHIPSET
+};
+
+static const struct {
+   int vendor_id;
+   const char *driver;
+   const int *chip_ids;
+   int num_chips_ids;
+} driver_map[] = {
+   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
+   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
+#ifndef DRIVER_MAP_GALLIUM_ONLY
+   { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) },
+   { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) },
+#endif
+   { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) },
+   { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) },
+   { 0x1002, "radeonsi", radeonsi_chip_ids, ARRAY_SIZE(radeonsi_chip_ids) },
+   { 0x10de, "nouveau", NULL, -1 },
+   { 0x15ad, "vmwgfx", vmwgfx_chip_ids, ARRAY_SIZE(vmwgfx_chip_ids) },
+   { 0x0000, NULL, NULL, 0 },
+};
+
+#endif /* _PCI_ID_DRIVER_MAP_H_ */
diff --git a/hw/xfree86/dri2/pci_ids/r200_pci_ids.h b/hw/xfree86/dri2/pci_ids/r200_pci_ids.h
new file mode 100644
index 0000000..f857ca7
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/r200_pci_ids.h
@@ -0,0 +1,24 @@
+CHIPSET(0x5148, R200_QH, R200)
+CHIPSET(0x514C, R200_QL, R200)
+CHIPSET(0x514D, R200_QM, R200)
+CHIPSET(0x4242, R200_BB, R200)
+
+CHIPSET(0x4966, RV250_If, RV250)
+CHIPSET(0x4967, RV250_Ig, RV250)
+CHIPSET(0x4C64, RV250_Ld, RV250)
+CHIPSET(0x4C66, RV250_Lf, RV250)
+CHIPSET(0x4C67, RV250_Lg, RV250)
+
+CHIPSET(0x4C6E, RV280_4C6E, RV280)
+CHIPSET(0x5960, RV280_5960, RV280)
+CHIPSET(0x5961, RV280_5961, RV280)
+CHIPSET(0x5962, RV280_5962, RV280)
+CHIPSET(0x5964, RV280_5964, RV280)
+CHIPSET(0x5965, RV280_5965, RV280)
+CHIPSET(0x5C61, RV280_5C61, RV280)
+CHIPSET(0x5C63, RV280_5C63, RV280)
+
+CHIPSET(0x5834, RS300_5834, RS300)
+CHIPSET(0x5835, RS300_5835, RS300)
+CHIPSET(0x7834, RS350_7834, RS300)
+CHIPSET(0x7835, RS350_7835, RS300)
diff --git a/hw/xfree86/dri2/pci_ids/r300_pci_ids.h b/hw/xfree86/dri2/pci_ids/r300_pci_ids.h
new file mode 100644
index 0000000..791026a
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/r300_pci_ids.h
@@ -0,0 +1,227 @@
+CHIPSET(0x4144, R300_AD, R300)
+CHIPSET(0x4145, R300_AE, R300)
+CHIPSET(0x4146, R300_AF, R300)
+CHIPSET(0x4147, R300_AG, R300)
+CHIPSET(0x4E44, R300_ND, R300)
+CHIPSET(0x4E45, R300_NE, R300)
+CHIPSET(0x4E46, R300_NF, R300)
+CHIPSET(0x4E47, R300_NG, R300)
+
+CHIPSET(0x4E48, R350_NH, R350)
+CHIPSET(0x4E49, R350_NI, R350)
+CHIPSET(0x4E4B, R350_NK, R350)
+CHIPSET(0x4148, R350_AH, R350)
+CHIPSET(0x4149, R350_AI, R350)
+CHIPSET(0x414A, R350_AJ, R350)
+CHIPSET(0x414B, R350_AK, R350)
+CHIPSET(0x4E4A, R360_NJ, R350)
+
+CHIPSET(0x4150, RV350_AP, RV350)
+CHIPSET(0x4151, RV350_AQ, RV350)
+CHIPSET(0x4152, RV350_AR, RV350)
+CHIPSET(0x4153, RV350_AS, RV350)
+CHIPSET(0x4154, RV350_AT, RV350)
+CHIPSET(0x4155, RV350_AU, RV350)
+CHIPSET(0x4156, RV350_AV, RV350)
+CHIPSET(0x4E50, RV350_NP, RV350)
+CHIPSET(0x4E51, RV350_NQ, RV350)
+CHIPSET(0x4E52, RV350_NR, RV350)
+CHIPSET(0x4E53, RV350_NS, RV350)
+CHIPSET(0x4E54, RV350_NT, RV350)
+CHIPSET(0x4E56, RV350_NV, RV350)
+
+CHIPSET(0x5460, RV370_5460, RV370)
+CHIPSET(0x5462, RV370_5462, RV370)
+CHIPSET(0x5464, RV370_5464, RV370)
+CHIPSET(0x5B60, RV370_5B60, RV370)
+CHIPSET(0x5B62, RV370_5B62, RV370)
+CHIPSET(0x5B63, RV370_5B63, RV370)
+CHIPSET(0x5B64, RV370_5B64, RV370)
+CHIPSET(0x5B65, RV370_5B65, RV370)
+
+CHIPSET(0x3150, RV380_3150, RV380)
+CHIPSET(0x3151, RV380_3151, RV380)
+CHIPSET(0x3152, RV380_3152, RV380)
+CHIPSET(0x3154, RV380_3154, RV380)
+CHIPSET(0x3155, RV380_3155, RV380)
+CHIPSET(0x3E50, RV380_3E50, RV380)
+CHIPSET(0x3E54, RV380_3E54, RV380)
+
+CHIPSET(0x4A48, R420_JH, R420)
+CHIPSET(0x4A49, R420_JI, R420)
+CHIPSET(0x4A4A, R420_JJ, R420)
+CHIPSET(0x4A4B, R420_JK, R420)
+CHIPSET(0x4A4C, R420_JL, R420)
+CHIPSET(0x4A4D, R420_JM, R420)
+CHIPSET(0x4A4E, R420_JN, R420)
+CHIPSET(0x4A4F, R420_JO, R420)
+CHIPSET(0x4A50, R420_JP, R420)
+CHIPSET(0x4A54, R420_JT, R420)
+
+CHIPSET(0x5548, R423_UH, R423)
+CHIPSET(0x5549, R423_UI, R423)
+CHIPSET(0x554A, R423_UJ, R423)
+CHIPSET(0x554B, R423_UK, R423)
+CHIPSET(0x5550, R423_5550, R423)
+CHIPSET(0x5551, R423_UQ, R423)
+CHIPSET(0x5552, R423_UR, R423)
+CHIPSET(0x5554, R423_UT, R423)
+CHIPSET(0x5D57, R423_5D57, R423)
+
+CHIPSET(0x554C, R430_554C, R430)
+CHIPSET(0x554D, R430_554D, R430)
+CHIPSET(0x554E, R430_554E, R430)
+CHIPSET(0x554F, R430_554F, R430)
+CHIPSET(0x5D48, R430_5D48, R430)
+CHIPSET(0x5D49, R430_5D49, R430)
+CHIPSET(0x5D4A, R430_5D4A, R430)
+
+CHIPSET(0x5D4C, R480_5D4C, R480)
+CHIPSET(0x5D4D, R480_5D4D, R480)
+CHIPSET(0x5D4E, R480_5D4E, R480)
+CHIPSET(0x5D4F, R480_5D4F, R480)
+CHIPSET(0x5D50, R480_5D50, R480)
+CHIPSET(0x5D52, R480_5D52, R480)
+
+CHIPSET(0x4B48, R481_4B48, R481)
+CHIPSET(0x4B49, R481_4B49, R481)
+CHIPSET(0x4B4A, R481_4B4A, R481)
+CHIPSET(0x4B4B, R481_4B4B, R481)
+CHIPSET(0x4B4C, R481_4B4C, R481)
+
+CHIPSET(0x564A, RV410_564A, RV410)
+CHIPSET(0x564B, RV410_564B, RV410)
+CHIPSET(0x564F, RV410_564F, RV410)
+CHIPSET(0x5652, RV410_5652, RV410)
+CHIPSET(0x5653, RV410_5653, RV410)
+CHIPSET(0x5657, RV410_5657, RV410)
+CHIPSET(0x5E48, RV410_5E48, RV410)
+CHIPSET(0x5E4A, RV410_5E4A, RV410)
+CHIPSET(0x5E4B, RV410_5E4B, RV410)
+CHIPSET(0x5E4C, RV410_5E4C, RV410)
+CHIPSET(0x5E4D, RV410_5E4D, RV410)
+CHIPSET(0x5E4F, RV410_5E4F, RV410)
+
+CHIPSET(0x5A41, RS400_5A41, RS400)
+CHIPSET(0x5A42, RS400_5A42, RS400)
+
+CHIPSET(0x5A61, RC410_5A61, RC410)
+CHIPSET(0x5A62, RC410_5A62, RC410)
+
+CHIPSET(0x5954, RS480_5954, RS480)
+CHIPSET(0x5955, RS480_5955, RS480)
+CHIPSET(0x5974, RS482_5974, RS480)
+CHIPSET(0x5975, RS482_5975, RS480)
+
+CHIPSET(0x7100, R520_7100, R520)
+CHIPSET(0x7101, R520_7101, R520)
+CHIPSET(0x7102, R520_7102, R520)
+CHIPSET(0x7103, R520_7103, R520)
+CHIPSET(0x7104, R520_7104, R520)
+CHIPSET(0x7105, R520_7105, R520)
+CHIPSET(0x7106, R520_7106, R520)
+CHIPSET(0x7108, R520_7108, R520)
+CHIPSET(0x7109, R520_7109, R520)
+CHIPSET(0x710A, R520_710A, R520)
+CHIPSET(0x710B, R520_710B, R520)
+CHIPSET(0x710C, R520_710C, R520)
+CHIPSET(0x710E, R520_710E, R520)
+CHIPSET(0x710F, R520_710F, R520)
+
+CHIPSET(0x7140, RV515_7140, RV515)
+CHIPSET(0x7141, RV515_7141, RV515)
+CHIPSET(0x7142, RV515_7142, RV515)
+CHIPSET(0x7143, RV515_7143, RV515)
+CHIPSET(0x7144, RV515_7144, RV515)
+CHIPSET(0x7145, RV515_7145, RV515)
+CHIPSET(0x7146, RV515_7146, RV515)
+CHIPSET(0x7147, RV515_7147, RV515)
+CHIPSET(0x7149, RV515_7149, RV515)
+CHIPSET(0x714A, RV515_714A, RV515)
+CHIPSET(0x714B, RV515_714B, RV515)
+CHIPSET(0x714C, RV515_714C, RV515)
+CHIPSET(0x714D, RV515_714D, RV515)
+CHIPSET(0x714E, RV515_714E, RV515)
+CHIPSET(0x714F, RV515_714F, RV515)
+CHIPSET(0x7151, RV515_7151, RV515)
+CHIPSET(0x7152, RV515_7152, RV515)
+CHIPSET(0x7153, RV515_7153, RV515)
+CHIPSET(0x715E, RV515_715E, RV515)
+CHIPSET(0x715F, RV515_715F, RV515)
+CHIPSET(0x7180, RV515_7180, RV515)
+CHIPSET(0x7181, RV515_7181, RV515)
+CHIPSET(0x7183, RV515_7183, RV515)
+CHIPSET(0x7186, RV515_7186, RV515)
+CHIPSET(0x7187, RV515_7187, RV515)
+CHIPSET(0x7188, RV515_7188, RV515)
+CHIPSET(0x718A, RV515_718A, RV515)
+CHIPSET(0x718B, RV515_718B, RV515)
+CHIPSET(0x718C, RV515_718C, RV515)
+CHIPSET(0x718D, RV515_718D, RV515)
+CHIPSET(0x718F, RV515_718F, RV515)
+CHIPSET(0x7193, RV515_7193, RV515)
+CHIPSET(0x7196, RV515_7196, RV515)
+CHIPSET(0x719B, RV515_719B, RV515)
+CHIPSET(0x719F, RV515_719F, RV515)
+CHIPSET(0x7200, RV515_7200, RV515)
+CHIPSET(0x7210, RV515_7210, RV515)
+CHIPSET(0x7211, RV515_7211, RV515)
+
+CHIPSET(0x71C0, RV530_71C0, RV530)
+CHIPSET(0x71C1, RV530_71C1, RV530)
+CHIPSET(0x71C2, RV530_71C2, RV530)
+CHIPSET(0x71C3, RV530_71C3, RV530)
+CHIPSET(0x71C4, RV530_71C4, RV530)
+CHIPSET(0x71C5, RV530_71C5, RV530)
+CHIPSET(0x71C6, RV530_71C6, RV530)
+CHIPSET(0x71C7, RV530_71C7, RV530)
+CHIPSET(0x71CD, RV530_71CD, RV530)
+CHIPSET(0x71CE, RV530_71CE, RV530)
+CHIPSET(0x71D2, RV530_71D2, RV530)
+CHIPSET(0x71D4, RV530_71D4, RV530)
+CHIPSET(0x71D5, RV530_71D5, RV530)
+CHIPSET(0x71D6, RV530_71D6, RV530)
+CHIPSET(0x71DA, RV530_71DA, RV530)
+CHIPSET(0x71DE, RV530_71DE, RV530)
+
+CHIPSET(0x7281, RV560_7281, RV560)
+CHIPSET(0x7283, RV560_7283, RV560)
+CHIPSET(0x7287, RV560_7287, RV560)
+CHIPSET(0x7290, RV560_7290, RV560)
+CHIPSET(0x7291, RV560_7291, RV560)
+CHIPSET(0x7293, RV560_7293, RV560)
+CHIPSET(0x7297, RV560_7297, RV560)
+
+CHIPSET(0x7280, RV570_7280, RV570)
+CHIPSET(0x7288, RV570_7288, RV570)
+CHIPSET(0x7289, RV570_7289, RV570)
+CHIPSET(0x728B, RV570_728B, RV570)
+CHIPSET(0x728C, RV570_728C, RV570)
+
+CHIPSET(0x7240, R580_7240, R580)
+CHIPSET(0x7243, R580_7243, R580)
+CHIPSET(0x7244, R580_7244, R580)
+CHIPSET(0x7245, R580_7245, R580)
+CHIPSET(0x7246, R580_7246, R580)
+CHIPSET(0x7247, R580_7247, R580)
+CHIPSET(0x7248, R580_7248, R580)
+CHIPSET(0x7249, R580_7249, R580)
+CHIPSET(0x724A, R580_724A, R580)
+CHIPSET(0x724B, R580_724B, R580)
+CHIPSET(0x724C, R580_724C, R580)
+CHIPSET(0x724D, R580_724D, R580)
+CHIPSET(0x724E, R580_724E, R580)
+CHIPSET(0x724F, R580_724F, R580)
+CHIPSET(0x7284, R580_7284, R580)
+
+CHIPSET(0x793F, RS600_793F, RS600)
+CHIPSET(0x7941, RS600_7941, RS600)
+CHIPSET(0x7942, RS600_7942, RS600)
+
+CHIPSET(0x791E, RS690_791E, RS690)
+CHIPSET(0x791F, RS690_791F, RS690)
+
+CHIPSET(0x796C, RS740_796C, RS740)
+CHIPSET(0x796D, RS740_796D, RS740)
+CHIPSET(0x796E, RS740_796E, RS740)
+CHIPSET(0x796F, RS740_796F, RS740)
diff --git a/hw/xfree86/dri2/pci_ids/r600_pci_ids.h b/hw/xfree86/dri2/pci_ids/r600_pci_ids.h
new file mode 100644
index 0000000..533c9f3
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/r600_pci_ids.h
@@ -0,0 +1,327 @@
+CHIPSET(0x9400, R600_9400, R600)
+CHIPSET(0x9401, R600_9401, R600)
+CHIPSET(0x9402, R600_9402, R600)
+CHIPSET(0x9403, R600_9403, R600)
+CHIPSET(0x9405, R600_9405, R600)
+CHIPSET(0x940A, R600_940A, R600)
+CHIPSET(0x940B, R600_940B, R600)
+CHIPSET(0x940F, R600_940F, R600)
+
+CHIPSET(0x94C0, RV610_94C0, RV610)
+CHIPSET(0x94C1, RV610_94C1, RV610)
+CHIPSET(0x94C3, RV610_94C3, RV610)
+CHIPSET(0x94C4, RV610_94C4, RV610)
+CHIPSET(0x94C5, RV610_94C5, RV610)
+CHIPSET(0x94C6, RV610_94C6, RV610)
+CHIPSET(0x94C7, RV610_94C7, RV610)
+CHIPSET(0x94C8, RV610_94C8, RV610)
+CHIPSET(0x94C9, RV610_94C9, RV610)
+CHIPSET(0x94CB, RV610_94CB, RV610)
+CHIPSET(0x94CC, RV610_94CC, RV610)
+CHIPSET(0x94CD, RV610_94CD, RV610)
+
+CHIPSET(0x9580, RV630_9580, RV630)
+CHIPSET(0x9581, RV630_9581, RV630)
+CHIPSET(0x9583, RV630_9583, RV630)
+CHIPSET(0x9586, RV630_9586, RV630)
+CHIPSET(0x9587, RV630_9587, RV630)
+CHIPSET(0x9588, RV630_9588, RV630)
+CHIPSET(0x9589, RV630_9589, RV630)
+CHIPSET(0x958A, RV630_958A, RV630)
+CHIPSET(0x958B, RV630_958B, RV630)
+CHIPSET(0x958C, RV630_958C, RV630)
+CHIPSET(0x958D, RV630_958D, RV630)
+CHIPSET(0x958E, RV630_958E, RV630)
+CHIPSET(0x958F, RV630_958F, RV630)
+
+CHIPSET(0x9500, RV670_9500, RV670)
+CHIPSET(0x9501, RV670_9501, RV670)
+CHIPSET(0x9504, RV670_9504, RV670)
+CHIPSET(0x9505, RV670_9505, RV670)
+CHIPSET(0x9506, RV670_9506, RV670)
+CHIPSET(0x9507, RV670_9507, RV670)
+CHIPSET(0x9508, RV670_9508, RV670)
+CHIPSET(0x9509, RV670_9509, RV670)
+CHIPSET(0x950F, RV670_950F, RV670)
+CHIPSET(0x9511, RV670_9511, RV670)
+CHIPSET(0x9515, RV670_9515, RV670)
+CHIPSET(0x9517, RV670_9517, RV670)
+CHIPSET(0x9519, RV670_9519, RV670)
+
+CHIPSET(0x95C0, RV620_95C0, RV620)
+CHIPSET(0x95C2, RV620_95C2, RV620)
+CHIPSET(0x95C4, RV620_95C4, RV620)
+CHIPSET(0x95C5, RV620_95C5, RV620)
+CHIPSET(0x95C6, RV620_95C6, RV620)
+CHIPSET(0x95C7, RV620_95C7, RV620)
+CHIPSET(0x95C9, RV620_95C9, RV620)
+CHIPSET(0x95CC, RV620_95CC, RV620)
+CHIPSET(0x95CD, RV620_95CD, RV620)
+CHIPSET(0x95CE, RV620_95CE, RV620)
+CHIPSET(0x95CF, RV620_95CF, RV620)
+
+CHIPSET(0x9590, RV635_9590, RV635)
+CHIPSET(0x9591, RV635_9591, RV635)
+CHIPSET(0x9593, RV635_9593, RV635)
+CHIPSET(0x9595, RV635_9595, RV635)
+CHIPSET(0x9596, RV635_9596, RV635)
+CHIPSET(0x9597, RV635_9597, RV635)
+CHIPSET(0x9598, RV635_9598, RV635)
+CHIPSET(0x9599, RV635_9599, RV635)
+CHIPSET(0x959B, RV635_959B, RV635)
+
+CHIPSET(0x9610, RS780_9610, RS780)
+CHIPSET(0x9611, RS780_9611, RS780)
+CHIPSET(0x9612, RS780_9612, RS780)
+CHIPSET(0x9613, RS780_9613, RS780)
+CHIPSET(0x9614, RS780_9614, RS780)
+CHIPSET(0x9615, RS780_9615, RS780)
+CHIPSET(0x9616, RS780_9616, RS780)
+
+CHIPSET(0x9710, RS880_9710, RS880)
+CHIPSET(0x9711, RS880_9711, RS880)
+CHIPSET(0x9712, RS880_9712, RS880)
+CHIPSET(0x9713, RS880_9713, RS880)
+CHIPSET(0x9714, RS880_9714, RS880)
+CHIPSET(0x9715, RS880_9715, RS880)
+
+CHIPSET(0x9440, RV770_9440, RV770)
+CHIPSET(0x9441, RV770_9441, RV770)
+CHIPSET(0x9442, RV770_9442, RV770)
+CHIPSET(0x9443, RV770_9443, RV770)
+CHIPSET(0x9444, RV770_9444, RV770)
+CHIPSET(0x9446, RV770_9446, RV770)
+CHIPSET(0x944A, RV770_944A, RV770)
+CHIPSET(0x944B, RV770_944B, RV770)
+CHIPSET(0x944C, RV770_944C, RV770)
+CHIPSET(0x944E, RV770_944E, RV770)
+CHIPSET(0x9450, RV770_9450, RV770)
+CHIPSET(0x9452, RV770_9452, RV770)
+CHIPSET(0x9456, RV770_9456, RV770)
+CHIPSET(0x945A, RV770_945A, RV770)
+CHIPSET(0x945B, RV770_945B, RV770)
+CHIPSET(0x945E, RV770_945E, RV770)
+CHIPSET(0x9460, RV790_9460, RV770)
+CHIPSET(0x9462, RV790_9462, RV770)
+CHIPSET(0x946A, RV770_946A, RV770)
+CHIPSET(0x946B, RV770_946B, RV770)
+CHIPSET(0x947A, RV770_947A, RV770)
+CHIPSET(0x947B, RV770_947B, RV770)
+
+CHIPSET(0x9480, RV730_9480, RV730)
+CHIPSET(0x9487, RV730_9487, RV730)
+CHIPSET(0x9488, RV730_9488, RV730)
+CHIPSET(0x9489, RV730_9489, RV730)
+CHIPSET(0x948A, RV730_948A, RV730)
+CHIPSET(0x948F, RV730_948F, RV730)
+CHIPSET(0x9490, RV730_9490, RV730)
+CHIPSET(0x9491, RV730_9491, RV730)
+CHIPSET(0x9495, RV730_9495, RV730)
+CHIPSET(0x9498, RV730_9498, RV730)
+CHIPSET(0x949C, RV730_949C, RV730)
+CHIPSET(0x949E, RV730_949E, RV730)
+CHIPSET(0x949F, RV730_949F, RV730)
+
+CHIPSET(0x9540, RV710_9540, RV710)
+CHIPSET(0x9541, RV710_9541, RV710)
+CHIPSET(0x9542, RV710_9542, RV710)
+CHIPSET(0x954E, RV710_954E, RV710)
+CHIPSET(0x954F, RV710_954F, RV710)
+CHIPSET(0x9552, RV710_9552, RV710)
+CHIPSET(0x9553, RV710_9553, RV710)
+CHIPSET(0x9555, RV710_9555, RV710)
+CHIPSET(0x9557, RV710_9557, RV710)
+CHIPSET(0x955F, RV710_955F, RV710)
+
+CHIPSET(0x94A0, RV740_94A0, RV740)
+CHIPSET(0x94A1, RV740_94A1, RV740)
+CHIPSET(0x94A3, RV740_94A3, RV740)
+CHIPSET(0x94B1, RV740_94B1, RV740)
+CHIPSET(0x94B3, RV740_94B3, RV740)
+CHIPSET(0x94B4, RV740_94B4, RV740)
+CHIPSET(0x94B5, RV740_94B5, RV740)
+CHIPSET(0x94B9, RV740_94B9, RV740)
+
+CHIPSET(0x68E0, CEDAR_68E0, CEDAR)
+CHIPSET(0x68E1, CEDAR_68E1, CEDAR)
+CHIPSET(0x68E4, CEDAR_68E4, CEDAR)
+CHIPSET(0x68E5, CEDAR_68E5, CEDAR)
+CHIPSET(0x68E8, CEDAR_68E8, CEDAR)
+CHIPSET(0x68E9, CEDAR_68E9, CEDAR)
+CHIPSET(0x68F1, CEDAR_68F1, CEDAR)
+CHIPSET(0x68F2, CEDAR_68F2, CEDAR)
+CHIPSET(0x68F8, CEDAR_68F8, CEDAR)
+CHIPSET(0x68F9, CEDAR_68F9, CEDAR)
+CHIPSET(0x68FA, CEDAR_68FA, CEDAR)
+CHIPSET(0x68FE, CEDAR_68FE, CEDAR)
+
+CHIPSET(0x68C0, REDWOOD_68C0, REDWOOD)
+CHIPSET(0x68C1, REDWOOD_68C1, REDWOOD)
+CHIPSET(0x68C7, REDWOOD_68C7, REDWOOD)
+CHIPSET(0x68C8, REDWOOD_68C8, REDWOOD)
+CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD)
+CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD)
+CHIPSET(0x68D9, REDWOOD_68D9, REDWOOD)
+CHIPSET(0x68DA, REDWOOD_68DA, REDWOOD)
+CHIPSET(0x68DE, REDWOOD_68DE, REDWOOD)
+
+CHIPSET(0x68A0, JUNIPER_68A0, JUNIPER)
+CHIPSET(0x68A1, JUNIPER_68A1, JUNIPER)
+CHIPSET(0x68A8, JUNIPER_68A8, JUNIPER)
+CHIPSET(0x68A9, JUNIPER_68A9, JUNIPER)
+CHIPSET(0x68B0, JUNIPER_68B0, JUNIPER)
+CHIPSET(0x68B8, JUNIPER_68B8, JUNIPER)
+CHIPSET(0x68B9, JUNIPER_68B9, JUNIPER)
+CHIPSET(0x68BA, JUNIPER_68BA, JUNIPER)
+CHIPSET(0x68BE, JUNIPER_68BE, JUNIPER)
+CHIPSET(0x68BF, JUNIPER_68BF, JUNIPER)
+
+CHIPSET(0x6880, CYPRESS_6880, CYPRESS)
+CHIPSET(0x6888, CYPRESS_6888, CYPRESS)
+CHIPSET(0x6889, CYPRESS_6889, CYPRESS)
+CHIPSET(0x688A, CYPRESS_688A, CYPRESS)
+CHIPSET(0x688C, CYPRESS_688C, CYPRESS)
+CHIPSET(0x688D, CYPRESS_688D, CYPRESS)
+CHIPSET(0x6898, CYPRESS_6898, CYPRESS)
+CHIPSET(0x6899, CYPRESS_6899, CYPRESS)
+CHIPSET(0x689B, CYPRESS_689B, CYPRESS)
+CHIPSET(0x689E, CYPRESS_689E, CYPRESS)
+
+CHIPSET(0x689C, HEMLOCK_689C, HEMLOCK)
+CHIPSET(0x689D, HEMLOCK_689D, HEMLOCK)
+
+CHIPSET(0x9802, PALM_9802, PALM)
+CHIPSET(0x9803, PALM_9803, PALM)
+CHIPSET(0x9804, PALM_9804, PALM)
+CHIPSET(0x9805, PALM_9805, PALM)
+CHIPSET(0x9806, PALM_9806, PALM)
+CHIPSET(0x9807, PALM_9807, PALM)
+CHIPSET(0x9808, PALM_9808, PALM)
+CHIPSET(0x9809, PALM_9809, PALM)
+CHIPSET(0x980A, PALM_980A, PALM)
+
+CHIPSET(0x9640, SUMO_9640,  SUMO)
+CHIPSET(0x9641, SUMO_9641,  SUMO)
+CHIPSET(0x9642, SUMO2_9642, SUMO2)
+CHIPSET(0x9643, SUMO2_9643, SUMO2)
+CHIPSET(0x9644, SUMO2_9644, SUMO2)
+CHIPSET(0x9645, SUMO2_9645, SUMO2)
+CHIPSET(0x9647, SUMO_9647,  SUMO)
+CHIPSET(0x9648, SUMO_9648,  SUMO)
+CHIPSET(0x9649, SUMO2_9649, SUMO2)
+CHIPSET(0x964a, SUMO_964A,  SUMO)
+CHIPSET(0x964b, SUMO_964B,  SUMO)
+CHIPSET(0x964c, SUMO_964C,  SUMO)
+CHIPSET(0x964e, SUMO_964E,  SUMO)
+CHIPSET(0x964f, SUMO_964F,  SUMO)
+
+CHIPSET(0x6700, CAYMAN_6700, CAYMAN)
+CHIPSET(0x6701, CAYMAN_6701, CAYMAN)
+CHIPSET(0x6702, CAYMAN_6702, CAYMAN)
+CHIPSET(0x6703, CAYMAN_6703, CAYMAN)
+CHIPSET(0x6704, CAYMAN_6704, CAYMAN)
+CHIPSET(0x6705, CAYMAN_6705, CAYMAN)
+CHIPSET(0x6706, CAYMAN_6706, CAYMAN)
+CHIPSET(0x6707, CAYMAN_6707, CAYMAN)
+CHIPSET(0x6708, CAYMAN_6708, CAYMAN)
+CHIPSET(0x6709, CAYMAN_6709, CAYMAN)
+CHIPSET(0x6718, CAYMAN_6718, CAYMAN)
+CHIPSET(0x6719, CAYMAN_6719, CAYMAN)
+CHIPSET(0x671C, CAYMAN_671C, CAYMAN)
+CHIPSET(0x671D, CAYMAN_671D, CAYMAN)
+CHIPSET(0x671F, CAYMAN_671F, CAYMAN)
+
+CHIPSET(0x6720, BARTS_6720, BARTS)
+CHIPSET(0x6721, BARTS_6721, BARTS)
+CHIPSET(0x6722, BARTS_6722, BARTS)
+CHIPSET(0x6723, BARTS_6723, BARTS)
+CHIPSET(0x6724, BARTS_6724, BARTS)
+CHIPSET(0x6725, BARTS_6725, BARTS)
+CHIPSET(0x6726, BARTS_6726, BARTS)
+CHIPSET(0x6727, BARTS_6727, BARTS)
+CHIPSET(0x6728, BARTS_6728, BARTS)
+CHIPSET(0x6729, BARTS_6729, BARTS)
+CHIPSET(0x6738, BARTS_6738, BARTS)
+CHIPSET(0x6739, BARTS_6739, BARTS)
+CHIPSET(0x673E, BARTS_673E, BARTS)
+
+CHIPSET(0x6740, TURKS_6740, TURKS)
+CHIPSET(0x6741, TURKS_6741, TURKS)
+CHIPSET(0x6742, TURKS_6742, TURKS)
+CHIPSET(0x6743, TURKS_6743, TURKS)
+CHIPSET(0x6744, TURKS_6744, TURKS)
+CHIPSET(0x6745, TURKS_6745, TURKS)
+CHIPSET(0x6746, TURKS_6746, TURKS)
+CHIPSET(0x6747, TURKS_6747, TURKS)
+CHIPSET(0x6748, TURKS_6748, TURKS)
+CHIPSET(0x6749, TURKS_6749, TURKS)
+CHIPSET(0x674A, TURKS_674A, TURKS)
+CHIPSET(0x6750, TURKS_6750, TURKS)
+CHIPSET(0x6751, TURKS_6751, TURKS)
+CHIPSET(0x6758, TURKS_6758, TURKS)
+CHIPSET(0x6759, TURKS_6759, TURKS)
+CHIPSET(0x675B, TURKS_675B, TURKS)
+CHIPSET(0x675D, TURKS_675D, TURKS)
+CHIPSET(0x675F, TURKS_675F, TURKS)
+CHIPSET(0x6840, TURKS_6840, TURKS)
+CHIPSET(0x6841, TURKS_6841, TURKS)
+CHIPSET(0x6842, TURKS_6842, TURKS)
+CHIPSET(0x6843, TURKS_6843, TURKS)
+CHIPSET(0x6849, TURKS_6849, TURKS)
+CHIPSET(0x6850, TURKS_6850, TURKS)
+CHIPSET(0x6858, TURKS_6858, TURKS)
+CHIPSET(0x6859, TURKS_6859, TURKS)
+
+CHIPSET(0x6760, CAICOS_6760, CAICOS)
+CHIPSET(0x6761, CAICOS_6761, CAICOS)
+CHIPSET(0x6762, CAICOS_6762, CAICOS)
+CHIPSET(0x6763, CAICOS_6763, CAICOS)
+CHIPSET(0x6764, CAICOS_6764, CAICOS)
+CHIPSET(0x6765, CAICOS_6765, CAICOS)
+CHIPSET(0x6766, CAICOS_6766, CAICOS)
+CHIPSET(0x6767, CAICOS_6767, CAICOS)
+CHIPSET(0x6768, CAICOS_6768, CAICOS)
+CHIPSET(0x6770, CAICOS_6770, CAICOS)
+CHIPSET(0x6771, CAICOS_6771, CAICOS)
+CHIPSET(0x6772, CAICOS_6772, CAICOS)
+CHIPSET(0x6778, CAICOS_6778, CAICOS)
+CHIPSET(0x6779, CAICOS_6779, CAICOS)
+CHIPSET(0x677B, CAICOS_677B, CAICOS)
+
+CHIPSET(0x9900, ARUBA_9900, ARUBA)
+CHIPSET(0x9901, ARUBA_9901, ARUBA)
+CHIPSET(0x9903, ARUBA_9903, ARUBA)
+CHIPSET(0x9904, ARUBA_9904, ARUBA)
+CHIPSET(0x9905, ARUBA_9905, ARUBA)
+CHIPSET(0x9906, ARUBA_9906, ARUBA)
+CHIPSET(0x9907, ARUBA_9907, ARUBA)
+CHIPSET(0x9908, ARUBA_9908, ARUBA)
+CHIPSET(0x9909, ARUBA_9909, ARUBA)
+CHIPSET(0x990A, ARUBA_990A, ARUBA)
+CHIPSET(0x990B, ARUBA_990B, ARUBA)
+CHIPSET(0x990C, ARUBA_990C, ARUBA)
+CHIPSET(0x990D, ARUBA_990D, ARUBA)
+CHIPSET(0x990E, ARUBA_990E, ARUBA)
+CHIPSET(0x990F, ARUBA_990F, ARUBA)
+CHIPSET(0x9910, ARUBA_9910, ARUBA)
+CHIPSET(0x9913, ARUBA_9913, ARUBA)
+CHIPSET(0x9917, ARUBA_9917, ARUBA)
+CHIPSET(0x9918, ARUBA_9918, ARUBA)
+CHIPSET(0x9919, ARUBA_9919, ARUBA)
+CHIPSET(0x9990, ARUBA_9990, ARUBA)
+CHIPSET(0x9991, ARUBA_9991, ARUBA)
+CHIPSET(0x9992, ARUBA_9992, ARUBA)
+CHIPSET(0x9993, ARUBA_9993, ARUBA)
+CHIPSET(0x9994, ARUBA_9994, ARUBA)
+CHIPSET(0x9995, ARUBA_9995, ARUBA)
+CHIPSET(0x9996, ARUBA_9996, ARUBA)
+CHIPSET(0x9997, ARUBA_9997, ARUBA)
+CHIPSET(0x9998, ARUBA_9998, ARUBA)
+CHIPSET(0x9999, ARUBA_9999, ARUBA)
+CHIPSET(0x999A, ARUBA_999A, ARUBA)
+CHIPSET(0x999B, ARUBA_999B, ARUBA)
+CHIPSET(0x999C, ARUBA_999C, ARUBA)
+CHIPSET(0x999D, ARUBA_999D, ARUBA)
+CHIPSET(0x99A0, ARUBA_99A0, ARUBA)
+CHIPSET(0x99A2, ARUBA_99A2, ARUBA)
+CHIPSET(0x99A4, ARUBA_99A4, ARUBA)
diff --git a/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h b/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h
new file mode 100644
index 0000000..a9efc76
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h
@@ -0,0 +1,23 @@
+CHIPSET(0x4C57, RADEON_LW, RV200)
+CHIPSET(0x4C58, RADEON_LX, RV200)
+CHIPSET(0x4C59, RADEON_LY, RV100)
+CHIPSET(0x4C5A, RADEON_LZ, RV100)
+CHIPSET(0x5144, RADEON_QD, R100)
+CHIPSET(0x5145, RADEON_QE, R100)
+CHIPSET(0x5146, RADEON_QF, R100)
+CHIPSET(0x5147, RADEON_QG, R100)
+CHIPSET(0x5159, RADEON_QY, RV100)
+CHIPSET(0x515A, RADEON_QZ, RV100)
+
+CHIPSET(0x5157, RV200_QW, RV200)
+CHIPSET(0x5158, RV200_QX, RV200)
+
+CHIPSET(0x515E, RN50_515E, UNKNOWN)
+CHIPSET(0x5969, RN50_5969, UNKNOWN)
+
+CHIPSET(0x4136, RS100_4136, RS100)
+CHIPSET(0x4336, RS100_4336, RS100)
+CHIPSET(0x4137, RS200_4137, RS200)
+CHIPSET(0x4337, RS200_4337, RS200)
+CHIPSET(0x4237, RS250_4237, RS200)
+CHIPSET(0x4437, RS250_4437, RS200)
diff --git a/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h b/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h
new file mode 100644
index 0000000..571e863
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h
@@ -0,0 +1,157 @@
+CHIPSET(0x6780, TAHITI_6780, TAHITI)
+CHIPSET(0x6784, TAHITI_6784, TAHITI)
+CHIPSET(0x6788, TAHITI_6788, TAHITI)
+CHIPSET(0x678A, TAHITI_678A, TAHITI)
+CHIPSET(0x6790, TAHITI_6790, TAHITI)
+CHIPSET(0x6791, TAHITI_6791, TAHITI)
+CHIPSET(0x6792, TAHITI_6792, TAHITI)
+CHIPSET(0x6798, TAHITI_6798, TAHITI)
+CHIPSET(0x6799, TAHITI_6799, TAHITI)
+CHIPSET(0x679A, TAHITI_679A, TAHITI)
+CHIPSET(0x679B, TAHITI_679B, TAHITI)
+CHIPSET(0x679E, TAHITI_679E, TAHITI)
+CHIPSET(0x679F, TAHITI_679F, TAHITI)
+
+CHIPSET(0x6800, PITCAIRN_6800, PITCAIRN)
+CHIPSET(0x6801, PITCAIRN_6801, PITCAIRN)
+CHIPSET(0x6802, PITCAIRN_6802, PITCAIRN)
+CHIPSET(0x6806, PITCAIRN_6806, PITCAIRN)
+CHIPSET(0x6808, PITCAIRN_6808, PITCAIRN)
+CHIPSET(0x6809, PITCAIRN_6809, PITCAIRN)
+CHIPSET(0x6810, PITCAIRN_6810, PITCAIRN)
+CHIPSET(0x6811, PITCAIRN_6811, PITCAIRN)
+CHIPSET(0x6816, PITCAIRN_6816, PITCAIRN)
+CHIPSET(0x6817, PITCAIRN_6817, PITCAIRN)
+CHIPSET(0x6818, PITCAIRN_6818, PITCAIRN)
+CHIPSET(0x6819, PITCAIRN_6819, PITCAIRN)
+CHIPSET(0x684C, PITCAIRN_684C, PITCAIRN)
+
+CHIPSET(0x6820, VERDE_6820, VERDE)
+CHIPSET(0x6821, VERDE_6821, VERDE)
+CHIPSET(0x6822, VERDE_6822, VERDE)
+CHIPSET(0x6823, VERDE_6823, VERDE)
+CHIPSET(0x6824, VERDE_6824, VERDE)
+CHIPSET(0x6825, VERDE_6825, VERDE)
+CHIPSET(0x6826, VERDE_6826, VERDE)
+CHIPSET(0x6827, VERDE_6827, VERDE)
+CHIPSET(0x6828, VERDE_6828, VERDE)
+CHIPSET(0x6829, VERDE_6829, VERDE)
+CHIPSET(0x682A, VERDE_682A, VERDE)
+CHIPSET(0x682B, VERDE_682B, VERDE)
+CHIPSET(0x682C, VERDE_682C, VERDE)
+CHIPSET(0x682D, VERDE_682D, VERDE)
+CHIPSET(0x682F, VERDE_682F, VERDE)
+CHIPSET(0x6830, VERDE_6830, VERDE)
+CHIPSET(0x6831, VERDE_6831, VERDE)
+CHIPSET(0x6835, VERDE_6835, VERDE)
+CHIPSET(0x6837, VERDE_6837, VERDE)
+CHIPSET(0x6838, VERDE_6838, VERDE)
+CHIPSET(0x6839, VERDE_6839, VERDE)
+CHIPSET(0x683B, VERDE_683B, VERDE)
+CHIPSET(0x683D, VERDE_683D, VERDE)
+CHIPSET(0x683F, VERDE_683F, VERDE)
+
+CHIPSET(0x6600, OLAND_6600, OLAND)
+CHIPSET(0x6601, OLAND_6601, OLAND)
+CHIPSET(0x6602, OLAND_6602, OLAND)
+CHIPSET(0x6603, OLAND_6603, OLAND)
+CHIPSET(0x6604, OLAND_6604, OLAND)
+CHIPSET(0x6605, OLAND_6605, OLAND)
+CHIPSET(0x6606, OLAND_6606, OLAND)
+CHIPSET(0x6607, OLAND_6607, OLAND)
+CHIPSET(0x6608, OLAND_6608, OLAND)
+CHIPSET(0x6610, OLAND_6610, OLAND)
+CHIPSET(0x6611, OLAND_6611, OLAND)
+CHIPSET(0x6613, OLAND_6613, OLAND)
+CHIPSET(0x6620, OLAND_6620, OLAND)
+CHIPSET(0x6621, OLAND_6621, OLAND)
+CHIPSET(0x6623, OLAND_6623, OLAND)
+CHIPSET(0x6631, OLAND_6631, OLAND)
+
+CHIPSET(0x6660, HAINAN_6660, HAINAN)
+CHIPSET(0x6663, HAINAN_6663, HAINAN)
+CHIPSET(0x6664, HAINAN_6664, HAINAN)
+CHIPSET(0x6665, HAINAN_6665, HAINAN)
+CHIPSET(0x6667, HAINAN_6667, HAINAN)
+CHIPSET(0x666F, HAINAN_666F, HAINAN)
+
+CHIPSET(0x6640, BONAIRE_6640, BONAIRE)
+CHIPSET(0x6641, BONAIRE_6641, BONAIRE)
+CHIPSET(0x6646, BONAIRE_6646, BONAIRE)
+CHIPSET(0x6647, BONAIRE_6647, BONAIRE)
+CHIPSET(0x6649, BONAIRE_6649, BONAIRE)
+CHIPSET(0x6650, BONAIRE_6650, BONAIRE)
+CHIPSET(0x6651, BONAIRE_6651, BONAIRE)
+CHIPSET(0x6658, BONAIRE_6658, BONAIRE)
+CHIPSET(0x665C, BONAIRE_665C, BONAIRE)
+CHIPSET(0x665D, BONAIRE_665D, BONAIRE)
+
+CHIPSET(0x9830, KABINI_9830, KABINI)
+CHIPSET(0x9831, KABINI_9831, KABINI)
+CHIPSET(0x9832, KABINI_9832, KABINI)
+CHIPSET(0x9833, KABINI_9833, KABINI)
+CHIPSET(0x9834, KABINI_9834, KABINI)
+CHIPSET(0x9835, KABINI_9835, KABINI)
+CHIPSET(0x9836, KABINI_9836, KABINI)
+CHIPSET(0x9837, KABINI_9837, KABINI)
+CHIPSET(0x9838, KABINI_9838, KABINI)
+CHIPSET(0x9839, KABINI_9839, KABINI)
+CHIPSET(0x983A, KABINI_983A, KABINI)
+CHIPSET(0x983B, KABINI_983B, KABINI)
+CHIPSET(0x983C, KABINI_983C, KABINI)
+CHIPSET(0x983D, KABINI_983D, KABINI)
+CHIPSET(0x983E, KABINI_983E, KABINI)
+CHIPSET(0x983F, KABINI_983F, KABINI)
+
+CHIPSET(0x9850, MULLINS_9850, MULLINS)
+CHIPSET(0x9851, MULLINS_9851, MULLINS)
+CHIPSET(0x9852, MULLINS_9852, MULLINS)
+CHIPSET(0x9853, MULLINS_9853, MULLINS)
+CHIPSET(0x9854, MULLINS_9854, MULLINS)
+CHIPSET(0x9855, MULLINS_9855, MULLINS)
+CHIPSET(0x9856, MULLINS_9856, MULLINS)
+CHIPSET(0x9857, MULLINS_9857, MULLINS)
+CHIPSET(0x9858, MULLINS_9858, MULLINS)
+CHIPSET(0x9859, MULLINS_9859, MULLINS)
+CHIPSET(0x985A, MULLINS_985A, MULLINS)
+CHIPSET(0x985B, MULLINS_985B, MULLINS)
+CHIPSET(0x985C, MULLINS_985C, MULLINS)
+CHIPSET(0x985D, MULLINS_985D, MULLINS)
+CHIPSET(0x985E, MULLINS_985E, MULLINS)
+CHIPSET(0x985F, MULLINS_985F, MULLINS)
+
+CHIPSET(0x1304, KAVERI_1304, KAVERI)
+CHIPSET(0x1305, KAVERI_1305, KAVERI)
+CHIPSET(0x1306, KAVERI_1306, KAVERI)
+CHIPSET(0x1307, KAVERI_1307, KAVERI)
+CHIPSET(0x1309, KAVERI_1309, KAVERI)
+CHIPSET(0x130A, KAVERI_130A, KAVERI)
+CHIPSET(0x130B, KAVERI_130B, KAVERI)
+CHIPSET(0x130C, KAVERI_130C, KAVERI)
+CHIPSET(0x130D, KAVERI_130D, KAVERI)
+CHIPSET(0x130E, KAVERI_130E, KAVERI)
+CHIPSET(0x130F, KAVERI_130F, KAVERI)
+CHIPSET(0x1310, KAVERI_1310, KAVERI)
+CHIPSET(0x1311, KAVERI_1311, KAVERI)
+CHIPSET(0x1312, KAVERI_1312, KAVERI)
+CHIPSET(0x1313, KAVERI_1313, KAVERI)
+CHIPSET(0x1315, KAVERI_1315, KAVERI)
+CHIPSET(0x1316, KAVERI_1316, KAVERI)
+CHIPSET(0x1317, KAVERI_1317, KAVERI)
+CHIPSET(0x1318, KAVERI_1318, KAVERI)
+CHIPSET(0x131B, KAVERI_131B, KAVERI)
+CHIPSET(0x131C, KAVERI_131C, KAVERI)
+CHIPSET(0x131D, KAVERI_131D, KAVERI)
+
+CHIPSET(0x67A0, HAWAII_67A0, HAWAII)
+CHIPSET(0x67A1, HAWAII_67A1, HAWAII)
+CHIPSET(0x67A2, HAWAII_67A2, HAWAII)
+CHIPSET(0x67A8, HAWAII_67A8, HAWAII)
+CHIPSET(0x67A9, HAWAII_67A9, HAWAII)
+CHIPSET(0x67AA, HAWAII_67AA, HAWAII)
+CHIPSET(0x67B0, HAWAII_67B0, HAWAII)
+CHIPSET(0x67B1, HAWAII_67B1, HAWAII)
+CHIPSET(0x67B8, HAWAII_67B8, HAWAII)
+CHIPSET(0x67B9, HAWAII_67B9, HAWAII)
+CHIPSET(0x67BA, HAWAII_67BA, HAWAII)
+CHIPSET(0x67BE, HAWAII_67BE, HAWAII)
diff --git a/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h b/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h
new file mode 100644
index 0000000..124d75b
--- /dev/null
+++ b/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h
@@ -0,0 +1 @@
+CHIPSET(0x0405, SVGAII, SVGAII)


More information about the xorg-commit mailing list