drm: remove a bunch of typedefs on the userspace interface
[safe/jmp/linux-2.6] / drivers / char / drm / radeon_state.c
index 717f546..348a89e 100644 (file)
@@ -1,5 +1,5 @@
-/* radeon_state.c -- State support for Radeon -*- linux-c -*-
- *
+/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
+/*
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
  * All Rights Reserved.
  *
@@ -42,25 +42,50 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
                                                    drm_file_t * filp_priv,
                                                    u32 *offset)
 {
-       u32 off = *offset;
+       u64 off = *offset;
+       u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
-       if (off >= dev_priv->fb_location &&
-           off < (dev_priv->gart_vm_start + dev_priv->gart_size))
-               return 0;
-
-       radeon_priv = filp_priv->driver_priv;
-       off += radeon_priv->radeon_fb_delta;
+       /* Hrm ... the story of the offset ... So this function converts
+        * the various ideas of what userland clients might have for an
+        * offset in the card address space into an offset into the card
+        * address space :) So with a sane client, it should just keep
+        * the value intact and just do some boundary checking. However,
+        * not all clients are sane. Some older clients pass us 0 based
+        * offsets relative to the start of the framebuffer and some may
+        * assume the AGP aperture it appended to the framebuffer, so we
+        * try to detect those cases and fix them up.
+        *
+        * Note: It might be a good idea here to make sure the offset lands
+        * in some "allowed" area to protect things like the PCIE GART...
+        */
 
-       DRM_DEBUG("offset fixed up to 0x%x\n", off);
+       /* First, the best case, the offset already lands in either the
+        * framebuffer or the GART mapped space
+        */
+       if (radeon_check_offset(dev_priv, off))
+               return 0;
 
-       if (off < dev_priv->fb_location ||
-           off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
-               return DRM_ERR(EINVAL);
+       /* Ok, that didn't happen... now check if we have a zero based
+        * offset that fits in the framebuffer + gart space, apply the
+        * magic offset we get from SETPARAM or calculated from fb_location
+        */
+       if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
+               radeon_priv = filp_priv->driver_priv;
+               off += radeon_priv->radeon_fb_delta;
+       }
 
-       *offset = off;
+       /* Finally, assume we aimed at a GART offset if beyond the fb */
+       if (off > fb_end)
+               off = off - fb_end - 1 + dev_priv->gart_vm_start;
 
-       return 0;
+       /* Now recheck and fail if out of bounds */
+       if (radeon_check_offset(dev_priv, off)) {
+               DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
+               *offset = off;
+               return 0;
+       }
+       return DRM_ERR(EINVAL);
 }
 
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
@@ -72,10 +97,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 
        case RADEON_EMIT_PP_MISC:
                if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
-                                                 &data[(RADEON_RB3D_DEPTHOFFSET
-                                                        -
-                                                        RADEON_PP_MISC) /
-                                                       4])) {
+                   &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
                        DRM_ERROR("Invalid depth buffer offset\n");
                        return DRM_ERR(EINVAL);
                }
@@ -83,10 +105,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 
        case RADEON_EMIT_PP_CNTL:
                if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
-                                                 &data[(RADEON_RB3D_COLOROFFSET
-                                                        -
-                                                        RADEON_PP_CNTL) /
-                                                       4])) {
+                   &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
                        DRM_ERROR("Invalid colour buffer offset\n");
                        return DRM_ERR(EINVAL);
                }
@@ -109,10 +128,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case RADEON_EMIT_PP_TXFILTER_1:
        case RADEON_EMIT_PP_TXFILTER_2:
                if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
-                                                 &data[(RADEON_PP_TXOFFSET_0
-                                                        -
-                                                        RADEON_PP_TXFILTER_0) /
-                                                       4])) {
+                   &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
                        DRM_ERROR("Invalid R100 texture offset\n");
                        return DRM_ERR(EINVAL);
                }
@@ -126,8 +142,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_CUBIC_OFFSETS_5:{
                        int i;
                        for (i = 0; i < 5; i++) {
-                               if (radeon_check_and_fixup_offset
-                                   (dev_priv, filp_priv, &data[i])) {
+                               if (radeon_check_and_fixup_offset(dev_priv,
+                                                                 filp_priv,
+                                                                 &data[i])) {
                                        DRM_ERROR
                                            ("Invalid R200 cubic texture offset\n");
                                        return DRM_ERR(EINVAL);
@@ -152,6 +169,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                }
                break;
 
+       case R200_EMIT_VAP_CTL:{
+                       RING_LOCALS;
+                       BEGIN_RING(2);
+                       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+                       ADVANCE_RING();
+               }
+               break;
+
        case RADEON_EMIT_RB3D_COLORPITCH:
        case RADEON_EMIT_RE_LINE_PATTERN:
        case RADEON_EMIT_SE_LINE_WIDTH:
@@ -179,7 +204,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
        case R200_EMIT_TFACTOR_0:
        case R200_EMIT_VTX_FMT_0:
-       case R200_EMIT_VAP_CTL:
        case R200_EMIT_MATRIX_SELECT_0:
        case R200_EMIT_TEX_PROC_CTL_2:
        case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
@@ -226,6 +250,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_TXCTLALL_3:
        case R200_EMIT_PP_TXCTLALL_4:
        case R200_EMIT_PP_TXCTLALL_5:
+       case R200_EMIT_VAP_PVS_CNTL:
                /* These packets don't contain memory offsets */
                break;
 
@@ -239,11 +264,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 
 static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                                                     dev_priv,
-                                                    drm_file_t * filp_priv,
-                                                    drm_radeon_kcmd_buffer_t *cmdbuf,
+                                                    drm_file_t *filp_priv,
+                                                    drm_radeon_kcmd_buffer_t *
+                                                    cmdbuf,
                                                     unsigned int *cmdsz)
 {
        u32 *cmd = (u32 *) cmdbuf->buf;
+       u32 offset, narrays;
+       int count, i, k;
 
        *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
 
@@ -257,10 +285,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                return DRM_ERR(EINVAL);
        }
 
-       /* Check client state and fix it up if necessary */
-       if (cmd[0] & 0x8000) {  /* MSB of opcode: next DWORD GUI_CNTL */
-               u32 offset;
+       switch(cmd[0] & 0xff00) {
+       /* XXX Are there old drivers needing other packets? */
+
+       case RADEON_3D_DRAW_IMMD:
+       case RADEON_3D_DRAW_VBUF:
+       case RADEON_3D_DRAW_INDX:
+       case RADEON_WAIT_FOR_IDLE:
+       case RADEON_CP_NOP:
+       case RADEON_3D_CLEAR_ZMASK:
+/*     case RADEON_CP_NEXT_CHAR:
+       case RADEON_CP_PLY_NEXTSCAN:
+       case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
+               /* these packets are safe */
+               break;
+
+       case RADEON_CP_3D_DRAW_IMMD_2:
+       case RADEON_CP_3D_DRAW_VBUF_2:
+       case RADEON_CP_3D_DRAW_INDX_2:
+       case RADEON_3D_CLEAR_HIZ:
+               /* safe but r200 only */
+               if (dev_priv->microcode_version != UCODE_R200) {
+                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+                       return DRM_ERR(EINVAL);
+               }
+               break;
+
+       case RADEON_3D_LOAD_VBPNTR:
+               count = (cmd[0] >> 16) & 0x3fff;
+
+               if (count > 18) { /* 12 arrays max */
+                       DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+                                 count);
+                       return DRM_ERR(EINVAL);
+               }
+
+               /* carefully check packet contents */
+               narrays = cmd[1] & ~0xc000;
+               k = 0;
+               i = 2;
+               while ((k < narrays) && (i < (count + 2))) {
+                       i++;            /* skip attribute field */
+                       if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+                               DRM_ERROR
+                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+                                    k, i);
+                               return DRM_ERR(EINVAL);
+                       }
+                       k++;
+                       i++;
+                       if (k == narrays)
+                               break;
+                       /* have one more to process, they come in pairs */
+                       if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+                               DRM_ERROR
+                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+                                    k, i);
+                               return DRM_ERR(EINVAL);
+                       }
+                       k++;
+                       i++;
+               }
+               /* do the counts match what we expect ? */
+               if ((k != narrays) || (i != (count + 2))) {
+                       DRM_ERROR
+                           ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+                             k, i, narrays, count + 1);
+                       return DRM_ERR(EINVAL);
+               }
+               break;
 
+       case RADEON_3D_RNDR_GEN_INDX_PRIM:
+               if (dev_priv->microcode_version != UCODE_R100) {
+                       DRM_ERROR("Invalid 3d packet for r200-class chip\n");
+                       return DRM_ERR(EINVAL);
+               }
+               if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) {
+                               DRM_ERROR("Invalid rndr_gen_indx offset\n");
+                               return DRM_ERR(EINVAL);
+               }
+               break;
+
+       case RADEON_CP_INDX_BUFFER:
+               if (dev_priv->microcode_version != UCODE_R200) {
+                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+                       return DRM_ERR(EINVAL);
+               }
+               if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+                       DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+                       return DRM_ERR(EINVAL);
+               }
+               if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) {
+                       DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+                       return DRM_ERR(EINVAL);
+               }
+               break;
+
+       case RADEON_CNTL_HOSTDATA_BLT:
+       case RADEON_CNTL_PAINT_MULTI:
+       case RADEON_CNTL_BITBLT_MULTI:
+               /* MSB of opcode: next DWORD GUI_CNTL */
                if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
                              | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
                        offset = cmd[2] << 10;
@@ -282,6 +406,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                        }
                        cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
                }
+               break;
+
+       default:
+               DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+               return DRM_ERR(EINVAL);
        }
 
        return 0;
@@ -292,7 +421,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
  */
 
 static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-                                            drm_clip_rect_t * box)
+                                            struct drm_clip_rect * box)
 {
        RING_LOCALS;
 
@@ -555,7 +684,8 @@ static struct {
        {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
        {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
        {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
-       {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+       {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+        "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
        {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
        {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
        {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
@@ -569,7 +699,7 @@ static struct {
        {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
                    "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
        {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},    /* 61 */
-       {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"},    /* 62 */
+       {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
        {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
        {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
        {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
@@ -592,7 +722,7 @@ static struct {
        {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
        {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
        {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
-       {R200_PP_AFS_0, 32, "R200_PP_AFS_0"},   /* 85 */
+       {R200_PP_AFS_0, 32, "R200_PP_AFS_0"},     /* 85 */
        {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
        {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
        {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
@@ -601,6 +731,7 @@ static struct {
        {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
        {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
        {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+       {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
 };
 
 /* ================================================================
@@ -642,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
                 RADEON_GMC_SRC_DATATYPE_COLOR |
                 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
 
-       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
                OUT_RING(dev_priv->front_pitch_offset);
        } else {
                OUT_RING(dev_priv->back_pitch_offset);
@@ -721,7 +852,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        unsigned int flags = clear->flags;
        u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
        int i;
@@ -730,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
 
        dev_priv->stats.clears++;
 
-       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
                unsigned int tmp = flags;
 
                flags &= ~(RADEON_FRONT | RADEON_BACK);
@@ -835,7 +966,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                 */
                dev_priv->sarea_priv->ctx_owner = 0;
 
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (flags & RADEON_USE_HIERZ)) {
                        /* FIXME : reverse engineer that for Rx00 cards */
                        /* FIXME : the mask supposedly contains low-res z values. So can't set
@@ -880,7 +1011,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                for (i = 0; i < nbox; i++) {
                        int tileoffset, nrtilesx, nrtilesy, j;
                        /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
-                       if ((dev_priv->flags & CHIP_HAS_HIERZ)
+                       if ((dev_priv->flags & RADEON_HAS_HIERZ)
                            && !(dev_priv->microcode_version == UCODE_R200)) {
                                /* FIXME : figure this out for r200 (when hierz is enabled). Or
                                   maybe r200 actually doesn't need to put the low-res z value into
@@ -964,7 +1095,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                }
 
                /* TODO don't always clear all hi-level z tiles */
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (dev_priv->microcode_version == UCODE_R200)
                    && (flags & RADEON_USE_HIERZ))
                        /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
@@ -985,8 +1116,8 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
         * rendering a quad into just those buffers.  Thus, we have to
         * make sure the 3D engine is configured correctly.
         */
-       if ((dev_priv->microcode_version == UCODE_R200) &&
-           (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+       else if ((dev_priv->microcode_version == UCODE_R200) &&
+               (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
 
                int tempPP_CNTL;
                int tempRE_CNTL;
@@ -1209,7 +1340,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int i;
        RING_LOCALS;
        DRM_DEBUG("\n");
@@ -1236,9 +1367,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
 
                DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
 
-               BEGIN_RING(7);
+               BEGIN_RING(9);
 
-               OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
                OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
                         RADEON_GMC_DST_PITCH_OFFSET_CNTL |
                         RADEON_GMC_BRUSH_NONE |
@@ -1250,7 +1381,8 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
 
                /* Make this work even if front & back are flipped:
                 */
-               if (dev_priv->current_page == 0) {
+               OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
+               if (dev_priv->sarea_priv->pfCurrentPage == 0) {
                        OUT_RING(dev_priv->back_pitch_offset);
                        OUT_RING(dev_priv->front_pitch_offset);
                } else {
@@ -1258,6 +1390,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
                        OUT_RING(dev_priv->back_pitch_offset);
                }
 
+               OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
                OUT_RING((x << 16) | y);
                OUT_RING((x << 16) | y);
                OUT_RING((w << 16) | h);
@@ -1283,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
-       int offset = (dev_priv->current_page == 1)
+       int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
            ? dev_priv->front_offset : dev_priv->back_offset;
        RING_LOCALS;
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+       DRM_DEBUG("%s: pfCurrentPage=%d\n",
                  __FUNCTION__,
-                 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+                 dev_priv->sarea_priv->pfCurrentPage);
 
        /* Do some trivial performance monitoring...
         */
@@ -1316,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
         * performing the swapbuffer ioctl.
         */
        dev_priv->sarea_priv->last_frame++;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
-           1 - dev_priv->current_page;
+       dev_priv->sarea_priv->pfCurrentPage =
+               1 - dev_priv->sarea_priv->pfCurrentPage;
 
        BEGIN_RING(2);
 
@@ -1637,6 +1770,14 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
                dwords = size / 4;
 
+#define RADEON_COPY_MT(_buf, _data, _width) \
+       do { \
+               if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+                       DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
+                       return DRM_ERR(EFAULT); \
+               } \
+       } while(0)
+
                if (microtile) {
                        /* texture micro tiling in use, minimum texture width is thus 16 bytes.
                           however, we cannot use blitter directly for texture width < 64 bytes,
@@ -1648,46 +1789,19 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                           from user space. */
                        if (tex->height == 1) {
                                if (tex_width >= 64 || tex_width <= 16) {
-                                       if (DRM_COPY_FROM_USER(buffer, data,
-                                                              tex_width *
-                                                              sizeof(u32))) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer, data,
+                                               (int)(tex_width * sizeof(u32)));
                                } else if (tex_width == 32) {
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer, data, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer + 8, data + 16, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer, data, 16);
+                                       RADEON_COPY_MT(buffer + 8,
+                                                      data + 16, 16);
                                }
                        } else if (tex_width >= 64 || tex_width == 16) {
-                               if (DRM_COPY_FROM_USER(buffer, data,
-                                                      dwords * sizeof(u32))) {
-                                       DRM_ERROR("EFAULT on data, %d dwords\n",
-                                                 dwords);
-                                       return DRM_ERR(EFAULT);
-                               }
+                               RADEON_COPY_MT(buffer, data,
+                                              (int)(dwords * sizeof(u32)));
                        } else if (tex_width < 16) {
                                for (i = 0; i < tex->height; i++) {
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer, data, tex_width)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer, data, tex_width);
                                        buffer += 4;
                                        data += tex_width;
                                }
@@ -1695,37 +1809,13 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                                /* TODO: make sure this works when not fitting in one buffer
                                   (i.e. 32bytes x 2048...) */
                                for (i = 0; i < tex->height; i += 2) {
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer, data, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer, data, 16);
                                        data += 16;
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer + 8, data, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer + 8, data, 16);
                                        data += 16;
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer + 4, data, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer + 4, data, 16);
                                        data += 16;
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer + 12, data, 16)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer + 12, data, 16);
                                        data += 16;
                                        buffer += 16;
                                }
@@ -1735,31 +1825,22 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                                /* Texture image width is larger than the minimum, so we
                                 * can upload it directly.
                                 */
-                               if (DRM_COPY_FROM_USER(buffer, data,
-                                                      dwords * sizeof(u32))) {
-                                       DRM_ERROR("EFAULT on data, %d dwords\n",
-                                                 dwords);
-                                       return DRM_ERR(EFAULT);
-                               }
+                               RADEON_COPY_MT(buffer, data,
+                                              (int)(dwords * sizeof(u32)));
                        } else {
                                /* Texture image width is less than the minimum, so we
                                 * need to pad out each image scanline to the minimum
                                 * width.
                                 */
                                for (i = 0; i < tex->height; i++) {
-                                       if (DRM_COPY_FROM_USER
-                                           (buffer, data, tex_width)) {
-                                               DRM_ERROR
-                                                   ("EFAULT on pad, %d bytes\n",
-                                                    tex_width);
-                                               return DRM_ERR(EFAULT);
-                                       }
+                                       RADEON_COPY_MT(buffer, data, tex_width);
                                        buffer += 8;
                                        data += tex_width;
                                }
                        }
                }
 
+#undef RADEON_COPY_MT
                buf->filp = filp;
                buf->used = size;
                offset = dev_priv->gart_buffers_offset + buf->offset;
@@ -1821,7 +1902,7 @@ static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
 }
 
 static void radeon_apply_surface_regs(int surf_index,
-                                     drm_radeon_private_t * dev_priv)
+                                     drm_radeon_private_t *dev_priv)
 {
        if (!dev_priv->mmio)
                return;
@@ -1847,8 +1928,8 @@ static void radeon_apply_surface_regs(int surf_index,
  * freed, we suddenly need two surfaces to store A and C, which might
  * not always be available.
  */
-static int alloc_surface(drm_radeon_surface_alloc_t * new,
-                        drm_radeon_private_t * dev_priv, DRMFILE filp)
+static int alloc_surface(drm_radeon_surface_alloc_t *new,
+                        drm_radeon_private_t *dev_priv, DRMFILE filp)
 {
        struct radeon_virt_surface *s;
        int i;
@@ -1997,11 +2078,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS)
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_surface_alloc_t alloc;
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_COPY_FROM_USER_IOCTL(alloc,
                                 (drm_radeon_surface_alloc_t __user *) data,
                                 sizeof(alloc));
@@ -2018,12 +2094,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS)
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_surface_free_t memfree;
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
-       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data,
                                 sizeof(memfree));
 
        if (free_surface(filp, dev_priv, memfree.address))
@@ -2081,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
        ADVANCE_RING();
 
        dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
 
-       return 0;
-}
+       if (dev_priv->sarea_priv->pfCurrentPage != 1)
+               dev_priv->sarea_priv->pfCurrentPage = 0;
 
-/* Called whenever a client dies, from drm_release.
- * NOTE:  Lock isn't necessarily held when this is called!
- */
-static int radeon_do_cleanup_pageflip(drm_device_t * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       if (dev_priv->current_page != 0)
-               radeon_cp_dispatch_flip(dev);
-
-       dev_priv->page_flipping = 0;
        return 0;
 }
 
@@ -2242,11 +2299,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
        DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
@@ -2393,11 +2445,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_COPY_FROM_USER_IOCTL(indirect,
                                 (drm_radeon_indirect_t __user *) data,
                                 sizeof(indirect));
@@ -2470,11 +2517,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
        DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
@@ -2596,9 +2638,9 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
        return 0;
 }
 
-static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
                                          drm_radeon_cmd_header_t header,
-                                         drm_radeon_kcmd_buffer_t * cmdbuf)
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        int sz = header.scalars.count;
        int start = header.scalars.offset;
@@ -2618,9 +2660,9 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
 
 /* God this is ugly
  */
-static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
                                           drm_radeon_cmd_header_t header,
-                                          drm_radeon_kcmd_buffer_t * cmdbuf)
+                                          drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        int sz = header.scalars.count;
        int start = ((unsigned int)header.scalars.offset) + 0x100;
@@ -2638,16 +2680,17 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
        return 0;
 }
 
-static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
                                          drm_radeon_cmd_header_t header,
-                                         drm_radeon_kcmd_buffer_t * cmdbuf)
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        int sz = header.vectors.count;
        int start = header.vectors.offset;
        int stride = header.vectors.stride;
        RING_LOCALS;
 
-       BEGIN_RING(3 + sz);
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
        OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
@@ -2659,6 +2702,32 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
        return 0;
 }
 
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+                                         drm_radeon_cmd_header_t header,
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.veclinear.count * 4;
+       int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+       RING_LOCALS;
+
+        if (!sz)
+                return 0;
+        if (sz * 4 > cmdbuf->bufsz)
+                return DRM_ERR(EINVAL);
+
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+       OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
 static int radeon_emit_packet3(drm_device_t * dev,
                               drm_file_t * filp_priv,
                               drm_radeon_kcmd_buffer_t *cmdbuf)
@@ -2685,16 +2754,16 @@ static int radeon_emit_packet3(drm_device_t * dev,
        return 0;
 }
 
-static int radeon_emit_packet3_cliprect(drm_device_t * dev,
-                                       drm_file_t * filp_priv,
+static int radeon_emit_packet3_cliprect(drm_device_t *dev,
+                                       drm_file_t *filp_priv,
                                        drm_radeon_kcmd_buffer_t *cmdbuf,
                                        int orig_nbox)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t box;
+       struct drm_clip_rect box;
        unsigned int cmdsz;
        int ret;
-       drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+       struct drm_clip_rect __user *boxes = cmdbuf->boxes;
        int i = 0;
        RING_LOCALS;
 
@@ -2791,11 +2860,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 
        LOCK_TEST_WITH_RETURN(dev, filp);
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
        DRM_COPY_FROM_USER_IOCTL(cmdbuf,
@@ -2818,7 +2882,8 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
                if (kbuf == NULL)
                        return DRM_ERR(ENOMEM);
-               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) {
+               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf,
+                                      cmdbuf.bufsz)) {
                        drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
                        return DRM_ERR(EFAULT);
                }
@@ -2921,6 +2986,14 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                                goto err;
                        }
                        break;
+               case RADEON_CMD_VECLINEAR:
+                       DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+                       if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+                               DRM_ERROR("radeon_emit_veclinear failed\n");
+                               goto err;
+                       }
+                       break;
+
                default:
                        DRM_ERROR("bad cmd_type %d at %p\n",
                                  header.header.cmd_type,
@@ -2949,11 +3022,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
        drm_radeon_getparam_t param;
        int value;
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
                                 sizeof(param));
 
@@ -2981,7 +3049,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
                value = dev_priv->gart_vm_start;
                break;
        case RADEON_PARAM_REGISTER_HANDLE:
-               value = dev_priv->mmio_offset;
+               value = dev_priv->mmio->offset;
                break;
        case RADEON_PARAM_STATUS_HANDLE:
                value = dev_priv->ring_rptr_offset;
@@ -3004,7 +3072,24 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
        case RADEON_PARAM_GART_TEX_HANDLE:
                value = dev_priv->gart_textures_offset;
                break;
+       case RADEON_PARAM_SCRATCH_OFFSET:
+               if (!dev_priv->writeback_works)
+                       return DRM_ERR(EINVAL);
+               value = RADEON_SCRATCH_REG_OFFSET;
+               break;
+       case RADEON_PARAM_CARD_TYPE:
+               if (dev_priv->flags & RADEON_IS_PCIE)
+                       value = RADEON_CARD_PCIE;
+               else if (dev_priv->flags & RADEON_IS_AGP)
+                       value = RADEON_CARD_AGP;
+               else
+                       value = RADEON_CARD_PCI;
+               break;
+       case RADEON_PARAM_VBLANK_CRTC:
+               value = radeon_vblank_crtc_get(dev);
+               break;
        default:
+               DRM_DEBUG("Invalid parameter %d\n", param.param);
                return DRM_ERR(EINVAL);
        }
 
@@ -3024,11 +3109,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
        drm_radeon_setparam_t sp;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
        DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
        DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
@@ -3054,6 +3134,18 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
                break;
        case RADEON_SETPARAM_PCIGART_LOCATION:
                dev_priv->pcigart_offset = sp.value;
+               dev_priv->pcigart_offset_set = 1;
+               break;
+       case RADEON_SETPARAM_NEW_MEMMAP:
+               dev_priv->new_memmap = sp.value;
+               break;
+       case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
+               dev_priv->gart_info.table_size = sp.value;
+               if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
+                       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+               break;
+       case RADEON_SETPARAM_VBLANK_CRTC:
+               return radeon_vblank_crtc_set(dev, sp.value);
                break;
        default:
                DRM_DEBUG("Invalid parameter %d\n", sp.param);
@@ -3066,6 +3158,7 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
 /* When a client dies:
  *    - Check for and clean up flipped page state
  *    - Free any alloced GART memory.
+ *    - Free any alloced radeon surfaces.
  *
  * DRM infrastructure takes care of reclaiming dma buffers.
  */
@@ -3073,9 +3166,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
 {
        if (dev->dev_private) {
                drm_radeon_private_t *dev_priv = dev->dev_private;
-               if (dev_priv->page_flipping) {
-                       radeon_do_cleanup_pageflip(dev);
-               }
+               dev_priv->page_flipping = 0;
                radeon_mem_release(filp, dev_priv->gart_heap);
                radeon_mem_release(filp, dev_priv->fb_heap);
                radeon_surfaces_release(filp, dev_priv);
@@ -3084,6 +3175,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
 
 void radeon_driver_lastclose(drm_device_t * dev)
 {
+       if (dev->dev_private) {
+               drm_radeon_private_t *dev_priv = dev->dev_private;
+
+               if (dev_priv->sarea_priv &&
+                   dev_priv->sarea_priv->pfCurrentPage != 0)
+                       radeon_cp_dispatch_flip(dev);
+       }
+
        radeon_do_release(dev);
 }
 
@@ -3092,6 +3191,7 @@ int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
        drm_radeon_private_t *dev_priv = dev->dev_private;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
+       DRM_DEBUG("\n");
        radeon_priv =
            (struct drm_radeon_driver_file_fields *)
            drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
@@ -3100,6 +3200,7 @@ int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
                return -ENOMEM;
 
        filp_priv->driver_priv = radeon_priv;
+
        if (dev_priv)
                radeon_priv->radeon_fb_delta = dev_priv->fb_location;
        else
@@ -3116,33 +3217,33 @@ void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
 }
 
 drm_ioctl_desc_t radeon_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1},
-       [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0},
-       [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
+       [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH}
 };
 
 int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);