xref: /onnv-gate/usr/src/uts/intel/io/drm/radeon_state.c (revision 7053:56f8bd9583f3)
16393Scg149915 
26393Scg149915 /*
36393Scg149915  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
46393Scg149915  * Use is subject to license terms.
56393Scg149915  */
66393Scg149915 /* radeon_state.c -- State support for Radeon -*- linux-c -*- */
76393Scg149915 /*
86393Scg149915  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
96393Scg149915  * All Rights Reserved.
106393Scg149915  *
116393Scg149915  * Permission is hereby granted, free of charge, to any person obtaining a
126393Scg149915  * copy of this software and associated documentation files (the "Software"),
136393Scg149915  * to deal in the Software without restriction, including without limitation
146393Scg149915  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
156393Scg149915  * and/or sell copies of the Software, and to permit persons to whom the
166393Scg149915  * Software is furnished to do so, subject to the following conditions:
176393Scg149915  *
186393Scg149915  * The above copyright notice and this permission notice (including the next
196393Scg149915  * paragraph) shall be included in all copies or substantial portions of the
206393Scg149915  * Software.
216393Scg149915  *
226393Scg149915  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
236393Scg149915  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
246393Scg149915  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
256393Scg149915  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
266393Scg149915  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
276393Scg149915  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
286393Scg149915  * DEALINGS IN THE SOFTWARE.
296393Scg149915  *
306393Scg149915  * Authors:
316393Scg149915  *    Gareth Hughes <gareth@valinux.com>
326393Scg149915  *    Kevin E. Martin <martin@valinux.com>
336393Scg149915  */
346393Scg149915 
356393Scg149915 #pragma ident	"%Z%%M%	%I%	%E% SMI"
366393Scg149915 
376393Scg149915 #include "drmP.h"
386393Scg149915 #include "drm.h"
396393Scg149915 #include "drm_sarea.h"
406393Scg149915 #include "radeon_drm.h"
416393Scg149915 #include "radeon_drv.h"
426393Scg149915 #include "radeon_io32.h"
436393Scg149915 
446393Scg149915 /*
456393Scg149915  * Helper functions for client state checking and fixup
466393Scg149915  */
476393Scg149915 
486393Scg149915 static inline int
radeon_check_and_fixup_offset(drm_radeon_private_t * dev_priv,drm_file_t * filp_priv,u32 * offset)496393Scg149915 radeon_check_and_fixup_offset(drm_radeon_private_t *dev_priv,
506393Scg149915     drm_file_t *filp_priv, u32 *offset)
516393Scg149915 {
526393Scg149915 	u64 off = *offset;
536393Scg149915 	u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
546393Scg149915 	struct drm_radeon_driver_file_fields *radeon_priv;
556393Scg149915 
566393Scg149915 	/*
576393Scg149915 	 * Hrm ... the story of the offset ... So this function converts
586393Scg149915 	 * the various ideas of what userland clients might have for an
596393Scg149915 	 * offset in the card address space into an offset into the card
606393Scg149915 	 * address space :) So with a sane client, it should just keep
616393Scg149915 	 * the value intact and just do some boundary checking. However,
626393Scg149915 	 * not all clients are sane. Some older clients pass us 0 based
636393Scg149915 	 * offsets relative to the start of the framebuffer and some may
646393Scg149915 	 * assume the AGP aperture it appended to the framebuffer, so we
656393Scg149915 	 * try to detect those cases and fix them up.
666393Scg149915 	 *
676393Scg149915 	 * Note: It might be a good idea here to make sure the offset lands
686393Scg149915 	 * in some "allowed" area to protect things like the PCIE GART...
696393Scg149915 	 */
706393Scg149915 
716393Scg149915 	/*
726393Scg149915 	 * First, the best case, the offset already lands in either the
736393Scg149915 	 * framebuffer or the GART mapped space
746393Scg149915 	 */
756393Scg149915 
76*7053Shh224818 	if (RADEON_CHECK_OFFSET(dev_priv, off))
776393Scg149915 		return (0);
786393Scg149915 
796393Scg149915 	/*
806393Scg149915 	 * Ok, that didn't happen... now check if we have a zero based
816393Scg149915 	 * offset that fits in the framebuffer + gart space, apply the
826393Scg149915 	 * magic offset we get from SETPARAM or calculated from fb_location
836393Scg149915 	 */
846393Scg149915 	if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
856393Scg149915 		radeon_priv = filp_priv->driver_priv;
866393Scg149915 		off += radeon_priv->radeon_fb_delta;
876393Scg149915 	}
886393Scg149915 
896393Scg149915 	/* Finally, assume we aimed at a GART offset if beyond the fb */
906393Scg149915 	if (off > fb_end)
916393Scg149915 		off = off - fb_end - 1 + dev_priv->gart_vm_start;
926393Scg149915 
936393Scg149915 	/* Now recheck and fail if out of bounds */
94*7053Shh224818 	if (RADEON_CHECK_OFFSET(dev_priv, off)) {
956393Scg149915 		DRM_DEBUG("offset fixed up to 0x%x\n", off);
966393Scg149915 		*offset = (uint32_t)off;
976393Scg149915 		return (0);
986393Scg149915 	}
996393Scg149915 	return (EINVAL);
1006393Scg149915 }
1016393Scg149915 
1026393Scg149915 static inline int
radeon_check_and_fixup_packets(drm_radeon_private_t * dev_priv,drm_file_t * filp_priv,int id,u32 * data)1036393Scg149915 radeon_check_and_fixup_packets(drm_radeon_private_t *dev_priv,
1046393Scg149915     drm_file_t *filp_priv, int id, u32 *data)
1056393Scg149915 {
1066393Scg149915 	switch (id) {
1076393Scg149915 
1086393Scg149915 	case RADEON_EMIT_PP_MISC:
1096393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
1106393Scg149915 		    &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
1116393Scg149915 			DRM_ERROR("Invalid depth buffer offset\n");
1126393Scg149915 			return (EINVAL);
1136393Scg149915 		}
1146393Scg149915 		break;
1156393Scg149915 
1166393Scg149915 	case RADEON_EMIT_PP_CNTL:
1176393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
1186393Scg149915 		    &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
1196393Scg149915 			DRM_ERROR("Invalid colour buffer offset\n");
1206393Scg149915 			return (EINVAL);
1216393Scg149915 		}
1226393Scg149915 		break;
1236393Scg149915 
1246393Scg149915 	case R200_EMIT_PP_TXOFFSET_0:
1256393Scg149915 	case R200_EMIT_PP_TXOFFSET_1:
1266393Scg149915 	case R200_EMIT_PP_TXOFFSET_2:
1276393Scg149915 	case R200_EMIT_PP_TXOFFSET_3:
1286393Scg149915 	case R200_EMIT_PP_TXOFFSET_4:
1296393Scg149915 	case R200_EMIT_PP_TXOFFSET_5:
1306393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
1316393Scg149915 		    &data[0])) {
1326393Scg149915 			DRM_ERROR("Invalid R200 texture offset\n");
1336393Scg149915 			return (EINVAL);
1346393Scg149915 		}
1356393Scg149915 		break;
1366393Scg149915 
1376393Scg149915 	case RADEON_EMIT_PP_TXFILTER_0:
1386393Scg149915 	case RADEON_EMIT_PP_TXFILTER_1:
1396393Scg149915 	case RADEON_EMIT_PP_TXFILTER_2:
1406393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
1416393Scg149915 		    &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
1426393Scg149915 			DRM_ERROR("Invalid R100 texture offset\n");
1436393Scg149915 			return (EINVAL);
1446393Scg149915 		}
1456393Scg149915 		break;
1466393Scg149915 
1476393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_0:
1486393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_1:
1496393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_2:
1506393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_3:
1516393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_4:
1526393Scg149915 	case R200_EMIT_PP_CUBIC_OFFSETS_5: {
1536393Scg149915 			int i;
1546393Scg149915 			for (i = 0; i < 5; i++) {
1556393Scg149915 				if (radeon_check_and_fixup_offset(dev_priv,
1566393Scg149915 				    filp_priv, &data[i])) {
1576393Scg149915 					DRM_ERROR("Invalid R200 cubic"
1586393Scg149915 					    " texture offset\n");
1596393Scg149915 					return (EINVAL);
1606393Scg149915 				}
1616393Scg149915 			}
1626393Scg149915 			break;
1636393Scg149915 		}
1646393Scg149915 
1656393Scg149915 	case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
1666393Scg149915 	case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
1676393Scg149915 	case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:
1686393Scg149915 	{
1696393Scg149915 			int i;
1706393Scg149915 			for (i = 0; i < 5; i++) {
1716393Scg149915 				if (radeon_check_and_fixup_offset(dev_priv,
1726393Scg149915 				    filp_priv, &data[i])) {
1736393Scg149915 					DRM_ERROR("Invalid R100 cubic"
1746393Scg149915 					    " texture offset\n");
1756393Scg149915 					return (EINVAL);
1766393Scg149915 				}
1776393Scg149915 			}
1786393Scg149915 	}
1796393Scg149915 		break;
1806393Scg149915 
1816393Scg149915 	case R200_EMIT_VAP_CTL:
1826393Scg149915 	{
1836393Scg149915 		RING_LOCALS;
1846393Scg149915 		BEGIN_RING(2);
1856393Scg149915 		OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
1866393Scg149915 		ADVANCE_RING();
1876393Scg149915 	}
1886393Scg149915 		break;
1896393Scg149915 
1906393Scg149915 	case RADEON_EMIT_RB3D_COLORPITCH:
1916393Scg149915 	case RADEON_EMIT_RE_LINE_PATTERN:
1926393Scg149915 	case RADEON_EMIT_SE_LINE_WIDTH:
1936393Scg149915 	case RADEON_EMIT_PP_LUM_MATRIX:
1946393Scg149915 	case RADEON_EMIT_PP_ROT_MATRIX_0:
1956393Scg149915 	case RADEON_EMIT_RB3D_STENCILREFMASK:
1966393Scg149915 	case RADEON_EMIT_SE_VPORT_XSCALE:
1976393Scg149915 	case RADEON_EMIT_SE_CNTL:
1986393Scg149915 	case RADEON_EMIT_SE_CNTL_STATUS:
1996393Scg149915 	case RADEON_EMIT_RE_MISC:
2006393Scg149915 	case RADEON_EMIT_PP_BORDER_COLOR_0:
2016393Scg149915 	case RADEON_EMIT_PP_BORDER_COLOR_1:
2026393Scg149915 	case RADEON_EMIT_PP_BORDER_COLOR_2:
2036393Scg149915 	case RADEON_EMIT_SE_ZBIAS_FACTOR:
2046393Scg149915 	case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
2056393Scg149915 	case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
2066393Scg149915 	case R200_EMIT_PP_TXCBLEND_0:
2076393Scg149915 	case R200_EMIT_PP_TXCBLEND_1:
2086393Scg149915 	case R200_EMIT_PP_TXCBLEND_2:
2096393Scg149915 	case R200_EMIT_PP_TXCBLEND_3:
2106393Scg149915 	case R200_EMIT_PP_TXCBLEND_4:
2116393Scg149915 	case R200_EMIT_PP_TXCBLEND_5:
2126393Scg149915 	case R200_EMIT_PP_TXCBLEND_6:
2136393Scg149915 	case R200_EMIT_PP_TXCBLEND_7:
2146393Scg149915 	case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
2156393Scg149915 	case R200_EMIT_TFACTOR_0:
2166393Scg149915 	case R200_EMIT_VTX_FMT_0:
2176393Scg149915 	case R200_EMIT_MATRIX_SELECT_0:
2186393Scg149915 	case R200_EMIT_TEX_PROC_CTL_2:
2196393Scg149915 	case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
2206393Scg149915 	case R200_EMIT_PP_TXFILTER_0:
2216393Scg149915 	case R200_EMIT_PP_TXFILTER_1:
2226393Scg149915 	case R200_EMIT_PP_TXFILTER_2:
2236393Scg149915 	case R200_EMIT_PP_TXFILTER_3:
2246393Scg149915 	case R200_EMIT_PP_TXFILTER_4:
2256393Scg149915 	case R200_EMIT_PP_TXFILTER_5:
2266393Scg149915 	case R200_EMIT_VTE_CNTL:
2276393Scg149915 	case R200_EMIT_OUTPUT_VTX_COMP_SEL:
2286393Scg149915 	case R200_EMIT_PP_TAM_DEBUG3:
2296393Scg149915 	case R200_EMIT_PP_CNTL_X:
2306393Scg149915 	case R200_EMIT_RB3D_DEPTHXY_OFFSET:
2316393Scg149915 	case R200_EMIT_RE_AUX_SCISSOR_CNTL:
2326393Scg149915 	case R200_EMIT_RE_SCISSOR_TL_0:
2336393Scg149915 	case R200_EMIT_RE_SCISSOR_TL_1:
2346393Scg149915 	case R200_EMIT_RE_SCISSOR_TL_2:
2356393Scg149915 	case R200_EMIT_SE_VAP_CNTL_STATUS:
2366393Scg149915 	case R200_EMIT_SE_VTX_STATE_CNTL:
2376393Scg149915 	case R200_EMIT_RE_POINTSIZE:
2386393Scg149915 	case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
2396393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_0:
2406393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_1:
2416393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_2:
2426393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_3:
2436393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_4:
2446393Scg149915 	case R200_EMIT_PP_CUBIC_FACES_5:
2456393Scg149915 	case RADEON_EMIT_PP_TEX_SIZE_0:
2466393Scg149915 	case RADEON_EMIT_PP_TEX_SIZE_1:
2476393Scg149915 	case RADEON_EMIT_PP_TEX_SIZE_2:
2486393Scg149915 	case R200_EMIT_RB3D_BLENDCOLOR:
2496393Scg149915 	case R200_EMIT_TCL_POINT_SPRITE_CNTL:
2506393Scg149915 	case RADEON_EMIT_PP_CUBIC_FACES_0:
2516393Scg149915 	case RADEON_EMIT_PP_CUBIC_FACES_1:
2526393Scg149915 	case RADEON_EMIT_PP_CUBIC_FACES_2:
2536393Scg149915 	case R200_EMIT_PP_TRI_PERF_CNTL:
2546393Scg149915 	case R200_EMIT_PP_AFS_0:
2556393Scg149915 	case R200_EMIT_PP_AFS_1:
2566393Scg149915 	case R200_EMIT_ATF_TFACTOR:
2576393Scg149915 	case R200_EMIT_PP_TXCTLALL_0:
2586393Scg149915 	case R200_EMIT_PP_TXCTLALL_1:
2596393Scg149915 	case R200_EMIT_PP_TXCTLALL_2:
2606393Scg149915 	case R200_EMIT_PP_TXCTLALL_3:
2616393Scg149915 	case R200_EMIT_PP_TXCTLALL_4:
2626393Scg149915 	case R200_EMIT_PP_TXCTLALL_5:
2636393Scg149915 	case R200_EMIT_VAP_PVS_CNTL:
2646393Scg149915 		/* These packets don't contain memory offsets */
2656393Scg149915 		break;
2666393Scg149915 
2676393Scg149915 	default:
2686393Scg149915 		DRM_ERROR("Unknown state packet ID %d\n", id);
2696393Scg149915 		return (EINVAL);
2706393Scg149915 	}
2716393Scg149915 
2726393Scg149915 	return (0);
2736393Scg149915 }
2746393Scg149915 
2756393Scg149915 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,unsigned int * cmdsz)2766393Scg149915 radeon_check_and_fixup_packet3(drm_radeon_private_t *dev_priv,
2776393Scg149915     drm_file_t *filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf,
2786393Scg149915     unsigned int *cmdsz)
2796393Scg149915 {
2806393Scg149915 	u32 *cmd = (u32 *)(uintptr_t)cmdbuf->buf;
2816393Scg149915 	u32 offset, narrays;
2826393Scg149915 	int count, i, k;
2836393Scg149915 
2846393Scg149915 	*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
2856393Scg149915 
2866393Scg149915 	if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
2876393Scg149915 		DRM_ERROR("Not a type 3 packet\n");
2886393Scg149915 		return (EINVAL);
2896393Scg149915 	}
2906393Scg149915 
2916393Scg149915 	if (4 * *cmdsz > cmdbuf->bufsz) {
2926393Scg149915 		DRM_ERROR("Packet size larger than size of data provided\n");
2936393Scg149915 		return (EINVAL);
2946393Scg149915 	}
2956393Scg149915 
2966393Scg149915 
2976393Scg149915 	switch (cmd[0] & 0xff00) {
2986393Scg149915 	/* XXX Are there old drivers needing other packets? */
2996393Scg149915 
3006393Scg149915 	case RADEON_3D_DRAW_IMMD:
3016393Scg149915 	case RADEON_3D_DRAW_VBUF:
3026393Scg149915 	case RADEON_3D_DRAW_INDX:
3036393Scg149915 	case RADEON_WAIT_FOR_IDLE:
3046393Scg149915 	case RADEON_CP_NOP:
3056393Scg149915 	case RADEON_3D_CLEAR_ZMASK:
3066393Scg149915 #if 0
3076393Scg149915 	case RADEON_CP_NEXT_CHAR:
3086393Scg149915 	case RADEON_CP_PLY_NEXTSCAN:
3096393Scg149915 	case RADEON_CP_SET_SCISSORS:
3106393Scg149915 	/* probably safe but will never need them? */
3116393Scg149915 #endif
3126393Scg149915 /* these packets are safe */
3136393Scg149915 		break;
3146393Scg149915 
3156393Scg149915 	case RADEON_CP_3D_DRAW_IMMD_2:
3166393Scg149915 	case RADEON_CP_3D_DRAW_VBUF_2:
3176393Scg149915 	case RADEON_CP_3D_DRAW_INDX_2:
3186393Scg149915 	case RADEON_3D_CLEAR_HIZ:
3196393Scg149915 		/* safe but r200 only */
3206393Scg149915 		if (dev_priv->microcode_version != UCODE_R200) {
3216393Scg149915 			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
3226393Scg149915 			return (EINVAL);
3236393Scg149915 		}
3246393Scg149915 		break;
3256393Scg149915 
3266393Scg149915 	case RADEON_3D_LOAD_VBPNTR:
3276393Scg149915 		count = (cmd[0] >> 16) & 0x3fff;
3286393Scg149915 
3296393Scg149915 		if (count > 18) { /* 12 arrays max */
3306393Scg149915 			DRM_ERROR(
3316393Scg149915 			    "Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
3326393Scg149915 			    count);
3336393Scg149915 			return (EINVAL);
3346393Scg149915 		}
3356393Scg149915 
3366393Scg149915 		/* carefully check packet contents */
3376393Scg149915 		narrays = cmd[1] & ~0xc000;
3386393Scg149915 		k = 0;
3396393Scg149915 		i = 2;
3406393Scg149915 		while ((k < narrays) && (i < (count + 2))) {
3416393Scg149915 			i++;		/* skip attribute field */
3426393Scg149915 			if (radeon_check_and_fixup_offset(dev_priv,
3436393Scg149915 			    filp_priv, &cmd[i])) {
3446393Scg149915 				DRM_ERROR(
3456393Scg149915 				    "Invalid offset (k=%d i=%d) ini"
3466393Scg149915 				    " 3D_LOAD_VBPNTR packet.\n", k, i);
3476393Scg149915 				return (EINVAL);
3486393Scg149915 			}
3496393Scg149915 			k++;
3506393Scg149915 			i++;
3516393Scg149915 			if (k == narrays)
3526393Scg149915 				break;
3536393Scg149915 			/* have one more to process, they come in pairs */
3546393Scg149915 			if (radeon_check_and_fixup_offset(dev_priv,
3556393Scg149915 			    filp_priv, &cmd[i])) {
3566393Scg149915 				DRM_ERROR(
3576393Scg149915 				    "Invalid offset (k=%d i=%d) in"
3586393Scg149915 				    " 3D_LOAD_VBPNTR packet.\n", k, i);
3596393Scg149915 				return (EINVAL);
3606393Scg149915 			}
3616393Scg149915 			k++;
3626393Scg149915 			i++;
3636393Scg149915 		}
3646393Scg149915 		/* do the counts match what we expect ? */
3656393Scg149915 		if ((k != narrays) || (i != (count + 2))) {
3666393Scg149915 			DRM_ERROR(
3676393Scg149915 			    "Malformed 3D_LOAD_VBPNTR packet"
3686393Scg149915 			    "(k=%d i=%d narrays=%d count+1=%d).\n",
3696393Scg149915 			    k, i, narrays, count + 1);
3706393Scg149915 			return (EINVAL);
3716393Scg149915 		}
3726393Scg149915 		break;
3736393Scg149915 
3746393Scg149915 	case RADEON_3D_RNDR_GEN_INDX_PRIM:
3756393Scg149915 		if (dev_priv->microcode_version != UCODE_R100) {
3766393Scg149915 			DRM_ERROR("Invalid 3d packet for r200-class chip\n");
3776393Scg149915 			return (EINVAL);
3786393Scg149915 		}
3796393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv,
3806393Scg149915 		    filp_priv, &cmd[1])) {
3816393Scg149915 				DRM_ERROR("Invalid rndr_gen_indx offset\n");
3826393Scg149915 				return (EINVAL);
3836393Scg149915 		}
3846393Scg149915 		break;
3856393Scg149915 
3866393Scg149915 	case RADEON_CP_INDX_BUFFER:
3876393Scg149915 		if (dev_priv->microcode_version != UCODE_R200) {
3886393Scg149915 			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
3896393Scg149915 			return (EINVAL);
3906393Scg149915 		}
3916393Scg149915 		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
3926393Scg149915 			DRM_ERROR(
3936393Scg149915 			    "Invalid indx_buffer reg address %08X\n", cmd[1]);
3946393Scg149915 			return (EINVAL);
3956393Scg149915 		}
3966393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv,
3976393Scg149915 		    filp_priv, &cmd[2])) {
3986393Scg149915 			DRM_ERROR(
3996393Scg149915 			    "Invalid indx_buffer offset is %08X\n", cmd[2]);
4006393Scg149915 			return (EINVAL);
4016393Scg149915 		}
4026393Scg149915 		break;
4036393Scg149915 
4046393Scg149915 	case RADEON_CNTL_HOSTDATA_BLT:
4056393Scg149915 	case RADEON_CNTL_PAINT_MULTI:
4066393Scg149915 	case RADEON_CNTL_BITBLT_MULTI:
4076393Scg149915 		/* MSB of opcode: next DWORD GUI_CNTL */
4086393Scg149915 		if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
4096393Scg149915 		    RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
4106393Scg149915 			offset = cmd[2] << 10;
4116393Scg149915 			if (radeon_check_and_fixup_offset
4126393Scg149915 			    (dev_priv, filp_priv, &offset)) {
4136393Scg149915 				DRM_ERROR("Invalid first packet offset\n");
4146393Scg149915 				return (EINVAL);
4156393Scg149915 			}
4166393Scg149915 			cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
4176393Scg149915 		}
4186393Scg149915 
4196393Scg149915 		if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
4206393Scg149915 		    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
4216393Scg149915 			offset = cmd[3] << 10;
4226393Scg149915 			if (radeon_check_and_fixup_offset
4236393Scg149915 			    (dev_priv, filp_priv, &offset)) {
4246393Scg149915 				DRM_ERROR("Invalid second packet offset\n");
4256393Scg149915 				return (EINVAL);
4266393Scg149915 			}
4276393Scg149915 			cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
4286393Scg149915 		}
4296393Scg149915 		break;
4306393Scg149915 
4316393Scg149915 	default:
4326393Scg149915 		DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
4336393Scg149915 		return (EINVAL);
4346393Scg149915 	}
4356393Scg149915 
4366393Scg149915 	return (0);
4376393Scg149915 }
4386393Scg149915 
4396393Scg149915 /*
4406393Scg149915  * CP hardware state programming functions
4416393Scg149915  */
4426393Scg149915 
radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,drm_clip_rect_t * box)4436393Scg149915 static inline void radeon_emit_clip_rect(drm_radeon_private_t *dev_priv,
4446393Scg149915     drm_clip_rect_t *box)
4456393Scg149915 {
4466393Scg149915 	RING_LOCALS;
4476393Scg149915 
4486393Scg149915 	DRM_DEBUG("   box:  x1=%d y1=%d  x2=%d y2=%d\n",
4496393Scg149915 	    box->x1, box->y1, box->x2, box->y2);
4506393Scg149915 
4516393Scg149915 	BEGIN_RING(4);
4526393Scg149915 	OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
4536393Scg149915 	OUT_RING((box->y1 << 16) | box->x1);
4546393Scg149915 	OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
4556393Scg149915 	OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
4566393Scg149915 	ADVANCE_RING();
4576393Scg149915 }
4586393Scg149915 
4596393Scg149915 /* Emit 1.1 state */
radeon_emit_state(drm_radeon_private_t * dev_priv,drm_file_t * filp_priv,drm_radeon_context_regs_t * ctx,drm_radeon_texture_regs_t * tex,unsigned int dirty)4606393Scg149915 static int radeon_emit_state(drm_radeon_private_t *dev_priv,
4616393Scg149915     drm_file_t *filp_priv, drm_radeon_context_regs_t *ctx,
4626393Scg149915     drm_radeon_texture_regs_t *tex, unsigned int dirty)
4636393Scg149915 {
4646393Scg149915 	RING_LOCALS;
4656393Scg149915 	DRM_DEBUG("dirty=0x%08x\n", dirty);
4666393Scg149915 
4676393Scg149915 	if (dirty & RADEON_UPLOAD_CONTEXT) {
4686393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
4696393Scg149915 		    &ctx->rb3d_depthoffset)) {
4706393Scg149915 			DRM_ERROR("Invalid depth buffer offset\n");
4716393Scg149915 			return (EINVAL);
4726393Scg149915 		}
4736393Scg149915 
4746393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
4756393Scg149915 		    &ctx->rb3d_coloroffset)) {
4766393Scg149915 			DRM_ERROR("Invalid depth buffer offset\n");
4776393Scg149915 			return (EINVAL);
4786393Scg149915 		}
4796393Scg149915 
4806393Scg149915 		BEGIN_RING(14);
4816393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
4826393Scg149915 		OUT_RING(ctx->pp_misc);
4836393Scg149915 		OUT_RING(ctx->pp_fog_color);
4846393Scg149915 		OUT_RING(ctx->re_solid_color);
4856393Scg149915 		OUT_RING(ctx->rb3d_blendcntl);
4866393Scg149915 		OUT_RING(ctx->rb3d_depthoffset);
4876393Scg149915 		OUT_RING(ctx->rb3d_depthpitch);
4886393Scg149915 		OUT_RING(ctx->rb3d_zstencilcntl);
4896393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
4906393Scg149915 		OUT_RING(ctx->pp_cntl);
4916393Scg149915 		OUT_RING(ctx->rb3d_cntl);
4926393Scg149915 		OUT_RING(ctx->rb3d_coloroffset);
4936393Scg149915 		OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
4946393Scg149915 		OUT_RING(ctx->rb3d_colorpitch);
4956393Scg149915 		ADVANCE_RING();
4966393Scg149915 	}
4976393Scg149915 
4986393Scg149915 	if (dirty & RADEON_UPLOAD_VERTFMT) {
4996393Scg149915 		BEGIN_RING(2);
5006393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
5016393Scg149915 		OUT_RING(ctx->se_coord_fmt);
5026393Scg149915 		ADVANCE_RING();
5036393Scg149915 	}
5046393Scg149915 
5056393Scg149915 	if (dirty & RADEON_UPLOAD_LINE) {
5066393Scg149915 		BEGIN_RING(5);
5076393Scg149915 		OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
5086393Scg149915 		OUT_RING(ctx->re_line_pattern);
5096393Scg149915 		OUT_RING(ctx->re_line_state);
5106393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
5116393Scg149915 		OUT_RING(ctx->se_line_width);
5126393Scg149915 		ADVANCE_RING();
5136393Scg149915 	}
5146393Scg149915 
5156393Scg149915 	if (dirty & RADEON_UPLOAD_BUMPMAP) {
5166393Scg149915 		BEGIN_RING(5);
5176393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
5186393Scg149915 		OUT_RING(ctx->pp_lum_matrix);
5196393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
5206393Scg149915 		OUT_RING(ctx->pp_rot_matrix_0);
5216393Scg149915 		OUT_RING(ctx->pp_rot_matrix_1);
5226393Scg149915 		ADVANCE_RING();
5236393Scg149915 	}
5246393Scg149915 
5256393Scg149915 	if (dirty & RADEON_UPLOAD_MASKS) {
5266393Scg149915 		BEGIN_RING(4);
5276393Scg149915 		OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
5286393Scg149915 		OUT_RING(ctx->rb3d_stencilrefmask);
5296393Scg149915 		OUT_RING(ctx->rb3d_ropcntl);
5306393Scg149915 		OUT_RING(ctx->rb3d_planemask);
5316393Scg149915 		ADVANCE_RING();
5326393Scg149915 	}
5336393Scg149915 
5346393Scg149915 	if (dirty & RADEON_UPLOAD_VIEWPORT) {
5356393Scg149915 		BEGIN_RING(7);
5366393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
5376393Scg149915 		OUT_RING(ctx->se_vport_xscale);
5386393Scg149915 		OUT_RING(ctx->se_vport_xoffset);
5396393Scg149915 		OUT_RING(ctx->se_vport_yscale);
5406393Scg149915 		OUT_RING(ctx->se_vport_yoffset);
5416393Scg149915 		OUT_RING(ctx->se_vport_zscale);
5426393Scg149915 		OUT_RING(ctx->se_vport_zoffset);
5436393Scg149915 		ADVANCE_RING();
5446393Scg149915 	}
5456393Scg149915 
5466393Scg149915 	if (dirty & RADEON_UPLOAD_SETUP) {
5476393Scg149915 		BEGIN_RING(4);
5486393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
5496393Scg149915 		OUT_RING(ctx->se_cntl);
5506393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
5516393Scg149915 		OUT_RING(ctx->se_cntl_status);
5526393Scg149915 		ADVANCE_RING();
5536393Scg149915 	}
5546393Scg149915 
5556393Scg149915 	if (dirty & RADEON_UPLOAD_MISC) {
5566393Scg149915 		BEGIN_RING(2);
5576393Scg149915 		OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
5586393Scg149915 		OUT_RING(ctx->re_misc);
5596393Scg149915 		ADVANCE_RING();
5606393Scg149915 	}
5616393Scg149915 
5626393Scg149915 	if (dirty & RADEON_UPLOAD_TEX0) {
5636393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv,
5646393Scg149915 		    filp_priv, &tex[0].pp_txoffset)) {
5656393Scg149915 			DRM_ERROR("Invalid texture offset for unit 0\n");
5666393Scg149915 			return (EINVAL);
5676393Scg149915 		}
5686393Scg149915 
5696393Scg149915 		BEGIN_RING(9);
5706393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
5716393Scg149915 		OUT_RING(tex[0].pp_txfilter);
5726393Scg149915 		OUT_RING(tex[0].pp_txformat);
5736393Scg149915 		OUT_RING(tex[0].pp_txoffset);
5746393Scg149915 		OUT_RING(tex[0].pp_txcblend);
5756393Scg149915 		OUT_RING(tex[0].pp_txablend);
5766393Scg149915 		OUT_RING(tex[0].pp_tfactor);
5776393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
5786393Scg149915 		OUT_RING(tex[0].pp_border_color);
5796393Scg149915 		ADVANCE_RING();
5806393Scg149915 	}
5816393Scg149915 
5826393Scg149915 	if (dirty & RADEON_UPLOAD_TEX1) {
5836393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv,
5846393Scg149915 		    filp_priv, &tex[1].pp_txoffset)) {
5856393Scg149915 			DRM_ERROR("Invalid texture offset for unit 1\n");
5866393Scg149915 			return (EINVAL);
5876393Scg149915 		}
5886393Scg149915 
5896393Scg149915 		BEGIN_RING(9);
5906393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
5916393Scg149915 		OUT_RING(tex[1].pp_txfilter);
5926393Scg149915 		OUT_RING(tex[1].pp_txformat);
5936393Scg149915 		OUT_RING(tex[1].pp_txoffset);
5946393Scg149915 		OUT_RING(tex[1].pp_txcblend);
5956393Scg149915 		OUT_RING(tex[1].pp_txablend);
5966393Scg149915 		OUT_RING(tex[1].pp_tfactor);
5976393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
5986393Scg149915 		OUT_RING(tex[1].pp_border_color);
5996393Scg149915 		ADVANCE_RING();
6006393Scg149915 	}
6016393Scg149915 
6026393Scg149915 	if (dirty & RADEON_UPLOAD_TEX2) {
6036393Scg149915 		if (radeon_check_and_fixup_offset(dev_priv,
6046393Scg149915 		    filp_priv, &tex[2].pp_txoffset)) {
6056393Scg149915 			DRM_ERROR("Invalid texture offset for unit 2\n");
6066393Scg149915 			return (EINVAL);
6076393Scg149915 		}
6086393Scg149915 
6096393Scg149915 		BEGIN_RING(9);
6106393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
6116393Scg149915 		OUT_RING(tex[2].pp_txfilter);
6126393Scg149915 		OUT_RING(tex[2].pp_txformat);
6136393Scg149915 		OUT_RING(tex[2].pp_txoffset);
6146393Scg149915 		OUT_RING(tex[2].pp_txcblend);
6156393Scg149915 		OUT_RING(tex[2].pp_txablend);
6166393Scg149915 		OUT_RING(tex[2].pp_tfactor);
6176393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
6186393Scg149915 		OUT_RING(tex[2].pp_border_color);
6196393Scg149915 		ADVANCE_RING();
6206393Scg149915 	}
6216393Scg149915 
6226393Scg149915 	return (0);
6236393Scg149915 }
6246393Scg149915 
6256393Scg149915 /* Emit 1.2 state */
radeon_emit_state2(drm_radeon_private_t * dev_priv,drm_file_t * filp_priv,drm_radeon_state_t * state)6266393Scg149915 static int radeon_emit_state2(drm_radeon_private_t *dev_priv,
6276393Scg149915     drm_file_t *filp_priv, drm_radeon_state_t *state)
6286393Scg149915 {
6296393Scg149915 	RING_LOCALS;
6306393Scg149915 
6316393Scg149915 	if (state->dirty & RADEON_UPLOAD_ZBIAS) {
6326393Scg149915 		BEGIN_RING(3);
6336393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
6346393Scg149915 		OUT_RING(state->context2.se_zbias_factor);
6356393Scg149915 		OUT_RING(state->context2.se_zbias_constant);
6366393Scg149915 		ADVANCE_RING();
6376393Scg149915 	}
6386393Scg149915 
6396393Scg149915 	return (radeon_emit_state(dev_priv, filp_priv,
6406393Scg149915 	    &state->context, state->tex, state->dirty));
6416393Scg149915 }
6426393Scg149915 
6436393Scg149915 /*
6446393Scg149915  * New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
6456393Scg149915  * 1.3 cmdbuffers allow all previous state to be updated as well as
6466393Scg149915  * the tcl scalar and vector areas.
6476393Scg149915  */
6486393Scg149915 static struct {
6496393Scg149915 	int start;
6506393Scg149915 	int len;
6516393Scg149915 	const char *name;
6526393Scg149915 } packet[RADEON_MAX_STATE_PACKETS] = {
6536393Scg149915 	{RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
6546393Scg149915 	{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
6556393Scg149915 	{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
6566393Scg149915 	{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
6576393Scg149915 	{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
6586393Scg149915 	{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
6596393Scg149915 	{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
6606393Scg149915 	{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
6616393Scg149915 	{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
6626393Scg149915 	{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
6636393Scg149915 	{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
6646393Scg149915 	{RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
6656393Scg149915 	{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
6666393Scg149915 	{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
6676393Scg149915 	{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
6686393Scg149915 	{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
6696393Scg149915 	{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
6706393Scg149915 	{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
6716393Scg149915 	{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
6726393Scg149915 	{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
6736393Scg149915 	{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
6746393Scg149915 		    "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
6756393Scg149915 	{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
6766393Scg149915 	{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
6776393Scg149915 	{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
6786393Scg149915 	{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
6796393Scg149915 	{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
6806393Scg149915 	{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
6816393Scg149915 	{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
6826393Scg149915 	{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
6836393Scg149915 	{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
6846393Scg149915 	{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
6856393Scg149915 	{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
6866393Scg149915 	{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
6876393Scg149915 	{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
6886393Scg149915 	{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
6896393Scg149915 	{R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
6906393Scg149915 	{R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
6916393Scg149915 	{R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
6926393Scg149915 	{R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
6936393Scg149915 	{R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
6946393Scg149915 	{R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
6956393Scg149915 	{R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
6966393Scg149915 	{R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
6976393Scg149915 	{R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
6986393Scg149915 	{R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
6996393Scg149915 	{R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
7006393Scg149915 	{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
7016393Scg149915 	{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
7026393Scg149915 	{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
7036393Scg149915 	{R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
7046393Scg149915 	"R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
7056393Scg149915 	{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
7066393Scg149915 	{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
7076393Scg149915 	{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
7086393Scg149915 	{R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
7096393Scg149915 	{R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
7106393Scg149915 	{R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
7116393Scg149915 	{R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
7126393Scg149915 	{R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
7136393Scg149915 	{R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
7146393Scg149915 	{R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
7156393Scg149915 	{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
7166393Scg149915 		    "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
7176393Scg149915 	{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},	/* 61 */
7186393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
7196393Scg149915 	{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
7206393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
7216393Scg149915 	{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
7226393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
7236393Scg149915 	{R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
7246393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
7256393Scg149915 	{R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
7266393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
7276393Scg149915 	{R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
7286393Scg149915 	{R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
7296393Scg149915 	{RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
7306393Scg149915 	{RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
7316393Scg149915 	{RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
7326393Scg149915 	{R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
7336393Scg149915 	{R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
7346393Scg149915 	{RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
7356393Scg149915 	{RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
7366393Scg149915 	{RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
7376393Scg149915 	{RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
7386393Scg149915 	{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
7396393Scg149915 	{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
7406393Scg149915 	{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
7416393Scg149915 	{R200_PP_AFS_0, 32, "R200_PP_AFS_0"},	/* 85 */
7426393Scg149915 	{R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
7436393Scg149915 	{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
7446393Scg149915 	{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
7456393Scg149915 	{R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
7466393Scg149915 	{R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
7476393Scg149915 	{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
7486393Scg149915 	{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
7496393Scg149915 	{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
7506393Scg149915 	{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
7516393Scg149915 };
7526393Scg149915 
7536393Scg149915 /*
7546393Scg149915  * Performance monitoring functions
7556393Scg149915  */
7566393Scg149915 
radeon_clear_box(drm_radeon_private_t * dev_priv,int x,int y,int w,int h,int r,int g,int b)7576393Scg149915 static void radeon_clear_box(drm_radeon_private_t *dev_priv,
7586393Scg149915     int x, int y, int w, int h, int r, int g, int b)
7596393Scg149915 {
7606393Scg149915 	u32 color;
7616393Scg149915 	RING_LOCALS;
7626393Scg149915 
7636393Scg149915 	x += dev_priv->sarea_priv->boxes[0].x1;
7646393Scg149915 	y += dev_priv->sarea_priv->boxes[0].y1;
7656393Scg149915 
7666393Scg149915 	switch (dev_priv->color_fmt) {
7676393Scg149915 	case RADEON_COLOR_FORMAT_RGB565:
7686393Scg149915 		color = (((r & 0xf8) << 8) |
7696393Scg149915 		    ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
7706393Scg149915 		break;
7716393Scg149915 	case RADEON_COLOR_FORMAT_ARGB8888:
7726393Scg149915 	default:
7736393Scg149915 		color = (((0xfful) << 24) | (r << 16) | (g << 8) | b);
7746393Scg149915 		break;
7756393Scg149915 	}
7766393Scg149915 
7776393Scg149915 	BEGIN_RING(4);
7786393Scg149915 	RADEON_WAIT_UNTIL_3D_IDLE();
7796393Scg149915 	OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
7806393Scg149915 	OUT_RING(0xffffffff);
7816393Scg149915 	ADVANCE_RING();
7826393Scg149915 
7836393Scg149915 	BEGIN_RING(6);
7846393Scg149915 
7856393Scg149915 	OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
7866393Scg149915 	OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
7876393Scg149915 	    RADEON_GMC_BRUSH_SOLID_COLOR |
7886393Scg149915 	    (dev_priv->color_fmt << 8) |
7896393Scg149915 	    RADEON_GMC_SRC_DATATYPE_COLOR |
7906393Scg149915 	    RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
7916393Scg149915 
7926393Scg149915 	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
7936393Scg149915 		OUT_RING(dev_priv->front_pitch_offset);
7946393Scg149915 	} else {
7956393Scg149915 		OUT_RING(dev_priv->back_pitch_offset);
7966393Scg149915 	}
7976393Scg149915 
7986393Scg149915 	OUT_RING(color);
7996393Scg149915 
8006393Scg149915 	OUT_RING((x << 16) | y);
8016393Scg149915 	OUT_RING((w << 16) | h);
8026393Scg149915 
8036393Scg149915 	ADVANCE_RING();
8046393Scg149915 }
8056393Scg149915 
radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)8066393Scg149915 static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv)
8076393Scg149915 {
8086393Scg149915 	/*
8096393Scg149915 	 * Collapse various things into a wait flag -- trying to
8106393Scg149915 	 * guess if userspase slept -- better just to have them tell us.
8116393Scg149915 	 */
8126393Scg149915 	if (dev_priv->stats.last_frame_reads > 1 ||
8136393Scg149915 	    dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
8146393Scg149915 		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
8156393Scg149915 	}
8166393Scg149915 
8176393Scg149915 	if (dev_priv->stats.freelist_loops) {
8186393Scg149915 		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
8196393Scg149915 	}
8206393Scg149915 
8216393Scg149915 	/* Purple box for page flipping */
8226393Scg149915 	if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
8236393Scg149915 		radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
8246393Scg149915 
8256393Scg149915 	/* Red box if we have to wait for idle at any point */
8266393Scg149915 	if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
8276393Scg149915 		radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
8286393Scg149915 
8296393Scg149915 	/* Blue box: lost context? */
8306393Scg149915 
8316393Scg149915 	/* Yellow box for texture swaps */
8326393Scg149915 	if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
8336393Scg149915 		radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
8346393Scg149915 
8356393Scg149915 	/* Green box if hardware never idles (as far as we can tell) */
8366393Scg149915 	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
8376393Scg149915 		radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
8386393Scg149915 
8396393Scg149915 	/*
8406393Scg149915 	 * Draw bars indicating number of buffers allocated
8416393Scg149915 	 * (not a great measure, easily confused)
8426393Scg149915 	 */
8436393Scg149915 	if (dev_priv->stats.requested_bufs) {
8446393Scg149915 		if (dev_priv->stats.requested_bufs > 100)
8456393Scg149915 			dev_priv->stats.requested_bufs = 100;
8466393Scg149915 
8476393Scg149915 		radeon_clear_box(dev_priv, 4, 16,
8486393Scg149915 		    dev_priv->stats.requested_bufs, 4, 196, 128, 128);
8496393Scg149915 	}
8506393Scg149915 
8516393Scg149915 	(void) memset(&dev_priv->stats, 0, sizeof (dev_priv->stats));
8526393Scg149915 
8536393Scg149915 }
8546393Scg149915 
8556393Scg149915 /*
8566393Scg149915  * CP command dispatch functions
8576393Scg149915  */
8586393Scg149915 
radeon_cp_dispatch_clear(drm_device_t * dev,drm_radeon_clear_t * clear,drm_radeon_clear_rect_t * depth_boxes)8596393Scg149915 static void radeon_cp_dispatch_clear(drm_device_t *dev,
8606393Scg149915     drm_radeon_clear_t *clear, drm_radeon_clear_rect_t *depth_boxes)
8616393Scg149915 {
8626393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
8636393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
8646393Scg149915 	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
8656393Scg149915 	int nbox = sarea_priv->nbox;
8666393Scg149915 	drm_clip_rect_t *pbox = sarea_priv->boxes;
8676393Scg149915 	unsigned int flags = clear->flags;
8686393Scg149915 	u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
8696393Scg149915 	int i;
8706393Scg149915 	RING_LOCALS;
8716393Scg149915 	DRM_DEBUG("flags = 0x%x\n", flags);
8726393Scg149915 
8736393Scg149915 	dev_priv->stats.clears++;
8746393Scg149915 
8756393Scg149915 	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
8766393Scg149915 		unsigned int tmp = flags;
8776393Scg149915 
8786393Scg149915 		flags &= ~(RADEON_FRONT | RADEON_BACK);
8796393Scg149915 		if (tmp & RADEON_FRONT)
8806393Scg149915 			flags |= RADEON_BACK;
8816393Scg149915 		if (tmp & RADEON_BACK)
8826393Scg149915 			flags |= RADEON_FRONT;
8836393Scg149915 	}
8846393Scg149915 
8856393Scg149915 	if (flags & (RADEON_FRONT | RADEON_BACK)) {
8866393Scg149915 
8876393Scg149915 		BEGIN_RING(4);
8886393Scg149915 
8896393Scg149915 		/*
8906393Scg149915 		 * Ensure the 3D stream is idle before doing a
8916393Scg149915 		 * 2D fill to clear the front or back buffer.
8926393Scg149915 		 */
8936393Scg149915 		RADEON_WAIT_UNTIL_3D_IDLE();
8946393Scg149915 
8956393Scg149915 		OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
8966393Scg149915 		OUT_RING(clear->color_mask);
8976393Scg149915 
8986393Scg149915 		ADVANCE_RING();
8996393Scg149915 
9006393Scg149915 		/* Make sure we restore the 3D state next time.  */
9016393Scg149915 		dev_priv->sarea_priv->ctx_owner = 0;
9026393Scg149915 
9036393Scg149915 		for (i = 0; i < nbox; i++) {
9046393Scg149915 			int x = pbox[i].x1;
9056393Scg149915 			int y = pbox[i].y1;
9066393Scg149915 			int w = pbox[i].x2 - x;
9076393Scg149915 			int h = pbox[i].y2 - y;
9086393Scg149915 
9096393Scg149915 			DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
9106393Scg149915 			    x, y, w, h, flags);
9116393Scg149915 
9126393Scg149915 			if (flags & RADEON_FRONT) {
9136393Scg149915 				BEGIN_RING(6);
9146393Scg149915 
9156393Scg149915 				OUT_RING(CP_PACKET3
9166393Scg149915 				    (RADEON_CNTL_PAINT_MULTI, 4));
9176393Scg149915 				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
9186393Scg149915 				    RADEON_GMC_BRUSH_SOLID_COLOR |
9196393Scg149915 				    (dev_priv-> color_fmt << 8) |
9206393Scg149915 				    RADEON_GMC_SRC_DATATYPE_COLOR |
9216393Scg149915 				    RADEON_ROP3_P |
9226393Scg149915 				    RADEON_GMC_CLR_CMP_CNTL_DIS);
9236393Scg149915 
9246393Scg149915 				OUT_RING(dev_priv->front_pitch_offset);
9256393Scg149915 				OUT_RING(clear->clear_color);
9266393Scg149915 
9276393Scg149915 				OUT_RING((x << 16) | y);
9286393Scg149915 				OUT_RING((w << 16) | h);
9296393Scg149915 
9306393Scg149915 				ADVANCE_RING();
9316393Scg149915 			}
9326393Scg149915 
9336393Scg149915 			if (flags & RADEON_BACK) {
9346393Scg149915 				BEGIN_RING(6);
9356393Scg149915 
9366393Scg149915 				OUT_RING(CP_PACKET3
9376393Scg149915 				    (RADEON_CNTL_PAINT_MULTI, 4));
9386393Scg149915 				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
9396393Scg149915 				    RADEON_GMC_BRUSH_SOLID_COLOR |
9406393Scg149915 				    (dev_priv-> color_fmt << 8) |
9416393Scg149915 				    RADEON_GMC_SRC_DATATYPE_COLOR |
9426393Scg149915 				    RADEON_ROP3_P |
9436393Scg149915 				    RADEON_GMC_CLR_CMP_CNTL_DIS);
9446393Scg149915 
9456393Scg149915 				OUT_RING(dev_priv->back_pitch_offset);
9466393Scg149915 				OUT_RING(clear->clear_color);
9476393Scg149915 
9486393Scg149915 				OUT_RING((x << 16) | y);
9496393Scg149915 				OUT_RING((w << 16) | h);
9506393Scg149915 
9516393Scg149915 				ADVANCE_RING();
9526393Scg149915 			}
9536393Scg149915 		}
9546393Scg149915 	}
9556393Scg149915 
9566393Scg149915 	/* hyper z clear */
9576393Scg149915 	/*
9586393Scg149915 	 * no docs available, based on reverse engeneering
9596393Scg149915 	 * by Stephane Marchesin
9606393Scg149915 	 */
9616393Scg149915 	if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) &&
9626393Scg149915 	    (flags & RADEON_CLEAR_FASTZ)) {
9636393Scg149915 
9646393Scg149915 		int i;
9656393Scg149915 		int depthpixperline =
9666393Scg149915 		    dev_priv->depth_fmt ==
9676393Scg149915 		    RADEON_DEPTH_FORMAT_16BIT_INT_Z ?
9686393Scg149915 		    (dev_priv->depth_pitch / 2) :
9696393Scg149915 		    (dev_priv-> depth_pitch / 4);
9706393Scg149915 
9716393Scg149915 		u32 clearmask;
9726393Scg149915 
9736393Scg149915 		u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
9746393Scg149915 		    ((clear->depth_mask & 0xff) << 24);
9756393Scg149915 
9766393Scg149915 		/*
9776393Scg149915 		 * Make sure we restore the 3D state next time.
9786393Scg149915 		 * we haven't touched any "normal" state - still
9796393Scg149915 		 * need this?
9806393Scg149915 		 */
9816393Scg149915 		dev_priv->sarea_priv->ctx_owner = 0;
9826393Scg149915 
9836393Scg149915 		if ((dev_priv->flags & RADEON_HAS_HIERZ) &&
9846393Scg149915 		    (flags & RADEON_USE_HIERZ)) {
9856393Scg149915 			/* FIXME : reverse engineer that for Rx00 cards */
9866393Scg149915 			/*
9876393Scg149915 			 * FIXME : the mask supposedly contains low-res
9886393Scg149915 			 * z values. So can't set just to the max (0xff?
9896393Scg149915 			 * or actually 0x3fff?), need to take z clear
9906393Scg149915 			 * value into account?
9916393Scg149915 			 */
9926393Scg149915 			/*
9936393Scg149915 			 * pattern seems to work for r100, though get
9946393Scg149915 			 * slight rendering errors with glxgears. If
9956393Scg149915 			 * hierz is not enabled for r100, only 4 bits
9966393Scg149915 			 * which indicate clear (15,16,31,32, all zero)
9976393Scg149915 			 * matter, the other ones are ignored, and the
9986393Scg149915 			 * same clear mask can be used. That's very
9996393Scg149915 			 * different behaviour than R200 which needs
10006393Scg149915 			 * different clear mask and different number
10016393Scg149915 			 * of tiles to clear if hierz is enabled or not !?!
10026393Scg149915 			 */
10036393Scg149915 			clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
10046393Scg149915 		} else {
10056393Scg149915 		/*
10066393Scg149915 		 * clear mask : chooses the clearing pattern.
10076393Scg149915 		 * rv250: could be used to clear only parts of macrotiles
10086393Scg149915 		 * (but that would get really complicated...)?
10096393Scg149915 		 * bit 0 and 1 (either or both of them ?!?!) are used to
10106393Scg149915 		 * not clear tile (or maybe one of the bits indicates if
10116393Scg149915 		 * the tile is compressed or not), bit 2 and 3 to not
10126393Scg149915 		 * clear tile 1,...,.
10136393Scg149915 		 * Pattern is as follows:
10146393Scg149915 		 * | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
10156393Scg149915 		 * bits -------------------------------------------------
10166393Scg149915 		 * | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
10176393Scg149915 		 * rv100: clearmask covers 2x8 4x1 tiles, but one clear
10186393Scg149915 		 * still covers 256 pixels ?!?
10196393Scg149915 		 */
10206393Scg149915 			clearmask = 0x0;
10216393Scg149915 		}
10226393Scg149915 
10236393Scg149915 		BEGIN_RING(8);
10246393Scg149915 		RADEON_WAIT_UNTIL_2D_IDLE();
10256393Scg149915 		OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
10266393Scg149915 		    tempRB3D_DEPTHCLEARVALUE);
10276393Scg149915 		/* what offset is this exactly ? */
10286393Scg149915 		OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
10296393Scg149915 		/* need ctlstat, otherwise get some strange black flickering */
10306393Scg149915 		OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
10316393Scg149915 		    RADEON_RB3D_ZC_FLUSH_ALL);
10326393Scg149915 		ADVANCE_RING();
10336393Scg149915 
10346393Scg149915 		for (i = 0; i < nbox; i++) {
10356393Scg149915 			int tileoffset, nrtilesx, nrtilesy, j;
10366393Scg149915 			/*
10376393Scg149915 			 * it looks like r200 needs rv-style clears, at
10386393Scg149915 			 * least if hierz is not enabled?
10396393Scg149915 			 */
10406393Scg149915 			if ((dev_priv->flags & RADEON_HAS_HIERZ) &&
10416393Scg149915 			    !(dev_priv->microcode_version == UCODE_R200)) {
10426393Scg149915 				/*
10436393Scg149915 				 * FIXME : figure this out for r200 (when hierz
10446393Scg149915 				 * is enabled). Or maybe r200 actually doesn't
10456393Scg149915 				 * need to put the low-res z value into the tile
10466393Scg149915 				 * cache like r100, but just needs to clear the
10476393Scg149915 				 * hi-level z-buffer? Works for R100, both with
10486393Scg149915 				 * hierz and without.R100 seems to operate on
10496393Scg149915 				 * 2x1 8x8 tiles, but... odd: offset/nrtiles
10506393Scg149915 				 * need to be 64 pix (4 blocka) aligned?
10516393Scg149915 				 * Potentially problematic with resolutions
10526393Scg149915 				 * which are not 64 pix aligned?
10536393Scg149915 				 */
10546393Scg149915 				tileoffset =
10556393Scg149915 				    ((pbox[i].y1 >> 3) * depthpixperline +
10566393Scg149915 				    pbox[i].x1) >> 6;
10576393Scg149915 				nrtilesx =
10586393Scg149915 				    ((pbox[i].x2 & ~63) -
10596393Scg149915 				    (pbox[i].x1 & ~63)) >> 4;
10606393Scg149915 				nrtilesy =
10616393Scg149915 				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
10626393Scg149915 				for (j = 0; j <= nrtilesy; j++) {
10636393Scg149915 					BEGIN_RING(4);
10646393Scg149915 					OUT_RING(CP_PACKET3
10656393Scg149915 					    (RADEON_3D_CLEAR_ZMASK, 2));
10666393Scg149915 					/* first tile */
10676393Scg149915 					OUT_RING(tileoffset * 8);
10686393Scg149915 					/* the number of tiles to clear */
10696393Scg149915 					OUT_RING(nrtilesx + 4);
10706393Scg149915 					/*
10716393Scg149915 					 * clear mask :
10726393Scg149915 					 * chooses the clearing pattern.
10736393Scg149915 					 */
10746393Scg149915 					OUT_RING(clearmask);
10756393Scg149915 					ADVANCE_RING();
10766393Scg149915 					tileoffset += depthpixperline >> 6;
10776393Scg149915 				}
10786393Scg149915 			} else if (dev_priv->microcode_version == UCODE_R200) {
10796393Scg149915 				/* works for rv250. */
10806393Scg149915 				/*
10816393Scg149915 				 * find first macro tile
10826393Scg149915 				 * (8x2 4x4 z-pixels on rv250)
10836393Scg149915 				 */
10846393Scg149915 				tileoffset =
10856393Scg149915 				    ((pbox[i].y1 >> 3) * depthpixperline +
10866393Scg149915 				    pbox[i].x1) >> 5;
10876393Scg149915 				nrtilesx =
10886393Scg149915 				    (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
10896393Scg149915 				nrtilesy =
10906393Scg149915 				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
10916393Scg149915 				for (j = 0; j <= nrtilesy; j++) {
10926393Scg149915 					BEGIN_RING(4);
10936393Scg149915 					OUT_RING(CP_PACKET3
10946393Scg149915 					    (RADEON_3D_CLEAR_ZMASK, 2));
10956393Scg149915 					/* first tile */
10966393Scg149915 					/*
10976393Scg149915 					 * judging by the first tile
10986393Scg149915 					 * offset needed, could possibly
10996393Scg149915 					 * directly address/clear 4x4
11006393Scg149915 					 * tiles instead of 8x2 * 4x4
11016393Scg149915 					 * macro tiles, though would
11026393Scg149915 					 * still need clear mask for
11036393Scg149915 					 * right/bottom if truely 4x4
11046393Scg149915 					 * granularity is desired ?
11056393Scg149915 					 */
11066393Scg149915 					OUT_RING(tileoffset * 16);
11076393Scg149915 					/* the number of tiles to clear */
11086393Scg149915 					OUT_RING(nrtilesx + 1);
11096393Scg149915 					/*
11106393Scg149915 					 * clear mask :
11116393Scg149915 					 * chooses the clearing pattern.
11126393Scg149915 					 */
11136393Scg149915 					OUT_RING(clearmask);
11146393Scg149915 					ADVANCE_RING();
11156393Scg149915 					tileoffset += depthpixperline >> 5;
11166393Scg149915 				}
11176393Scg149915 			} else {	/* rv 100 */
11186393Scg149915 				/* rv100 might not need 64 pix alignment */
11196393Scg149915 				/* offsets are, hmm, weird */
11206393Scg149915 				tileoffset =
11216393Scg149915 				    ((pbox[i].y1 >> 4) * depthpixperline +
11226393Scg149915 				    pbox[i].x1) >> 6;
11236393Scg149915 				nrtilesx =
11246393Scg149915 				    ((pbox[i].x2 & ~63) -
11256393Scg149915 				    (pbox[i].x1 & ~63)) >> 4;
11266393Scg149915 				nrtilesy =
11276393Scg149915 				    (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
11286393Scg149915 				for (j = 0; j <= nrtilesy; j++) {
11296393Scg149915 					BEGIN_RING(4);
11306393Scg149915 					OUT_RING(CP_PACKET3
11316393Scg149915 					    (RADEON_3D_CLEAR_ZMASK, 2));
11326393Scg149915 					OUT_RING(tileoffset * 128);
11336393Scg149915 					/* the number of tiles to clear */
11346393Scg149915 					OUT_RING(nrtilesx + 4);
11356393Scg149915 					/*
11366393Scg149915 					 * clear mask :
11376393Scg149915 					 * chooses the clearing pattern.
11386393Scg149915 					 */
11396393Scg149915 					OUT_RING(clearmask);
11406393Scg149915 					ADVANCE_RING();
11416393Scg149915 					tileoffset += depthpixperline >> 6;
11426393Scg149915 				}
11436393Scg149915 			}
11446393Scg149915 		}
11456393Scg149915 
11466393Scg149915 		/* TODO don't always clear all hi-level z tiles */
11476393Scg149915 		if ((dev_priv->flags & RADEON_HAS_HIERZ) &&
11486393Scg149915 		    (dev_priv->microcode_version == UCODE_R200) &&
11496393Scg149915 		    (flags & RADEON_USE_HIERZ))
11506393Scg149915 			/*
11516393Scg149915 			 * r100 and cards without hierarchical z-buffer
11526393Scg149915 			 * have no high-level z-buffer
11536393Scg149915 			 */
11546393Scg149915 			/*
11556393Scg149915 			 * FIXME : the mask supposedly contains low-res
11566393Scg149915 			 * z values. So can't set just to the max (0xff?
11576393Scg149915 			 * or actually 0x3fff?), need to take z clear value
11586393Scg149915 			 * into account?
11596393Scg149915 			 */
11606393Scg149915 		{
11616393Scg149915 			BEGIN_RING(4);
11626393Scg149915 			OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
11636393Scg149915 			OUT_RING(0x0);	/* First tile */
11646393Scg149915 			OUT_RING(0x3cc0);
11656393Scg149915 			OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
11666393Scg149915 			ADVANCE_RING();
11676393Scg149915 		}
11686393Scg149915 	}
11696393Scg149915 
11706393Scg149915 	/*
11716393Scg149915 	 * We have to clear the depth and/or stencil buffers by
11726393Scg149915 	 * rendering a quad into just those buffers.  Thus, we have to
11736393Scg149915 	 * make sure the 3D engine is configured correctly.
11746393Scg149915 	 */
11756393Scg149915 	else if ((dev_priv->microcode_version == UCODE_R200) &&
11766393Scg149915 	    (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
11776393Scg149915 
11786393Scg149915 		int tempPP_CNTL;
11796393Scg149915 		int tempRE_CNTL;
11806393Scg149915 		int tempRB3D_CNTL;
11816393Scg149915 		int tempRB3D_ZSTENCILCNTL;
11826393Scg149915 		int tempRB3D_STENCILREFMASK;
11836393Scg149915 		int tempRB3D_PLANEMASK;
11846393Scg149915 		int tempSE_CNTL;
11856393Scg149915 		int tempSE_VTE_CNTL;
11866393Scg149915 		int tempSE_VTX_FMT_0;
11876393Scg149915 		int tempSE_VTX_FMT_1;
11886393Scg149915 		int tempSE_VAP_CNTL;
11896393Scg149915 		int tempRE_AUX_SCISSOR_CNTL;
11906393Scg149915 
11916393Scg149915 		tempPP_CNTL = 0;
11926393Scg149915 		tempRE_CNTL = 0;
11936393Scg149915 
11946393Scg149915 		tempRB3D_CNTL = depth_clear->rb3d_cntl;
11956393Scg149915 
11966393Scg149915 		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
11976393Scg149915 		tempRB3D_STENCILREFMASK = 0x0;
11986393Scg149915 
11996393Scg149915 		tempSE_CNTL = depth_clear->se_cntl;
12006393Scg149915 
12016393Scg149915 		/* Disable TCL */
12026393Scg149915 
12036393Scg149915 		tempSE_VAP_CNTL =
12046393Scg149915 		    (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
12056393Scg149915 		    (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
12066393Scg149915 
12076393Scg149915 		tempRB3D_PLANEMASK = 0x0;
12086393Scg149915 
12096393Scg149915 		tempRE_AUX_SCISSOR_CNTL = 0x0;
12106393Scg149915 
12116393Scg149915 		tempSE_VTE_CNTL =
12126393Scg149915 		    SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
12136393Scg149915 
12146393Scg149915 		/* Vertex format (X, Y, Z, W) */
12156393Scg149915 		tempSE_VTX_FMT_0 =
12166393Scg149915 		    SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
12176393Scg149915 		    SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
12186393Scg149915 		tempSE_VTX_FMT_1 = 0x0;
12196393Scg149915 
12206393Scg149915 		/*
12216393Scg149915 		 * Depth buffer specific enables
12226393Scg149915 		 */
12236393Scg149915 		if (flags & RADEON_DEPTH) {
12246393Scg149915 			/* Enable depth buffer */
12256393Scg149915 			tempRB3D_CNTL |= RADEON_Z_ENABLE;
12266393Scg149915 		} else {
12276393Scg149915 			/* Disable depth buffer */
12286393Scg149915 			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
12296393Scg149915 		}
12306393Scg149915 
12316393Scg149915 		/*
12326393Scg149915 		 * Stencil buffer specific enables
12336393Scg149915 		 */
12346393Scg149915 		if (flags & RADEON_STENCIL) {
12356393Scg149915 			tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
12366393Scg149915 			tempRB3D_STENCILREFMASK = clear->depth_mask;
12376393Scg149915 		} else {
12386393Scg149915 			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
12396393Scg149915 			tempRB3D_STENCILREFMASK = 0x00000000;
12406393Scg149915 		}
12416393Scg149915 
12426393Scg149915 		if (flags & RADEON_USE_COMP_ZBUF) {
12436393Scg149915 			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
12446393Scg149915 			    RADEON_Z_DECOMPRESSION_ENABLE;
12456393Scg149915 		}
12466393Scg149915 		if (flags & RADEON_USE_HIERZ) {
12476393Scg149915 			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
12486393Scg149915 		}
12496393Scg149915 
12506393Scg149915 		BEGIN_RING(26);
12516393Scg149915 		RADEON_WAIT_UNTIL_2D_IDLE();
12526393Scg149915 
12536393Scg149915 		OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
12546393Scg149915 		OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
12556393Scg149915 		OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
12566393Scg149915 		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
12576393Scg149915 		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
12586393Scg149915 		    tempRB3D_STENCILREFMASK);
12596393Scg149915 		OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
12606393Scg149915 		OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
12616393Scg149915 		OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
12626393Scg149915 		OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
12636393Scg149915 		OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
12646393Scg149915 		OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
12656393Scg149915 		OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
12666393Scg149915 		ADVANCE_RING();
12676393Scg149915 
12686393Scg149915 		/* Make sure we restore the 3D state next time. */
12696393Scg149915 		dev_priv->sarea_priv->ctx_owner = 0;
12706393Scg149915 
12716393Scg149915 		for (i = 0; i < nbox; i++) {
12726393Scg149915 
12736393Scg149915 			/*
12746393Scg149915 			 * Funny that this should be required --
12756393Scg149915 			 *  sets top-left?
12766393Scg149915 			 */
12776393Scg149915 			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
12786393Scg149915 
12796393Scg149915 			BEGIN_RING(14);
12806393Scg149915 			OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
12816393Scg149915 			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
12826393Scg149915 			    RADEON_PRIM_WALK_RING |
12836393Scg149915 			    (3 << RADEON_NUM_VERTICES_SHIFT)));
12846393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
12856393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
12866393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
12876393Scg149915 			OUT_RING(0x3f800000);
12886393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
12896393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
12906393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
12916393Scg149915 			OUT_RING(0x3f800000);
12926393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
12936393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
12946393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
12956393Scg149915 			OUT_RING(0x3f800000);
12966393Scg149915 			ADVANCE_RING();
12976393Scg149915 		}
12986393Scg149915 	} else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
12996393Scg149915 
13006393Scg149915 		int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
13016393Scg149915 
13026393Scg149915 		rb3d_cntl = depth_clear->rb3d_cntl;
13036393Scg149915 
13046393Scg149915 		if (flags & RADEON_DEPTH) {
13056393Scg149915 			rb3d_cntl |= RADEON_Z_ENABLE;
13066393Scg149915 		} else {
13076393Scg149915 			rb3d_cntl &= ~RADEON_Z_ENABLE;
13086393Scg149915 		}
13096393Scg149915 
13106393Scg149915 		if (flags & RADEON_STENCIL) {
13116393Scg149915 			rb3d_cntl |= RADEON_STENCIL_ENABLE;
13126393Scg149915 
13136393Scg149915 			/* misnamed field */
13146393Scg149915 			rb3d_stencilrefmask = clear->depth_mask;
13156393Scg149915 
13166393Scg149915 		} else {
13176393Scg149915 			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
13186393Scg149915 			rb3d_stencilrefmask = 0x00000000;
13196393Scg149915 		}
13206393Scg149915 
13216393Scg149915 		if (flags & RADEON_USE_COMP_ZBUF) {
13226393Scg149915 			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
13236393Scg149915 			    RADEON_Z_DECOMPRESSION_ENABLE;
13246393Scg149915 		}
13256393Scg149915 		if (flags & RADEON_USE_HIERZ) {
13266393Scg149915 			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
13276393Scg149915 		}
13286393Scg149915 
13296393Scg149915 		BEGIN_RING(13);
13306393Scg149915 		RADEON_WAIT_UNTIL_2D_IDLE();
13316393Scg149915 
13326393Scg149915 		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
13336393Scg149915 		OUT_RING(0x00000000);
13346393Scg149915 		OUT_RING(rb3d_cntl);
13356393Scg149915 
13366393Scg149915 		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
13376393Scg149915 		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
13386393Scg149915 		OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
13396393Scg149915 		OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
13406393Scg149915 		ADVANCE_RING();
13416393Scg149915 
13426393Scg149915 		/* Make sure we restore the 3D state next time.  */
13436393Scg149915 		dev_priv->sarea_priv->ctx_owner = 0;
13446393Scg149915 
13456393Scg149915 		for (i = 0; i < nbox; i++) {
13466393Scg149915 
13476393Scg149915 			/*
13486393Scg149915 			 * Funny that this should be required --
13496393Scg149915 			 *  sets top-left?
13506393Scg149915 			 */
13516393Scg149915 			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
13526393Scg149915 
13536393Scg149915 			BEGIN_RING(15);
13546393Scg149915 
13556393Scg149915 			OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
13566393Scg149915 			OUT_RING(RADEON_VTX_Z_PRESENT |
13576393Scg149915 			    RADEON_VTX_PKCOLOR_PRESENT);
13586393Scg149915 			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
13596393Scg149915 			    RADEON_PRIM_WALK_RING |
13606393Scg149915 			    RADEON_MAOS_ENABLE |
13616393Scg149915 			    RADEON_VTX_FMT_RADEON_MODE |
13626393Scg149915 			    (3 << RADEON_NUM_VERTICES_SHIFT)));
13636393Scg149915 
13646393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
13656393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
13666393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
13676393Scg149915 			OUT_RING(0x0);
13686393Scg149915 
13696393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
13706393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
13716393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
13726393Scg149915 			OUT_RING(0x0);
13736393Scg149915 
13746393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
13756393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
13766393Scg149915 			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
13776393Scg149915 			OUT_RING(0x0);
13786393Scg149915 
13796393Scg149915 			ADVANCE_RING();
13806393Scg149915 		}
13816393Scg149915 	}
13826393Scg149915 
13836393Scg149915 	/*
13846393Scg149915 	 * Increment the clear counter.  The client-side 3D driver must
13856393Scg149915 	 * wait on this value before performing the clear ioctl.  We
13866393Scg149915 	 * need this because the card's so damned fast...
13876393Scg149915 	 */
13886393Scg149915 	dev_priv->sarea_priv->last_clear++;
13896393Scg149915 
13906393Scg149915 	BEGIN_RING(4);
13916393Scg149915 
13926393Scg149915 	RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
13936393Scg149915 	RADEON_WAIT_UNTIL_IDLE();
13946393Scg149915 
13956393Scg149915 	ADVANCE_RING();
13966393Scg149915 }
13976393Scg149915 
radeon_cp_dispatch_swap(drm_device_t * dev)13986393Scg149915 static void radeon_cp_dispatch_swap(drm_device_t *dev)
13996393Scg149915 {
14006393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
14016393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
14026393Scg149915 	int nbox = sarea_priv->nbox;
14036393Scg149915 	drm_clip_rect_t *pbox = sarea_priv->boxes;
14046393Scg149915 	int i;
14056393Scg149915 	RING_LOCALS;
14066393Scg149915 
14076393Scg149915 	/* Do some trivial performance monitoring... */
14086393Scg149915 	if (dev_priv->do_boxes)
14096393Scg149915 		radeon_cp_performance_boxes(dev_priv);
14106393Scg149915 
14116393Scg149915 	/*
14126393Scg149915 	 * Wait for the 3D stream to idle before dispatching the bitblt.
14136393Scg149915 	 * This will prevent data corruption between the two streams.
14146393Scg149915 	 */
14156393Scg149915 	BEGIN_RING(2);
14166393Scg149915 
14176393Scg149915 	RADEON_WAIT_UNTIL_3D_IDLE();
14186393Scg149915 
14196393Scg149915 	ADVANCE_RING();
14206393Scg149915 
14216393Scg149915 	for (i = 0; i < nbox; i++) {
14226393Scg149915 		int x = pbox[i].x1;
14236393Scg149915 		int y = pbox[i].y1;
14246393Scg149915 		int w = pbox[i].x2 - x;
14256393Scg149915 		int h = pbox[i].y2 - y;
14266393Scg149915 
14276393Scg149915 		DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
14286393Scg149915 
14296393Scg149915 		BEGIN_RING(9);
14306393Scg149915 
14316393Scg149915 		OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
14326393Scg149915 		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
14336393Scg149915 		    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
14346393Scg149915 		    RADEON_GMC_BRUSH_NONE |
14356393Scg149915 		    (dev_priv->color_fmt << 8) |
14366393Scg149915 		    RADEON_GMC_SRC_DATATYPE_COLOR |
14376393Scg149915 		    RADEON_ROP3_S |
14386393Scg149915 		    RADEON_DP_SRC_SOURCE_MEMORY |
14396393Scg149915 		    RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
14406393Scg149915 
14416393Scg149915 		/* Make this work even if front & back are flipped: */
14426393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
14436393Scg149915 		if (dev_priv->current_page == 0) {
14446393Scg149915 			OUT_RING(dev_priv->back_pitch_offset);
14456393Scg149915 			OUT_RING(dev_priv->front_pitch_offset);
14466393Scg149915 		} else {
14476393Scg149915 			OUT_RING(dev_priv->front_pitch_offset);
14486393Scg149915 			OUT_RING(dev_priv->back_pitch_offset);
14496393Scg149915 		}
14506393Scg149915 
14516393Scg149915 		OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
14526393Scg149915 		OUT_RING((x << 16) | y);
14536393Scg149915 		OUT_RING((x << 16) | y);
14546393Scg149915 		OUT_RING((w << 16) | h);
14556393Scg149915 
14566393Scg149915 		ADVANCE_RING();
14576393Scg149915 	}
14586393Scg149915 
14596393Scg149915 	/*
14606393Scg149915 	 * Increment the frame counter.  The client-side 3D driver must
14616393Scg149915 	 * throttle the framerate by waiting for this value before
14626393Scg149915 	 * performing the swapbuffer ioctl.
14636393Scg149915 	 */
14646393Scg149915 	dev_priv->sarea_priv->last_frame ++;
14656393Scg149915 
14666393Scg149915 	BEGIN_RING(4);
14676393Scg149915 
14686393Scg149915 	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
14696393Scg149915 	RADEON_WAIT_UNTIL_2D_IDLE();
14706393Scg149915 
14716393Scg149915 	ADVANCE_RING();
14726393Scg149915 }
14736393Scg149915 
radeon_cp_dispatch_flip(drm_device_t * dev)14746393Scg149915 static void radeon_cp_dispatch_flip(drm_device_t *dev)
14756393Scg149915 {
14766393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
14776393Scg149915 	drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
14786393Scg149915 	int offset = (dev_priv->current_page == 1)
14796393Scg149915 	    ? dev_priv->front_offset : dev_priv->back_offset;
14806393Scg149915 	RING_LOCALS;
14816393Scg149915 	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
14826393Scg149915 	    __FUNCTION__,
14836393Scg149915 	    dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
14846393Scg149915 
14856393Scg149915 	/* Do some trivial performance monitoring... */
14866393Scg149915 	if (dev_priv->do_boxes) {
14876393Scg149915 		dev_priv->stats.boxes |= RADEON_BOX_FLIP;
14886393Scg149915 		radeon_cp_performance_boxes(dev_priv);
14896393Scg149915 	}
14906393Scg149915 
14916393Scg149915 	/* Update the frame offsets for both CRTCs */
14926393Scg149915 	BEGIN_RING(6);
14936393Scg149915 
14946393Scg149915 	RADEON_WAIT_UNTIL_3D_IDLE();
14956393Scg149915 	OUT_RING_REG(RADEON_CRTC_OFFSET,
14966393Scg149915 	    ((sarea->frame.y * dev_priv->front_pitch +
14976393Scg149915 	    sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) + offset);
14986393Scg149915 	OUT_RING_REG(RADEON_CRTC2_OFFSET,
14996393Scg149915 	    dev_priv->sarea_priv->crtc2_base + offset);
15006393Scg149915 
15016393Scg149915 	ADVANCE_RING();
15026393Scg149915 
15036393Scg149915 	/*
15046393Scg149915 	 * Increment the frame counter.  The client-side 3D driver must
15056393Scg149915 	 * throttle the framerate by waiting for this value before
15066393Scg149915 	 * performing the swapbuffer ioctl.
15076393Scg149915 	 */
15086393Scg149915 	dev_priv->sarea_priv->last_frame ++;
15096393Scg149915 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
15106393Scg149915 	    1 - dev_priv->current_page;
15116393Scg149915 
15126393Scg149915 	BEGIN_RING(2);
15136393Scg149915 
15146393Scg149915 	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
15156393Scg149915 
15166393Scg149915 	ADVANCE_RING();
15176393Scg149915 }
15186393Scg149915 
bad_prim_vertex_nr(int primitive,int nr)15196393Scg149915 static int bad_prim_vertex_nr(int primitive, int nr)
15206393Scg149915 {
15216393Scg149915 	switch (primitive & RADEON_PRIM_TYPE_MASK) {
15226393Scg149915 	case RADEON_PRIM_TYPE_NONE:
15236393Scg149915 	case RADEON_PRIM_TYPE_POINT:
15246393Scg149915 		return (nr < 1);
15256393Scg149915 	case RADEON_PRIM_TYPE_LINE:
15266393Scg149915 		return ((nr & 1) || nr == 0);
15276393Scg149915 	case RADEON_PRIM_TYPE_LINE_STRIP:
15286393Scg149915 		return (nr < 2);
15296393Scg149915 	case RADEON_PRIM_TYPE_TRI_LIST:
15306393Scg149915 	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
15316393Scg149915 	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
15326393Scg149915 	case RADEON_PRIM_TYPE_RECT_LIST:
15336393Scg149915 		return (nr % 3 || nr == 0);
15346393Scg149915 	case RADEON_PRIM_TYPE_TRI_FAN:
15356393Scg149915 	case RADEON_PRIM_TYPE_TRI_STRIP:
15366393Scg149915 		return (nr < 3);
15376393Scg149915 	default:
15386393Scg149915 		return (1);
15396393Scg149915 	}
15406393Scg149915 }
15416393Scg149915 
15426393Scg149915 typedef struct {
15436393Scg149915 	unsigned int start;
15446393Scg149915 	unsigned int finish;
15456393Scg149915 	unsigned int prim;
15466393Scg149915 	unsigned int numverts;
15476393Scg149915 	unsigned int offset;
15486393Scg149915 	unsigned int vc_format;
15496393Scg149915 } drm_radeon_tcl_prim_t;
15506393Scg149915 
radeon_cp_dispatch_vertex(drm_device_t * dev,drm_buf_t * buf,drm_radeon_tcl_prim_t * prim)15516393Scg149915 static void radeon_cp_dispatch_vertex(drm_device_t *dev,
15526393Scg149915     drm_buf_t *buf, drm_radeon_tcl_prim_t *prim)
15536393Scg149915 {
15546393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
15556393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
15566393Scg149915 	int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
15576393Scg149915 	int numverts = (int)prim->numverts;
15586393Scg149915 	int nbox = sarea_priv->nbox;
15596393Scg149915 	int i = 0;
15606393Scg149915 	RING_LOCALS;
15616393Scg149915 
15626393Scg149915 	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
15636393Scg149915 	    prim->prim, prim->vc_format, prim->start,
15646393Scg149915 	    prim->finish, prim->numverts);
15656393Scg149915 
15666393Scg149915 	if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
15676393Scg149915 		DRM_ERROR("bad prim %x numverts %d\n",
15686393Scg149915 		    prim->prim, prim->numverts);
15696393Scg149915 		return;
15706393Scg149915 	}
15716393Scg149915 
15726393Scg149915 	do {
15736393Scg149915 		/* Emit the next cliprect */
15746393Scg149915 		if (i < nbox) {
15756393Scg149915 			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
15766393Scg149915 		}
15776393Scg149915 
15786393Scg149915 		/* Emit the vertex buffer rendering commands */
15796393Scg149915 		BEGIN_RING(5);
15806393Scg149915 
15816393Scg149915 		OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
15826393Scg149915 		OUT_RING(offset);
15836393Scg149915 		OUT_RING(numverts);
15846393Scg149915 		OUT_RING(prim->vc_format);
15856393Scg149915 		OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
15866393Scg149915 		    RADEON_COLOR_ORDER_RGBA |
15876393Scg149915 		    RADEON_VTX_FMT_RADEON_MODE |
15886393Scg149915 		    (numverts << RADEON_NUM_VERTICES_SHIFT));
15896393Scg149915 
15906393Scg149915 		ADVANCE_RING();
15916393Scg149915 
15926393Scg149915 		i++;
15936393Scg149915 	} while (i < nbox);
15946393Scg149915 }
15956393Scg149915 
radeon_cp_discard_buffer(drm_device_t * dev,drm_buf_t * buf)15966393Scg149915 static void radeon_cp_discard_buffer(drm_device_t *dev, drm_buf_t *buf)
15976393Scg149915 {
15986393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
15996393Scg149915 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
16006393Scg149915 	RING_LOCALS;
16016393Scg149915 
16026393Scg149915 	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
16036393Scg149915 
16046393Scg149915 	/* Emit the vertex buffer age */
16056393Scg149915 	BEGIN_RING(2);
16066393Scg149915 	RADEON_DISPATCH_AGE(buf_priv->age);
16076393Scg149915 	ADVANCE_RING();
16086393Scg149915 
16096393Scg149915 	buf->pending = 1;
16106393Scg149915 	buf->used = 0;
16116393Scg149915 }
16126393Scg149915 
radeon_cp_dispatch_indirect(drm_device_t * dev,drm_buf_t * buf,int start,int end)16136393Scg149915 static void radeon_cp_dispatch_indirect(drm_device_t *dev,
16146393Scg149915     drm_buf_t *buf, int start, int end)
16156393Scg149915 {
16166393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
16176393Scg149915 	RING_LOCALS;
16186393Scg149915 	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
16196393Scg149915 
16206393Scg149915 	if (start != end) {
16216393Scg149915 		int offset = (dev_priv->gart_buffers_offset +
16226393Scg149915 		    buf->offset + start);
16236393Scg149915 		int dwords = (end - start + 3) / sizeof (u32);
16246393Scg149915 
16256393Scg149915 		/*
16266393Scg149915 		 * Indirect buffer data must be an even number of
16276393Scg149915 		 * dwords, so if we've been given an odd number we must
16286393Scg149915 		 * pad the data with a Type-2 CP packet.
16296393Scg149915 		 */
16306393Scg149915 		if (dwords & 1) {
16316393Scg149915 			u32 *data = (u32 *)(uintptr_t)
16326393Scg149915 			    ((char *)dev->agp_buffer_map->handle
16336393Scg149915 			    + buf->offset + start);
16346393Scg149915 			data[dwords++] = RADEON_CP_PACKET2;
16356393Scg149915 		}
16366393Scg149915 
16376393Scg149915 		/* Fire off the indirect buffer */
16386393Scg149915 		BEGIN_RING(3);
16396393Scg149915 
16406393Scg149915 		OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
16416393Scg149915 		OUT_RING(offset);
16426393Scg149915 		OUT_RING(dwords);
16436393Scg149915 
16446393Scg149915 		ADVANCE_RING();
16456393Scg149915 	}
16466393Scg149915 }
16476393Scg149915 
radeon_cp_dispatch_indices(drm_device_t * dev,drm_buf_t * elt_buf,drm_radeon_tcl_prim_t * prim)16486393Scg149915 static void radeon_cp_dispatch_indices(drm_device_t *dev,
16496393Scg149915     drm_buf_t *elt_buf, drm_radeon_tcl_prim_t *prim)
16506393Scg149915 {
16516393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
16526393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
16536393Scg149915 	int offset = dev_priv->gart_buffers_offset + prim->offset;
16546393Scg149915 	u32 *data;
16556393Scg149915 	int dwords;
16566393Scg149915 	int i = 0;
16576393Scg149915 	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
16586393Scg149915 	int count = (prim->finish - start) / sizeof (u16);
16596393Scg149915 	int nbox = sarea_priv->nbox;
16606393Scg149915 
16616393Scg149915 	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
16626393Scg149915 	    prim->prim, prim->vc_format, prim->start,
16636393Scg149915 	    prim->finish, prim->offset, prim->numverts);
16646393Scg149915 
16656393Scg149915 	if (bad_prim_vertex_nr(prim->prim, count)) {
16666393Scg149915 		DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
16676393Scg149915 		return;
16686393Scg149915 	}
16696393Scg149915 
16706393Scg149915 	if (start >= prim->finish || (prim->start & 0x7)) {
16716393Scg149915 		DRM_ERROR("buffer prim %d\n", prim->prim);
16726393Scg149915 		return;
16736393Scg149915 	}
16746393Scg149915 
16756393Scg149915 	dwords = (prim->finish - prim->start + 3) / sizeof (u32);
16766393Scg149915 
16776393Scg149915 	data = (u32 *)(uintptr_t)((char *)dev->agp_buffer_map->handle +
16786393Scg149915 	    elt_buf->offset + prim->start);
16796393Scg149915 
16806393Scg149915 	data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
16816393Scg149915 	data[1] = offset;
16826393Scg149915 	data[2] = prim->numverts;
16836393Scg149915 	data[3] = prim->vc_format;
16846393Scg149915 	data[4] = (prim->prim |
16856393Scg149915 	    RADEON_PRIM_WALK_IND |
16866393Scg149915 	    RADEON_COLOR_ORDER_RGBA |
16876393Scg149915 	    RADEON_VTX_FMT_RADEON_MODE |
16886393Scg149915 	    (count << RADEON_NUM_VERTICES_SHIFT));
16896393Scg149915 
16906393Scg149915 	do {
16916393Scg149915 		if (i < nbox)
16926393Scg149915 			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
16936393Scg149915 
16946393Scg149915 		radeon_cp_dispatch_indirect(dev, elt_buf,
16956393Scg149915 		    prim->start, prim->finish);
16966393Scg149915 
16976393Scg149915 		i++;
16986393Scg149915 	} while (i < nbox);
16996393Scg149915 
17006393Scg149915 }
17016393Scg149915 
17026393Scg149915 #define	RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
17036393Scg149915 
17046393Scg149915 /*ARGSUSED*/
radeon_cp_dispatch_texture(drm_file_t * fpriv,drm_device_t * dev,drm_radeon_texture_t * tex,drm_radeon_tex_image_t * image,int mode)17056393Scg149915 static int radeon_cp_dispatch_texture(drm_file_t *fpriv,
17066393Scg149915     drm_device_t *dev, drm_radeon_texture_t *tex,
17076393Scg149915     drm_radeon_tex_image_t *image, int mode)
17086393Scg149915 {
17096393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
17106393Scg149915 	drm_buf_t *buf;
17116393Scg149915 	u32 format;
17126393Scg149915 	u32 *buffer;
17136393Scg149915 	const u8 __user *data;
17146393Scg149915 	int size, dwords, tex_width, blit_width, spitch;
17156393Scg149915 	u32 height;
17166393Scg149915 	int i;
17176393Scg149915 	u32 texpitch, microtile;
17186393Scg149915 	u32 offset;
17196393Scg149915 	RING_LOCALS;
17206393Scg149915 
17216393Scg149915 
17226393Scg149915 	if (radeon_check_and_fixup_offset(dev_priv, fpriv, &tex->offset)) {
17236393Scg149915 		DRM_ERROR("Invalid destination offset\n");
17246393Scg149915 		return (EINVAL);
17256393Scg149915 	}
17266393Scg149915 
17276393Scg149915 	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
17286393Scg149915 
17296393Scg149915 	/*
17306393Scg149915 	 * Flush the pixel cache.  This ensures no pixel data gets mixed
17316393Scg149915 	 * up with the texture data from the host data blit, otherwise
17326393Scg149915 	 * part of the texture image may be corrupted.
17336393Scg149915 	 */
17346393Scg149915 	BEGIN_RING(4);
17356393Scg149915 	RADEON_FLUSH_CACHE();
17366393Scg149915 	RADEON_WAIT_UNTIL_IDLE();
17376393Scg149915 	ADVANCE_RING();
17386393Scg149915 
17396393Scg149915 	/*
17406393Scg149915 	 * The compiler won't optimize away a division by a variable,
17416393Scg149915 	 * even if the only legal values are powers of two.  Thus, we'll
17426393Scg149915 	 * use a shift instead.
17436393Scg149915 	 */
17446393Scg149915 	switch (tex->format) {
17456393Scg149915 	case RADEON_TXFORMAT_ARGB8888:
17466393Scg149915 	case RADEON_TXFORMAT_RGBA8888:
17476393Scg149915 		format = RADEON_COLOR_FORMAT_ARGB8888;
17486393Scg149915 		tex_width = tex->width * 4;
17496393Scg149915 		blit_width = image->width * 4;
17506393Scg149915 		break;
17516393Scg149915 	case RADEON_TXFORMAT_AI88:
17526393Scg149915 	case RADEON_TXFORMAT_ARGB1555:
17536393Scg149915 	case RADEON_TXFORMAT_RGB565:
17546393Scg149915 	case RADEON_TXFORMAT_ARGB4444:
17556393Scg149915 	case RADEON_TXFORMAT_VYUY422:
17566393Scg149915 	case RADEON_TXFORMAT_YVYU422:
17576393Scg149915 		format = RADEON_COLOR_FORMAT_RGB565;
17586393Scg149915 		tex_width = tex->width * 2;
17596393Scg149915 		blit_width = image->width * 2;
17606393Scg149915 		break;
17616393Scg149915 	case RADEON_TXFORMAT_I8:
17626393Scg149915 	case RADEON_TXFORMAT_RGB332:
17636393Scg149915 		format = RADEON_COLOR_FORMAT_CI8;
17646393Scg149915 		tex_width = tex->width * 1;
17656393Scg149915 		blit_width = image->width * 1;
17666393Scg149915 		break;
17676393Scg149915 	default:
17686393Scg149915 		DRM_ERROR("invalid texture format %d\n", tex->format);
17696393Scg149915 		return (EINVAL);
17706393Scg149915 	}
17716393Scg149915 	spitch = blit_width >> 6;
17726393Scg149915 	if (spitch == 0 && image->height > 1)
17736393Scg149915 		return (EINVAL);
17746393Scg149915 
17756393Scg149915 	texpitch = tex->pitch;
17766393Scg149915 	if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
17776393Scg149915 		microtile = 1;
17786393Scg149915 		if (tex_width < 64) {
17796393Scg149915 			texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
17806393Scg149915 			/* we got tiled coordinates, untile them */
17816393Scg149915 			image->x *= 2;
17826393Scg149915 		}
17836393Scg149915 	} else
17846393Scg149915 		microtile = 0;
17856393Scg149915 
17866393Scg149915 	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
17876393Scg149915 
17886393Scg149915 	do {
17896393Scg149915 		DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
17906393Scg149915 		    tex->offset >> 10, tex->pitch, tex->format,
17916393Scg149915 		    image->x, image->y, image->width, image->height);
17926393Scg149915 
17936393Scg149915 		/*
17946393Scg149915 		 * Make a copy of some parameters in case we have to
17956393Scg149915 		 * update them for a multi-pass texture blit.
17966393Scg149915 		 */
17976393Scg149915 		height = image->height;
17986393Scg149915 		data = (const u8 __user *)image->data;
17996393Scg149915 
18006393Scg149915 		size = height * blit_width;
18016393Scg149915 
18026393Scg149915 		if (size > RADEON_MAX_TEXTURE_SIZE) {
18036393Scg149915 			height = RADEON_MAX_TEXTURE_SIZE / blit_width;
18046393Scg149915 			size = height * blit_width;
18056393Scg149915 		} else if (size < 4 && size > 0) {
18066393Scg149915 			size = 4;
18076393Scg149915 		} else if (size == 0) {
18086393Scg149915 			return (0);
18096393Scg149915 		}
18106393Scg149915 
18116393Scg149915 		buf = radeon_freelist_get(dev);
18126393Scg149915 #if 0
18136393Scg149915 		if (0 && !buf) {
18146393Scg149915 			radeon_do_cp_idle(dev_priv);
18156393Scg149915 			buf = radeon_freelist_get(dev);
18166393Scg149915 		}
18176393Scg149915 #endif
18186393Scg149915 		if (!buf) {
18196393Scg149915 			DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
18206393Scg149915 
18216393Scg149915 #ifdef _MULTI_DATAMODEL
18226393Scg149915 			if (ddi_model_convert_from(mode & FMODELS) ==
18236393Scg149915 			    DDI_MODEL_ILP32) {
18246393Scg149915 				drm_radeon_tex_image_32_t image32;
18256393Scg149915 				image32.x = image->x;
18266393Scg149915 				image32.y = image->y;
18276393Scg149915 				image32.width = image->width;
18286393Scg149915 				image32.height = image->height;
18296393Scg149915 				image32.data = (uint32_t)(uintptr_t)image->data;
18306393Scg149915 				DRM_COPYTO_WITH_RETURN(tex->image, &image32,
18316393Scg149915 				    sizeof (image32));
18326393Scg149915 			} else {
18336393Scg149915 #endif
18346393Scg149915 				DRM_COPYTO_WITH_RETURN(tex->image, image,
18356393Scg149915 				    sizeof (*image));
18366393Scg149915 #ifdef _MULTI_DATAMODEL
18376393Scg149915 			}
18386393Scg149915 #endif
18396393Scg149915 			return (EAGAIN);
18406393Scg149915 		}
18416393Scg149915 
18426393Scg149915 		/*
18436393Scg149915 		 * Dispatch the indirect buffer.
18446393Scg149915 		 */
18456393Scg149915 		buffer = (u32 *)(uintptr_t)
18466393Scg149915 		    ((char *)dev->agp_buffer_map->handle + buf->offset);
18476393Scg149915 
18486393Scg149915 		dwords = size / 4;
18496393Scg149915 
18506393Scg149915 #define	RADEON_COPY_MT(_buf, _data, _width) \
18516393Scg149915 	do { \
18526393Scg149915 		if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
18536393Scg149915 			DRM_ERROR("%d: EFAULT on pad, %d bytes\n", \
18546393Scg149915 			    __LINE__, (_width)); \
18556393Scg149915 			return (EFAULT); \
18566393Scg149915 		} \
18576393Scg149915 	} while (*"\0")
18586393Scg149915 
18596393Scg149915 		if (microtile) {
18606393Scg149915 			/*
18616393Scg149915 			 * texture micro tiling in use, minimum texture
18626393Scg149915 			 * width is thus 16 bytes. however, we cannot use
18636393Scg149915 			 * blitter directly for texture width < 64 bytes,
18646393Scg149915 			 * since minimum tex pitch is 64 bytes and we need
18656393Scg149915 			 * this to match the texture width, otherwise the
18666393Scg149915 			 * blitter will tile it wrong. Thus, tiling manually
18676393Scg149915 			 * in this case. Additionally, need to special case
18686393Scg149915 			 * tex height = 1, since our actual image will have
18696393Scg149915 			 * height 2 and we need to ensure we don't read
18706393Scg149915 			 * beyond the texture size from user space.
18716393Scg149915 			 */
18726393Scg149915 			if (tex->height == 1) {
18736393Scg149915 				if (tex_width >= 64 || tex_width <= 16) {
18746393Scg149915 					RADEON_COPY_MT(buffer, data,
18756393Scg149915 					    (int)(tex_width * sizeof (u32)));
18766393Scg149915 				} else if (tex_width == 32) {
18776393Scg149915 					RADEON_COPY_MT(buffer, data, 16);
18786393Scg149915 					RADEON_COPY_MT(buffer + 8,
18796393Scg149915 					    data + 16, 16);
18806393Scg149915 				}
18816393Scg149915 			} else if (tex_width >= 64 || tex_width == 16) {
18826393Scg149915 				RADEON_COPY_MT(buffer, data,
18836393Scg149915 				    (int)(dwords * sizeof (u32)));
18846393Scg149915 			} else if (tex_width < 16) {
18856393Scg149915 				for (i = 0; i < tex->height; i++) {
18866393Scg149915 					RADEON_COPY_MT(buffer, data, tex_width);
18876393Scg149915 					buffer += 4;
18886393Scg149915 					data += tex_width;
18896393Scg149915 				}
18906393Scg149915 			} else if (tex_width == 32) {
18916393Scg149915 				/*
18926393Scg149915 				 * TODO: make sure this works when not
18936393Scg149915 				 * fitting in one buffer
18946393Scg149915 				 *  (i.e. 32bytes x 2048...)
18956393Scg149915 				 */
18966393Scg149915 				for (i = 0; i < tex->height; i += 2) {
18976393Scg149915 					RADEON_COPY_MT(buffer, data, 16);
18986393Scg149915 					data += 16;
18996393Scg149915 					RADEON_COPY_MT(buffer + 8, data, 16);
19006393Scg149915 					data += 16;
19016393Scg149915 					RADEON_COPY_MT(buffer + 4, data, 16);
19026393Scg149915 					data += 16;
19036393Scg149915 					RADEON_COPY_MT(buffer + 12, data, 16);
19046393Scg149915 					data += 16;
19056393Scg149915 					buffer += 16;
19066393Scg149915 				}
19076393Scg149915 			}
19086393Scg149915 		} else {
19096393Scg149915 			if (tex_width >= 32) {
19106393Scg149915 				/*
19116393Scg149915 				 * Texture image width is larger than the
19126393Scg149915 				 * minimum, so we can upload it directly.
19136393Scg149915 				 */
19146393Scg149915 				RADEON_COPY_MT(buffer, data,
19156393Scg149915 				    (int)(dwords * sizeof (u32)));
19166393Scg149915 			} else {
19176393Scg149915 				/*
19186393Scg149915 				 * Texture image width is less than the minimum,
19196393Scg149915 				 * so we need to pad out each image scanline to
19206393Scg149915 				 * the minimum width.
19216393Scg149915 				 */
19226393Scg149915 				for (i = 0; i < tex->height; i++) {
19236393Scg149915 					RADEON_COPY_MT(buffer, data, tex_width);
19246393Scg149915 					buffer += 8;
19256393Scg149915 					data += tex_width;
19266393Scg149915 				}
19276393Scg149915 			}
19286393Scg149915 		}
19296393Scg149915 
19306393Scg149915 #undef RADEON_COPY_MT
19316393Scg149915 		buf->filp = fpriv;
19326393Scg149915 		buf->used = size;
19336393Scg149915 		offset = dev_priv->gart_buffers_offset + buf->offset;
19346393Scg149915 
19356393Scg149915 		BEGIN_RING(9);
19366393Scg149915 		OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
19376393Scg149915 		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
19386393Scg149915 		    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
19396393Scg149915 		    RADEON_GMC_BRUSH_NONE |
19406393Scg149915 		    (format << 8) |
19416393Scg149915 		    RADEON_GMC_SRC_DATATYPE_COLOR |
19426393Scg149915 		    RADEON_ROP3_S |
19436393Scg149915 		    RADEON_DP_SRC_SOURCE_MEMORY |
19446393Scg149915 		    RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
19456393Scg149915 		OUT_RING((spitch << 22) | (offset >> 10));
19466393Scg149915 		OUT_RING((texpitch << 22) | (tex->offset >> 10));
19476393Scg149915 		OUT_RING(0);
19486393Scg149915 		OUT_RING((image->x << 16) | image->y);
19496393Scg149915 		OUT_RING((image->width << 16) | height);
19506393Scg149915 		RADEON_WAIT_UNTIL_2D_IDLE();
19516393Scg149915 		ADVANCE_RING();
19526393Scg149915 		COMMIT_RING();
19536393Scg149915 
19546393Scg149915 
19556393Scg149915 		radeon_cp_discard_buffer(dev, buf);
19566393Scg149915 
19576393Scg149915 		/* Update the input parameters for next time */
19586393Scg149915 		image->y += height;
19596393Scg149915 		image->height -= height;
19606393Scg149915 		image->data = (const u8 __user *)image->data + size;
19616393Scg149915 	} while (image->height > 0);
19626393Scg149915 
19636393Scg149915 	/*
19646393Scg149915 	 * Flush the pixel cache after the blit completes.  This ensures
19656393Scg149915 	 * the texture data is written out to memory before rendering
19666393Scg149915 	 * continues.
19676393Scg149915 	 */
19686393Scg149915 	BEGIN_RING(4);
19696393Scg149915 	RADEON_FLUSH_CACHE();
19706393Scg149915 	RADEON_WAIT_UNTIL_2D_IDLE();
19716393Scg149915 	ADVANCE_RING();
19726393Scg149915 	COMMIT_RING();
19736393Scg149915 	return (0);
19746393Scg149915 }
19756393Scg149915 
radeon_cp_dispatch_stipple(drm_device_t * dev,u32 * stipple)19766393Scg149915 static void radeon_cp_dispatch_stipple(drm_device_t *dev, u32 *stipple)
19776393Scg149915 {
19786393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
19796393Scg149915 	int i;
19806393Scg149915 	RING_LOCALS;
19816393Scg149915 	DRM_DEBUG("\n");
19826393Scg149915 
19836393Scg149915 	BEGIN_RING(35);
19846393Scg149915 
19856393Scg149915 	OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
19866393Scg149915 	OUT_RING(0x00000000);
19876393Scg149915 
19886393Scg149915 	OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
19896393Scg149915 	for (i = 0; i < 32; i++) {
19906393Scg149915 		OUT_RING(stipple[i]);
19916393Scg149915 	}
19926393Scg149915 
19936393Scg149915 	ADVANCE_RING();
19946393Scg149915 }
19956393Scg149915 
radeon_apply_surface_regs(int surf_index,drm_radeon_private_t * dev_priv)19966393Scg149915 static void radeon_apply_surface_regs(int surf_index,
19976393Scg149915     drm_radeon_private_t *dev_priv)
19986393Scg149915 {
19996393Scg149915 	if (!dev_priv->mmio)
20006393Scg149915 		return;
20016393Scg149915 
20026393Scg149915 	(void) radeon_do_cp_idle(dev_priv);
20036393Scg149915 
20046393Scg149915 	RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
20056393Scg149915 	    dev_priv->surfaces[surf_index].flags);
20066393Scg149915 	RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
20076393Scg149915 	    dev_priv->surfaces[surf_index].lower);
20086393Scg149915 	RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
20096393Scg149915 	    dev_priv->surfaces[surf_index].upper);
20106393Scg149915 }
20116393Scg149915 
20126393Scg149915 /*
20136393Scg149915  * Allocates a virtual surface
20146393Scg149915  * doesn't always allocate a real surface, will stretch an existing
20156393Scg149915  * surface when possible.
20166393Scg149915  *
20176393Scg149915  * Note that refcount can be at most 2, since during a free refcount=3
20186393Scg149915  * might mean we have to allocate a new surface which might not always
20196393Scg149915  * be available.
20206393Scg149915  * For example : we allocate three contigous surfaces ABC. If B is
20216393Scg149915  * freed, we suddenly need two surfaces to store A and C, which might
20226393Scg149915  * not always be available.
20236393Scg149915  */
alloc_surface(drm_radeon_surface_alloc_t * new,drm_radeon_private_t * dev_priv,drm_file_t * filp)20246393Scg149915 static int alloc_surface(drm_radeon_surface_alloc_t *new,
20256393Scg149915     drm_radeon_private_t *dev_priv, drm_file_t *filp)
20266393Scg149915 {
20276393Scg149915 	struct radeon_virt_surface *s;
20286393Scg149915 	int i;
20296393Scg149915 	int virt_surface_index;
20306393Scg149915 	uint32_t new_upper, new_lower;
20316393Scg149915 
20326393Scg149915 	new_lower = new->address;
20336393Scg149915 	new_upper = new_lower + new->size - 1;
20346393Scg149915 
20356393Scg149915 	/* sanity check */
20366393Scg149915 	if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
20376393Scg149915 	    ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
20386393Scg149915 	    RADEON_SURF_ADDRESS_FIXED_MASK) ||
20396393Scg149915 	    ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
20406393Scg149915 		return (-1);
20416393Scg149915 
20426393Scg149915 	/* make sure there is no overlap with existing surfaces */
20436393Scg149915 	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
20446393Scg149915 		if ((dev_priv->surfaces[i].refcount != 0) &&
20456393Scg149915 		    (((new_lower >= dev_priv->surfaces[i].lower) &&
20466393Scg149915 		    (new_lower < dev_priv->surfaces[i].upper)) ||
20476393Scg149915 		    ((new_lower < dev_priv->surfaces[i].lower) &&
20486393Scg149915 		    (new_upper > dev_priv->surfaces[i].lower)))) {
20496393Scg149915 			return (-1);
20506393Scg149915 		}
20516393Scg149915 	}
20526393Scg149915 
20536393Scg149915 	/* find a virtual surface */
20546393Scg149915 	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
20556393Scg149915 		if (dev_priv->virt_surfaces[i].filp == 0)
20566393Scg149915 			break;
20576393Scg149915 	if (i == 2 * RADEON_MAX_SURFACES) {
20586393Scg149915 		return (-1);
20596393Scg149915 	}
20606393Scg149915 	virt_surface_index = i;
20616393Scg149915 
20626393Scg149915 	/* try to reuse an existing surface */
20636393Scg149915 	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
20646393Scg149915 		/* extend before */
20656393Scg149915 		if ((dev_priv->surfaces[i].refcount == 1) &&
20666393Scg149915 		    (new->flags == dev_priv->surfaces[i].flags) &&
20676393Scg149915 		    (new_upper + 1 == dev_priv->surfaces[i].lower)) {
20686393Scg149915 			s = &(dev_priv->virt_surfaces[virt_surface_index]);
20696393Scg149915 			s->surface_index = i;
20706393Scg149915 			s->lower = new_lower;
20716393Scg149915 			s->upper = new_upper;
20726393Scg149915 			s->flags = new->flags;
20736393Scg149915 			s->filp = filp;
20746393Scg149915 			dev_priv->surfaces[i].refcount++;
20756393Scg149915 			dev_priv->surfaces[i].lower = s->lower;
20766393Scg149915 			radeon_apply_surface_regs(s->surface_index, dev_priv);
20776393Scg149915 			return (virt_surface_index);
20786393Scg149915 		}
20796393Scg149915 
20806393Scg149915 		/* extend after */
20816393Scg149915 		if ((dev_priv->surfaces[i].refcount == 1) &&
20826393Scg149915 		    (new->flags == dev_priv->surfaces[i].flags) &&
20836393Scg149915 		    (new_lower == dev_priv->surfaces[i].upper + 1)) {
20846393Scg149915 			s = &(dev_priv->virt_surfaces[virt_surface_index]);
20856393Scg149915 			s->surface_index = i;
20866393Scg149915 			s->lower = new_lower;
20876393Scg149915 			s->upper = new_upper;
20886393Scg149915 			s->flags = new->flags;
20896393Scg149915 			s->filp = filp;
20906393Scg149915 			dev_priv->surfaces[i].refcount++;
20916393Scg149915 			dev_priv->surfaces[i].upper = s->upper;
20926393Scg149915 			radeon_apply_surface_regs(s->surface_index, dev_priv);
20936393Scg149915 			return (virt_surface_index);
20946393Scg149915 		}
20956393Scg149915 	}
20966393Scg149915 
20976393Scg149915 	/* okay, we need a new one */
20986393Scg149915 	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
20996393Scg149915 		if (dev_priv->surfaces[i].refcount == 0) {
21006393Scg149915 			s = &(dev_priv->virt_surfaces[virt_surface_index]);
21016393Scg149915 			s->surface_index = i;
21026393Scg149915 			s->lower = new_lower;
21036393Scg149915 			s->upper = new_upper;
21046393Scg149915 			s->flags = new->flags;
21056393Scg149915 			s->filp = filp;
21066393Scg149915 			dev_priv->surfaces[i].refcount = 1;
21076393Scg149915 			dev_priv->surfaces[i].lower = s->lower;
21086393Scg149915 			dev_priv->surfaces[i].upper = s->upper;
21096393Scg149915 			dev_priv->surfaces[i].flags = s->flags;
21106393Scg149915 			radeon_apply_surface_regs(s->surface_index, dev_priv);
21116393Scg149915 			return (virt_surface_index);
21126393Scg149915 		}
21136393Scg149915 	}
21146393Scg149915 
21156393Scg149915 	/* we didn't find anything */
21166393Scg149915 	return (-1);
21176393Scg149915 }
21186393Scg149915 
21196393Scg149915 static int
free_surface(drm_file_t * filp,drm_radeon_private_t * dev_priv,int lower)21206393Scg149915 free_surface(drm_file_t *filp, drm_radeon_private_t *dev_priv, int lower)
21216393Scg149915 {
21226393Scg149915 	struct radeon_virt_surface *s;
21236393Scg149915 	int i;
21246393Scg149915 
21256393Scg149915 	/* find the virtual surface */
21266393Scg149915 	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
21276393Scg149915 		s = &(dev_priv->virt_surfaces[i]);
21286393Scg149915 		if (s->filp) {
21296393Scg149915 			if ((lower == s->lower) && (filp == s->filp)) {
21306393Scg149915 				if (dev_priv->surfaces[s->surface_index].
21316393Scg149915 				    lower == s->lower)
21326393Scg149915 					dev_priv->surfaces[s->surface_index].
21336393Scg149915 					    lower = s->upper;
21346393Scg149915 
21356393Scg149915 				if (dev_priv->surfaces[s->surface_index].
21366393Scg149915 				    upper == s->upper)
21376393Scg149915 					dev_priv->surfaces[s->surface_index].
21386393Scg149915 					    upper = s->lower;
21396393Scg149915 
21406393Scg149915 				dev_priv->surfaces[s->surface_index].refcount--;
21416393Scg149915 				if (dev_priv->surfaces[s->surface_index].
21426393Scg149915 				    refcount == 0)
21436393Scg149915 					dev_priv->surfaces[s->surface_index].
21446393Scg149915 					    flags = 0;
21456393Scg149915 				s->filp = NULL;
21466393Scg149915 				radeon_apply_surface_regs(s->surface_index,
21476393Scg149915 				    dev_priv);
21486393Scg149915 				return (0);
21496393Scg149915 			}
21506393Scg149915 		}
21516393Scg149915 	}
21526393Scg149915 
21536393Scg149915 	return (1);
21546393Scg149915 }
21556393Scg149915 
radeon_surfaces_release(drm_file_t * filp,drm_radeon_private_t * dev_priv)21566393Scg149915 static void radeon_surfaces_release(drm_file_t *filp,
21576393Scg149915     drm_radeon_private_t *dev_priv)
21586393Scg149915 {
21596393Scg149915 	int i;
21606393Scg149915 
21616393Scg149915 	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
21626393Scg149915 		if (dev_priv->virt_surfaces[i].filp == filp)
21636393Scg149915 			(void) free_surface(filp, dev_priv,
21646393Scg149915 			    dev_priv->virt_surfaces[i].lower);
21656393Scg149915 	}
21666393Scg149915 }
21676393Scg149915 
21686393Scg149915 /*
21696393Scg149915  * IOCTL functions
21706393Scg149915  */
21716393Scg149915 /*ARGSUSED*/
radeon_surface_alloc(DRM_IOCTL_ARGS)21726393Scg149915 static int radeon_surface_alloc(DRM_IOCTL_ARGS)
21736393Scg149915 {
21746393Scg149915 	DRM_DEVICE;
21756393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
21766393Scg149915 	drm_radeon_surface_alloc_t alloc;
21776393Scg149915 
21786393Scg149915 	if (!dev_priv) {
21796393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
21806393Scg149915 		return (EINVAL);
21816393Scg149915 	}
21826393Scg149915 
21836393Scg149915 	DRM_COPYFROM_WITH_RETURN(&alloc, (void *)data, sizeof (alloc));
21846393Scg149915 
21856393Scg149915 	if (alloc_surface(&alloc, dev_priv, fpriv) == -1)
21866393Scg149915 		return (EINVAL);
21876393Scg149915 	else
21886393Scg149915 		return (0);
21896393Scg149915 }
21906393Scg149915 
21916393Scg149915 /*ARGSUSED*/
radeon_surface_free(DRM_IOCTL_ARGS)21926393Scg149915 static int radeon_surface_free(DRM_IOCTL_ARGS)
21936393Scg149915 {
21946393Scg149915 	DRM_DEVICE;
21956393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
21966393Scg149915 	drm_radeon_surface_free_t memfree;
21976393Scg149915 
21986393Scg149915 	if (!dev_priv) {
21996393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
22006393Scg149915 		return (EINVAL);
22016393Scg149915 	}
22026393Scg149915 
22036393Scg149915 	DRM_COPYFROM_WITH_RETURN(&memfree, (void *)data, sizeof (memfree));
22046393Scg149915 	if (free_surface(fpriv, dev_priv, memfree.address)) {
22056393Scg149915 		return (EINVAL);
22066393Scg149915 	}
22076393Scg149915 	else
22086393Scg149915 		return (0);
22096393Scg149915 }
22106393Scg149915 
22116393Scg149915 /*ARGSUSED*/
radeon_cp_clear(DRM_IOCTL_ARGS)22126393Scg149915 static int radeon_cp_clear(DRM_IOCTL_ARGS)
22136393Scg149915 {
22146393Scg149915 	DRM_DEVICE;
22156393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
22166393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
22176393Scg149915 	drm_radeon_clear_t clear;
22186393Scg149915 	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
22196393Scg149915 
22206393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
22216393Scg149915 
22226393Scg149915 #ifdef _MULTI_DATAMODEL
22236393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
22246393Scg149915 		drm_radeon_clear_32_t	clear32;
22256393Scg149915 		DRM_COPYFROM_WITH_RETURN(&clear32, (void *)data,
22266393Scg149915 		    sizeof (clear32));
22276393Scg149915 		clear.flags = clear32.flags;
22286393Scg149915 		clear.clear_color = clear32.clear_color;
22296393Scg149915 		clear.clear_depth = clear32.clear_depth;
22306393Scg149915 		clear.color_mask = clear32.color_mask;
22316393Scg149915 		clear.depth_mask = clear32.depth_mask;
22326393Scg149915 		clear.depth_boxes = (void*)(uintptr_t)clear32.depth_boxes;
22336393Scg149915 	} else {
22346393Scg149915 #endif
22356393Scg149915 		DRM_COPYFROM_WITH_RETURN(&clear, (void *)data, sizeof (clear));
22366393Scg149915 #ifdef _MULTI_DATAMODEL
22376393Scg149915 	}
22386393Scg149915 #endif
22396393Scg149915 
22406393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
22416393Scg149915 
22426393Scg149915 	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
22436393Scg149915 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
22446393Scg149915 
22456393Scg149915 	if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
22466393Scg149915 	    sarea_priv->nbox * sizeof (depth_boxes[0])))
22476393Scg149915 	return (EFAULT);
22486393Scg149915 
22496393Scg149915 	radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
22506393Scg149915 
22516393Scg149915 	COMMIT_RING();
22526393Scg149915 	return (0);
22536393Scg149915 }
22546393Scg149915 
22556393Scg149915 /*
22566393Scg149915  * Not sure why this isn't set all the time:
22576393Scg149915  */
radeon_do_init_pageflip(drm_device_t * dev)22586393Scg149915 static int radeon_do_init_pageflip(drm_device_t *dev)
22596393Scg149915 {
22606393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
22616393Scg149915 	RING_LOCALS;
22626393Scg149915 
22636393Scg149915 	BEGIN_RING(6);
22646393Scg149915 	RADEON_WAIT_UNTIL_3D_IDLE();
22656393Scg149915 	OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
22666393Scg149915 	OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
22676393Scg149915 	    RADEON_CRTC_OFFSET_FLIP_CNTL);
22686393Scg149915 	OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
22696393Scg149915 	OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
22706393Scg149915 	    RADEON_CRTC_OFFSET_FLIP_CNTL);
22716393Scg149915 	ADVANCE_RING();
22726393Scg149915 
22736393Scg149915 	dev_priv->page_flipping = 1;
22746393Scg149915 	dev_priv->current_page = 0;
22756393Scg149915 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
22766393Scg149915 
22776393Scg149915 	return (0);
22786393Scg149915 }
22796393Scg149915 
22806393Scg149915 /*
22816393Scg149915  * Called whenever a client dies, from drm_release.
22826393Scg149915  * NOTE:  Lock isn't necessarily held when this is called!
22836393Scg149915  */
radeon_do_cleanup_pageflip(drm_device_t * dev)22846393Scg149915 static int radeon_do_cleanup_pageflip(drm_device_t *dev)
22856393Scg149915 {
22866393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
22876393Scg149915 
22886393Scg149915 	if (dev_priv->current_page != 0)
22896393Scg149915 		radeon_cp_dispatch_flip(dev);
22906393Scg149915 
22916393Scg149915 	dev_priv->page_flipping = 0;
22926393Scg149915 	return (0);
22936393Scg149915 }
22946393Scg149915 
22956393Scg149915 /*
22966393Scg149915  * Swapping and flipping are different operations, need different ioctls.
22976393Scg149915  * They can & should be intermixed to support multiple 3d windows.
22986393Scg149915  */
22996393Scg149915 /*ARGSUSED*/
radeon_cp_flip(DRM_IOCTL_ARGS)23006393Scg149915 static int radeon_cp_flip(DRM_IOCTL_ARGS)
23016393Scg149915 {
23026393Scg149915 	DRM_DEVICE;
23036393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
23046393Scg149915 
23056393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
23066393Scg149915 
23076393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
23086393Scg149915 
23096393Scg149915 	if (!dev_priv->page_flipping)
23106393Scg149915 		(void) radeon_do_init_pageflip(dev);
23116393Scg149915 
23126393Scg149915 	radeon_cp_dispatch_flip(dev);
23136393Scg149915 
23146393Scg149915 	COMMIT_RING();
23156393Scg149915 	return (0);
23166393Scg149915 }
23176393Scg149915 
23186393Scg149915 /*ARGSUSED*/
radeon_cp_swap(DRM_IOCTL_ARGS)23196393Scg149915 static int radeon_cp_swap(DRM_IOCTL_ARGS)
23206393Scg149915 {
23216393Scg149915 	DRM_DEVICE;
23226393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
23236393Scg149915 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
23246393Scg149915 
23256393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
23266393Scg149915 
23276393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
23286393Scg149915 
23296393Scg149915 	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
23306393Scg149915 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
23316393Scg149915 
23326393Scg149915 	radeon_cp_dispatch_swap(dev);
23336393Scg149915 	dev_priv->sarea_priv->ctx_owner = 0;
23346393Scg149915 
23356393Scg149915 	COMMIT_RING();
23366393Scg149915 	return (0);
23376393Scg149915 }
23386393Scg149915 
23396393Scg149915 /*ARGSUSED*/
radeon_cp_vertex(DRM_IOCTL_ARGS)23406393Scg149915 static int radeon_cp_vertex(DRM_IOCTL_ARGS)
23416393Scg149915 {
23426393Scg149915 	DRM_DEVICE;
23436393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
23446393Scg149915 	drm_radeon_sarea_t *sarea_priv;
23456393Scg149915 	drm_device_dma_t *dma = dev->dma;
23466393Scg149915 	drm_buf_t *buf;
23476393Scg149915 	drm_radeon_vertex_t vertex;
23486393Scg149915 	drm_radeon_tcl_prim_t prim;
23496393Scg149915 
23506393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
23516393Scg149915 
23526393Scg149915 	if (!dev_priv) {
23536393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
23546393Scg149915 		return (EINVAL);
23556393Scg149915 	}
23566393Scg149915 
23576393Scg149915 	sarea_priv = dev_priv->sarea_priv;
23586393Scg149915 
23596393Scg149915 	DRM_COPYFROM_WITH_RETURN(&vertex, (void *)data, sizeof (vertex));
23606393Scg149915 
23616393Scg149915 	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
23626393Scg149915 	    DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
23636393Scg149915 
23646393Scg149915 	if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
23656393Scg149915 		DRM_ERROR("buffer index %d (of %d max)\n",
23666393Scg149915 		    vertex.idx, dma->buf_count - 1);
23676393Scg149915 		return (EINVAL);
23686393Scg149915 	}
23696393Scg149915 	if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
23706393Scg149915 		DRM_ERROR("buffer prim %d\n", vertex.prim);
23716393Scg149915 		return (EINVAL);
23726393Scg149915 	}
23736393Scg149915 
23746393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
23756393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
23766393Scg149915 
23776393Scg149915 	buf = dma->buflist[vertex.idx];
23786393Scg149915 
23796393Scg149915 	if (buf->filp != fpriv) {
23806393Scg149915 		DRM_ERROR("process %d using buffer owned by %p\n",
23816393Scg149915 		    DRM_CURRENTPID, buf->filp);
23826393Scg149915 		return (EINVAL);
23836393Scg149915 	}
23846393Scg149915 	if (buf->pending) {
23856393Scg149915 		DRM_ERROR("sending pending buffer %d\n", vertex.idx);
23866393Scg149915 		return (EINVAL);
23876393Scg149915 	}
23886393Scg149915 
23896393Scg149915 	/*
23906393Scg149915 	 * Build up a prim_t record:
23916393Scg149915 	 */
23926393Scg149915 	if (vertex.count) {
23936393Scg149915 		buf->used = vertex.count;	/* not used? */
23946393Scg149915 
23956393Scg149915 		if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
23966393Scg149915 			if (radeon_emit_state(dev_priv, fpriv,
23976393Scg149915 			    &sarea_priv->context_state,
23986393Scg149915 			    sarea_priv->tex_state,
23996393Scg149915 			    sarea_priv->dirty)) {
24006393Scg149915 				DRM_ERROR("radeon_emit_state failed\n");
24016393Scg149915 				return (EINVAL);
24026393Scg149915 			}
24036393Scg149915 
24046393Scg149915 			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
24056393Scg149915 			    RADEON_UPLOAD_TEX1IMAGES |
24066393Scg149915 			    RADEON_UPLOAD_TEX2IMAGES |
24076393Scg149915 			    RADEON_REQUIRE_QUIESCENCE);
24086393Scg149915 		}
24096393Scg149915 
24106393Scg149915 		prim.start = 0;
24116393Scg149915 		prim.finish = vertex.count;	/* unused */
24126393Scg149915 		prim.prim = vertex.prim;
24136393Scg149915 		prim.numverts = vertex.count;
24146393Scg149915 		prim.vc_format = dev_priv->sarea_priv->vc_format;
24156393Scg149915 
24166393Scg149915 		radeon_cp_dispatch_vertex(dev, buf, &prim);
24176393Scg149915 	}
24186393Scg149915 
24196393Scg149915 	if (vertex.discard) {
24206393Scg149915 		radeon_cp_discard_buffer(dev, buf);
24216393Scg149915 	}
24226393Scg149915 
24236393Scg149915 	COMMIT_RING();
24246393Scg149915 	return (0);
24256393Scg149915 }
24266393Scg149915 
24276393Scg149915 /*ARGSUSED*/
radeon_cp_indices(DRM_IOCTL_ARGS)24286393Scg149915 static int radeon_cp_indices(DRM_IOCTL_ARGS)
24296393Scg149915 {
24306393Scg149915 	DRM_DEVICE;
24316393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
24326393Scg149915 	drm_radeon_sarea_t *sarea_priv;
24336393Scg149915 	drm_device_dma_t *dma = dev->dma;
24346393Scg149915 	drm_buf_t *buf;
24356393Scg149915 	drm_radeon_indices_t elts;
24366393Scg149915 	drm_radeon_tcl_prim_t prim;
24376393Scg149915 /*	int count; */
24386393Scg149915 
24396393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
24406393Scg149915 
24416393Scg149915 	if (!dev_priv) {
24426393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
24436393Scg149915 		return (EINVAL);
24446393Scg149915 	}
24456393Scg149915 	sarea_priv = dev_priv->sarea_priv;
24466393Scg149915 
24476393Scg149915 	DRM_COPYFROM_WITH_RETURN(&elts, (void *)data, sizeof (elts));
24486393Scg149915 
24496393Scg149915 	DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
24506393Scg149915 	    DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
24516393Scg149915 
24526393Scg149915 	if (elts.idx < 0 || elts.idx >= dma->buf_count) {
24536393Scg149915 		DRM_ERROR("buffer index %d (of %d max)\n",
24546393Scg149915 		    elts.idx, dma->buf_count - 1);
24556393Scg149915 		return (EINVAL);
24566393Scg149915 	}
24576393Scg149915 	if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
24586393Scg149915 		DRM_ERROR("buffer prim %d\n", elts.prim);
24596393Scg149915 		return (EINVAL);
24606393Scg149915 	}
24616393Scg149915 
24626393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
24636393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
24646393Scg149915 
24656393Scg149915 	buf = dma->buflist[elts.idx];
24666393Scg149915 
24676393Scg149915 	if (buf->filp != fpriv) {
24686393Scg149915 		DRM_ERROR("process %d using buffer owned by %p\n",
24696393Scg149915 		    DRM_CURRENTPID, buf->filp);
24706393Scg149915 		return (EINVAL);
24716393Scg149915 	}
24726393Scg149915 	if (buf->pending) {
24736393Scg149915 		DRM_ERROR("sending pending buffer %d\n", elts.idx);
24746393Scg149915 		return (EINVAL);
24756393Scg149915 	}
24766393Scg149915 
24776393Scg149915 /*	count = (elts.end - elts.start) / sizeof(u16); */
24786393Scg149915 	elts.start -= RADEON_INDEX_PRIM_OFFSET;
24796393Scg149915 
24806393Scg149915 	if (elts.start & 0x7) {
24816393Scg149915 		DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
24826393Scg149915 		return (EINVAL);
24836393Scg149915 	}
24846393Scg149915 	if (elts.start < buf->used) {
24856393Scg149915 		DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
24866393Scg149915 		return (EINVAL);
24876393Scg149915 	}
24886393Scg149915 
24896393Scg149915 	buf->used = elts.end;
24906393Scg149915 
24916393Scg149915 	if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
24926393Scg149915 		if (radeon_emit_state(dev_priv, fpriv,
24936393Scg149915 		    &sarea_priv->context_state,
24946393Scg149915 		    sarea_priv->tex_state,
24956393Scg149915 		    sarea_priv->dirty)) {
24966393Scg149915 			DRM_ERROR("radeon_emit_state failed\n");
24976393Scg149915 			return (EINVAL);
24986393Scg149915 		}
24996393Scg149915 
25006393Scg149915 		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
25016393Scg149915 		    RADEON_UPLOAD_TEX1IMAGES |
25026393Scg149915 		    RADEON_UPLOAD_TEX2IMAGES |
25036393Scg149915 		    RADEON_REQUIRE_QUIESCENCE);
25046393Scg149915 	}
25056393Scg149915 
25066393Scg149915 	/*
25076393Scg149915 	 * Build up a prim_t record:
25086393Scg149915 	 */
25096393Scg149915 	prim.start = elts.start;
25106393Scg149915 	prim.finish = elts.end;
25116393Scg149915 	prim.prim = elts.prim;
25126393Scg149915 	prim.offset = 0;	/* offset from start of dma buffers */
25136393Scg149915 	prim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
25146393Scg149915 	prim.vc_format = dev_priv->sarea_priv->vc_format;
25156393Scg149915 
25166393Scg149915 	radeon_cp_dispatch_indices(dev, buf, &prim);
25176393Scg149915 	if (elts.discard) {
25186393Scg149915 		radeon_cp_discard_buffer(dev, buf);
25196393Scg149915 	}
25206393Scg149915 
25216393Scg149915 	COMMIT_RING();
25226393Scg149915 	return (0);
25236393Scg149915 }
25246393Scg149915 
25256393Scg149915 /*ARGSUSED*/
radeon_cp_texture(DRM_IOCTL_ARGS)25266393Scg149915 static int radeon_cp_texture(DRM_IOCTL_ARGS)
25276393Scg149915 {
25286393Scg149915 	DRM_DEVICE;
25296393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
25306393Scg149915 	drm_radeon_texture_t tex;
25316393Scg149915 	drm_radeon_tex_image_t image;
25326393Scg149915 	int ret;
25336393Scg149915 
25346393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
25356393Scg149915 
25366393Scg149915 #ifdef _MULTI_DATAMODEL
25376393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
25386393Scg149915 		drm_radeon_texture_32_t tex32;
25396393Scg149915 		drm_radeon_tex_image_32_t image32;
25406393Scg149915 
25416393Scg149915 		DRM_COPYFROM_WITH_RETURN(&tex32, (void *)data, sizeof (tex32));
25426393Scg149915 		if (tex32.image == 0) {
25436393Scg149915 			DRM_ERROR("null texture image!\n");
25446393Scg149915 			return (EINVAL);
25456393Scg149915 		}
25466393Scg149915 		if (DRM_COPY_FROM_USER(&image32,
25476393Scg149915 		    (void *)(uintptr_t)tex32.image, sizeof (image32))) {
25486393Scg149915 			cmn_err(CE_WARN, "copyin32 failed");
25496393Scg149915 			return (EFAULT);
25506393Scg149915 		}
25516393Scg149915 
25526393Scg149915 		tex.offset = tex32.offset;
25536393Scg149915 		tex.pitch = tex32.pitch;
25546393Scg149915 		tex.format = tex32.format;
25556393Scg149915 		tex.width = tex32.width;
25566393Scg149915 		tex.height = tex32.height;
25576393Scg149915 		tex.image = (void*)(uintptr_t)tex32.image;
25586393Scg149915 
25596393Scg149915 		image.x = image32.x;
25606393Scg149915 		image.y = image32.y;
25616393Scg149915 		image.width = image32.width;
25626393Scg149915 		image.height = image32.height;
25636393Scg149915 		image.data = (void*)(uintptr_t)image32.data;
25646393Scg149915 
25656393Scg149915 	} else {
25666393Scg149915 #endif
25676393Scg149915 		DRM_COPYFROM_WITH_RETURN(&tex, (void *)data, sizeof (tex));
25686393Scg149915 		if (tex.image == NULL) {
25696393Scg149915 			return (EINVAL);
25706393Scg149915 		}
25716393Scg149915 		if (DRM_COPY_FROM_USER(&image,
25726393Scg149915 		    (drm_radeon_tex_image_t *)tex.image, sizeof (image))) {
25736393Scg149915 			return (EFAULT);
25746393Scg149915 		}
25756393Scg149915 #ifdef _MULTI_DATAMODEL
25766393Scg149915 	}
25776393Scg149915 #endif
25786393Scg149915 
25796393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
25806393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
25816393Scg149915 
25826393Scg149915 	ret = radeon_cp_dispatch_texture(fpriv, dev, &tex, &image, mode);
25836393Scg149915 
25846393Scg149915 	COMMIT_RING();
25856393Scg149915 	return (ret);
25866393Scg149915 }
25876393Scg149915 
25886393Scg149915 /*ARGSUSED*/
radeon_cp_stipple(DRM_IOCTL_ARGS)25896393Scg149915 static int radeon_cp_stipple(DRM_IOCTL_ARGS)
25906393Scg149915 {
25916393Scg149915 	DRM_DEVICE;
25926393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
25936393Scg149915 	drm_radeon_stipple_t stipple;
25946393Scg149915 	u32 mask[32];
25956393Scg149915 
25966393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
25976393Scg149915 
25986393Scg149915 #ifdef _MULTI_DATAMODEL
25996393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
26006393Scg149915 		drm_radeon_stipple_32_t stipple32;
26016393Scg149915 		DRM_COPYFROM_WITH_RETURN(&stipple32, (void *)data,
26026393Scg149915 		    sizeof (stipple32));
26036393Scg149915 		stipple.mask = (void *)(uintptr_t)stipple32.mask;
26046393Scg149915 	} else {
26056393Scg149915 #endif
26066393Scg149915 		DRM_COPYFROM_WITH_RETURN(&stipple, (void *)data,
26076393Scg149915 		    sizeof (stipple));
26086393Scg149915 #ifdef _MULTI_DATAMODEL
26096393Scg149915 	}
26106393Scg149915 #endif
26116393Scg149915 	if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof (u32)))
26126393Scg149915 		return (EFAULT);
26136393Scg149915 
26146393Scg149915 
26156393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
26166393Scg149915 
26176393Scg149915 	radeon_cp_dispatch_stipple(dev, mask);
26186393Scg149915 
26196393Scg149915 	COMMIT_RING();
26206393Scg149915 	return (0);
26216393Scg149915 }
26226393Scg149915 
26236393Scg149915 /*ARGSUSED*/
radeon_cp_indirect(DRM_IOCTL_ARGS)26246393Scg149915 static int radeon_cp_indirect(DRM_IOCTL_ARGS)
26256393Scg149915 {
26266393Scg149915 	DRM_DEVICE;
26276393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
26286393Scg149915 	drm_device_dma_t *dma = dev->dma;
26296393Scg149915 	drm_buf_t *buf;
26306393Scg149915 	drm_radeon_indirect_t indirect;
26316393Scg149915 	RING_LOCALS;
26326393Scg149915 
26336393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
26346393Scg149915 
26356393Scg149915 	if (!dev_priv) {
26366393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
26376393Scg149915 		return (EINVAL);
26386393Scg149915 	}
26396393Scg149915 
26406393Scg149915 	DRM_COPYFROM_WITH_RETURN(&indirect, (void *) data, sizeof (indirect));
26416393Scg149915 
26426393Scg149915 	DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
26436393Scg149915 	    indirect.idx, indirect.start, indirect.end, indirect.discard);
26446393Scg149915 
26456393Scg149915 	if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
26466393Scg149915 		DRM_ERROR("buffer index %d (of %d max)\n",
26476393Scg149915 		    indirect.idx, dma->buf_count - 1);
26486393Scg149915 		return (EINVAL);
26496393Scg149915 	}
26506393Scg149915 
26516393Scg149915 	buf = dma->buflist[indirect.idx];
26526393Scg149915 
26536393Scg149915 	if (buf->filp != fpriv) {
26546393Scg149915 		DRM_ERROR("process %d using buffer owned by %p\n",
26556393Scg149915 		    DRM_CURRENTPID, buf->filp);
26566393Scg149915 		return (EINVAL);
26576393Scg149915 	}
26586393Scg149915 	if (buf->pending) {
26596393Scg149915 		DRM_ERROR("sending pending buffer %d\n", indirect.idx);
26606393Scg149915 		return (EINVAL);
26616393Scg149915 	}
26626393Scg149915 
26636393Scg149915 	if (indirect.start < buf->used) {
26646393Scg149915 		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
26656393Scg149915 		    indirect.start, buf->used);
26666393Scg149915 		return (EINVAL);
26676393Scg149915 	}
26686393Scg149915 
26696393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
26706393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
26716393Scg149915 
26726393Scg149915 	buf->used = indirect.end;
26736393Scg149915 
26746393Scg149915 	/*
26756393Scg149915 	 * Wait for the 3D stream to idle before the indirect buffer
26766393Scg149915 	 * containing 2D acceleration commands is processed.
26776393Scg149915 	 */
26786393Scg149915 	BEGIN_RING(2);
26796393Scg149915 
26806393Scg149915 	RADEON_WAIT_UNTIL_3D_IDLE();
26816393Scg149915 
26826393Scg149915 	ADVANCE_RING();
26836393Scg149915 
26846393Scg149915 	/*
26856393Scg149915 	 * Dispatch the indirect buffer full of commands from the
26866393Scg149915 	 * X server.  This is insecure and is thus only available to
26876393Scg149915 	 * privileged clients.
26886393Scg149915 	 */
26896393Scg149915 	radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
26906393Scg149915 	if (indirect.discard) {
26916393Scg149915 		radeon_cp_discard_buffer(dev, buf);
26926393Scg149915 	}
26936393Scg149915 
26946393Scg149915 	COMMIT_RING();
26956393Scg149915 	return (0);
26966393Scg149915 }
26976393Scg149915 
26986393Scg149915 /*ARGSUSED*/
radeon_cp_vertex2(DRM_IOCTL_ARGS)26996393Scg149915 static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
27006393Scg149915 {
27016393Scg149915 	DRM_DEVICE;
27026393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
27036393Scg149915 	drm_radeon_sarea_t *sarea_priv;
27046393Scg149915 	drm_device_dma_t *dma = dev->dma;
27056393Scg149915 	drm_buf_t *buf;
27066393Scg149915 	drm_radeon_vertex2_t vertex;
27076393Scg149915 	int i;
27086393Scg149915 	unsigned char laststate;
27096393Scg149915 
27106393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
27116393Scg149915 
27126393Scg149915 	if (!dev_priv) {
27136393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
27146393Scg149915 		return (EINVAL);
27156393Scg149915 	}
27166393Scg149915 
27176393Scg149915 	sarea_priv = dev_priv->sarea_priv;
27186393Scg149915 
27196393Scg149915 
27206393Scg149915 #ifdef _MULTI_DATAMODEL
27216393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
27226393Scg149915 		drm_radeon_vertex2_32_t	vertex32;
27236393Scg149915 
27246393Scg149915 		DRM_COPYFROM_WITH_RETURN(&vertex32, (void *) data,
27256393Scg149915 		    sizeof (vertex32));
27266393Scg149915 		vertex.idx = vertex32.idx;
27276393Scg149915 		vertex.discard = vertex32.discard;
27286393Scg149915 		vertex.nr_states = vertex32.nr_states;
27296393Scg149915 		vertex.state = (void *) (uintptr_t)vertex32.state;
27306393Scg149915 		vertex.nr_prims = vertex32.nr_prims;
27316393Scg149915 		vertex.prim = (void *)(uintptr_t)vertex32.prim;
27326393Scg149915 	} else {
27336393Scg149915 #endif
27346393Scg149915 		DRM_COPYFROM_WITH_RETURN(&vertex, (void *) data,
27356393Scg149915 		    sizeof (vertex));
27366393Scg149915 #ifdef _MULTI_DATAMODEL
27376393Scg149915 	}
27386393Scg149915 #endif
27396393Scg149915 
27406393Scg149915 	DRM_DEBUG("pid=%d index=%d discard=%d\n",
27416393Scg149915 	    DRM_CURRENTPID, vertex.idx, vertex.discard);
27426393Scg149915 
27436393Scg149915 	if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
27446393Scg149915 		DRM_ERROR("buffer index %d (of %d max)\n",
27456393Scg149915 		    vertex.idx, dma->buf_count - 1);
27466393Scg149915 		return (EINVAL);
27476393Scg149915 	}
27486393Scg149915 
27496393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
27506393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
27516393Scg149915 
27526393Scg149915 	buf = dma->buflist[vertex.idx];
27536393Scg149915 
27546393Scg149915 	if (buf->filp != fpriv) {
27556393Scg149915 		DRM_ERROR("process %d using buffer owned by %p\n",
27566393Scg149915 		    DRM_CURRENTPID, buf->filp);
27576393Scg149915 		return (EINVAL);
27586393Scg149915 	}
27596393Scg149915 
27606393Scg149915 	if (buf->pending) {
27616393Scg149915 		DRM_ERROR("sending pending buffer %d\n", vertex.idx);
27626393Scg149915 		return (EINVAL);
27636393Scg149915 	}
27646393Scg149915 
27656393Scg149915 	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
27666393Scg149915 		return (EINVAL);
27676393Scg149915 
27686393Scg149915 	for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
27696393Scg149915 		drm_radeon_prim_t prim;
27706393Scg149915 		drm_radeon_tcl_prim_t tclprim;
27716393Scg149915 
27726393Scg149915 		if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof (prim)))
27736393Scg149915 			return (EFAULT);
27746393Scg149915 
27756393Scg149915 		if (prim.stateidx != laststate) {
27766393Scg149915 			drm_radeon_state_t state;
27776393Scg149915 
27786393Scg149915 			if (DRM_COPY_FROM_USER(&state,
27796393Scg149915 			    &vertex.state[prim.stateidx], sizeof (state)))
27806393Scg149915 				return (EFAULT);
27816393Scg149915 
27826393Scg149915 			if (radeon_emit_state2(dev_priv, fpriv, &state)) {
27836393Scg149915 				DRM_ERROR("radeon_emit_state2 failed\n");
27846393Scg149915 				return (EINVAL);
27856393Scg149915 			}
27866393Scg149915 
27876393Scg149915 			laststate = prim.stateidx;
27886393Scg149915 		}
27896393Scg149915 
27906393Scg149915 		tclprim.start = prim.start;
27916393Scg149915 		tclprim.finish = prim.finish;
27926393Scg149915 		tclprim.prim = prim.prim;
27936393Scg149915 		tclprim.vc_format = prim.vc_format;
27946393Scg149915 
27956393Scg149915 		if (prim.prim & RADEON_PRIM_WALK_IND) {
27966393Scg149915 			tclprim.offset = prim.numverts * 64;
27976393Scg149915 			tclprim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
27986393Scg149915 
27996393Scg149915 			radeon_cp_dispatch_indices(dev, buf, &tclprim);
28006393Scg149915 		} else {
28016393Scg149915 			tclprim.numverts = prim.numverts;
28026393Scg149915 			tclprim.offset = 0;	/* not used */
28036393Scg149915 
28046393Scg149915 			radeon_cp_dispatch_vertex(dev, buf, &tclprim);
28056393Scg149915 		}
28066393Scg149915 
28076393Scg149915 		if (sarea_priv->nbox == 1)
28086393Scg149915 			sarea_priv->nbox = 0;
28096393Scg149915 	}
28106393Scg149915 
28116393Scg149915 	if (vertex.discard) {
28126393Scg149915 		radeon_cp_discard_buffer(dev, buf);
28136393Scg149915 	}
28146393Scg149915 
28156393Scg149915 	COMMIT_RING();
28166393Scg149915 	return (0);
28176393Scg149915 }
28186393Scg149915 
radeon_emit_packets(drm_radeon_private_t * dev_priv,drm_file_t * filp_priv,drm_radeon_cmd_header_t header,drm_radeon_kcmd_buffer_t * cmdbuf)28196393Scg149915 static int radeon_emit_packets(drm_radeon_private_t *dev_priv,
28206393Scg149915     drm_file_t *filp_priv, drm_radeon_cmd_header_t header,
28216393Scg149915     drm_radeon_kcmd_buffer_t *cmdbuf)
28226393Scg149915 {
28236393Scg149915 	int id = (int)header.packet.packet_id;
28246393Scg149915 	int sz, reg;
28256393Scg149915 	u32 *data = (u32 *)(uintptr_t)cmdbuf->buf;
28266393Scg149915 	RING_LOCALS;
28276393Scg149915 
28286393Scg149915 	if (id >= RADEON_MAX_STATE_PACKETS)
28296393Scg149915 		return (EINVAL);
28306393Scg149915 
28316393Scg149915 	sz = packet[id].len;
28326393Scg149915 	reg = packet[id].start;
28336393Scg149915 
28346393Scg149915 	if (sz * sizeof (int) > cmdbuf->bufsz) {
28356393Scg149915 		DRM_ERROR("Packet size provided larger than data provided\n");
28366393Scg149915 		return (EINVAL);
28376393Scg149915 	}
28386393Scg149915 
28396393Scg149915 	if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
28406393Scg149915 		DRM_ERROR("Packet verification failed\n");
28416393Scg149915 		return (EINVAL);
28426393Scg149915 	}
28436393Scg149915 
28446393Scg149915 	BEGIN_RING(sz + 1);
28456393Scg149915 	OUT_RING(CP_PACKET0(reg, (sz - 1)));
28466393Scg149915 	OUT_RING_TABLE(data, sz);
28476393Scg149915 	ADVANCE_RING();
28486393Scg149915 
28496393Scg149915 	cmdbuf->buf += sz * sizeof (int);
28506393Scg149915 	cmdbuf->bufsz -= sz * sizeof (int);
28516393Scg149915 	return (0);
28526393Scg149915 }
28536393Scg149915 
28546393Scg149915 static inline int
radeon_emit_scalars(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_kcmd_buffer_t * cmdbuf)28556393Scg149915 radeon_emit_scalars(drm_radeon_private_t *dev_priv,
28566393Scg149915     drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf)
28576393Scg149915 {
28586393Scg149915 	int sz = header.scalars.count;
28596393Scg149915 	int start = header.scalars.offset;
28606393Scg149915 	int stride = header.scalars.stride;
28616393Scg149915 	RING_LOCALS;
28626393Scg149915 
28636393Scg149915 	BEGIN_RING(3 + sz);
28646393Scg149915 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
28656393Scg149915 	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
28666393Scg149915 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
28676393Scg149915 	OUT_RING_TABLE(cmdbuf->buf, sz);
28686393Scg149915 	ADVANCE_RING();
28696393Scg149915 	cmdbuf->buf += sz * sizeof (int);
28706393Scg149915 	cmdbuf->bufsz -= sz * sizeof (int);
28716393Scg149915 	return (0);
28726393Scg149915 }
28736393Scg149915 
28746393Scg149915 /*
28756393Scg149915  * God this is ugly
28766393Scg149915  */
28776393Scg149915 static inline int
radeon_emit_scalars2(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_kcmd_buffer_t * cmdbuf)28786393Scg149915 radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
28796393Scg149915     drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf)
28806393Scg149915 {
28816393Scg149915 	int sz = header.scalars.count;
28826393Scg149915 	int start = ((unsigned int)header.scalars.offset) + 0x100;
28836393Scg149915 	int stride = header.scalars.stride;
28846393Scg149915 	RING_LOCALS;
28856393Scg149915 
28866393Scg149915 	BEGIN_RING(3 + sz);
28876393Scg149915 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
28886393Scg149915 	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
28896393Scg149915 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
28906393Scg149915 	OUT_RING_TABLE(cmdbuf->buf, sz);
28916393Scg149915 	ADVANCE_RING();
28926393Scg149915 	cmdbuf->buf += sz * sizeof (int);
28936393Scg149915 	cmdbuf->bufsz -= sz * sizeof (int);
28946393Scg149915 	return (0);
28956393Scg149915 }
28966393Scg149915 
28976393Scg149915 static inline int
radeon_emit_vectors(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_kcmd_buffer_t * cmdbuf)28986393Scg149915 radeon_emit_vectors(drm_radeon_private_t *dev_priv,
28996393Scg149915     drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf)
29006393Scg149915 {
29016393Scg149915 	int sz = header.vectors.count;
29026393Scg149915 	int start = header.vectors.offset;
29036393Scg149915 	int stride = header.vectors.stride;
29046393Scg149915 	RING_LOCALS;
29056393Scg149915 
29066393Scg149915 	BEGIN_RING(5 + sz);
29076393Scg149915 	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
29086393Scg149915 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
29096393Scg149915 	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
29106393Scg149915 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
29116393Scg149915 	OUT_RING_TABLE(cmdbuf->buf, sz);
29126393Scg149915 	ADVANCE_RING();
29136393Scg149915 
29146393Scg149915 	cmdbuf->buf += sz * sizeof (int);
29156393Scg149915 	cmdbuf->bufsz -= sz * sizeof (int);
29166393Scg149915 	return (0);
29176393Scg149915 }
29186393Scg149915 
29196393Scg149915 static inline int
radeon_emit_veclinear(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_kcmd_buffer_t * cmdbuf)29206393Scg149915 radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
29216393Scg149915     drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf)
29226393Scg149915 {
29236393Scg149915 	int sz = header.veclinear.count * 4;
29246393Scg149915 	int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
29256393Scg149915 	RING_LOCALS;
29266393Scg149915 
29276393Scg149915 		if (!sz)
29286393Scg149915 			return (0);
29296393Scg149915 		if (sz * 4 > cmdbuf->bufsz)
29306393Scg149915 			return (EINVAL);
29316393Scg149915 
29326393Scg149915 	BEGIN_RING(5 + sz);
29336393Scg149915 	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
29346393Scg149915 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
29356393Scg149915 	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
29366393Scg149915 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
29376393Scg149915 	OUT_RING_TABLE(cmdbuf->buf, sz);
29386393Scg149915 	ADVANCE_RING();
29396393Scg149915 
29406393Scg149915 	cmdbuf->buf += sz * sizeof (int);
29416393Scg149915 	cmdbuf->bufsz -= sz * sizeof (int);
29426393Scg149915 	return (0);
29436393Scg149915 }
29446393Scg149915 
29456393Scg149915 static int
radeon_emit_packet3(drm_device_t * dev,drm_file_t * filp_priv,drm_radeon_kcmd_buffer_t * cmdbuf)29466393Scg149915 radeon_emit_packet3(drm_device_t *dev, drm_file_t *filp_priv,
29476393Scg149915     drm_radeon_kcmd_buffer_t *cmdbuf)
29486393Scg149915 {
29496393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
29506393Scg149915 	unsigned int cmdsz;
29516393Scg149915 	int ret;
29526393Scg149915 	RING_LOCALS;
29536393Scg149915 
29546393Scg149915 
29556393Scg149915 	if ((ret = radeon_check_and_fixup_packet3(dev_priv,
29566393Scg149915 	    filp_priv, cmdbuf, &cmdsz))) {
29576393Scg149915 		DRM_ERROR("Packet verification failed\n");
29586393Scg149915 		return (ret);
29596393Scg149915 	}
29606393Scg149915 
29616393Scg149915 	BEGIN_RING(cmdsz);
29626393Scg149915 	OUT_RING_TABLE(cmdbuf->buf, cmdsz);
29636393Scg149915 	ADVANCE_RING();
29646393Scg149915 
29656393Scg149915 	cmdbuf->buf += cmdsz * 4;
29666393Scg149915 	cmdbuf->bufsz -= cmdsz * 4;
29676393Scg149915 	return (0);
29686393Scg149915 }
29696393Scg149915 
radeon_emit_packet3_cliprect(drm_device_t * dev,drm_file_t * filp_priv,drm_radeon_kcmd_buffer_t * cmdbuf,int orig_nbox)29706393Scg149915 static int radeon_emit_packet3_cliprect(drm_device_t *dev,
29716393Scg149915 					drm_file_t *filp_priv,
29726393Scg149915 					drm_radeon_kcmd_buffer_t *cmdbuf,
29736393Scg149915 					int orig_nbox)
29746393Scg149915 {
29756393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
29766393Scg149915 	drm_clip_rect_t box;
29776393Scg149915 	unsigned int cmdsz;
29786393Scg149915 	int ret;
29796393Scg149915 	drm_clip_rect_t __user *boxes = cmdbuf->boxes;
29806393Scg149915 	int i = 0;
29816393Scg149915 	RING_LOCALS;
29826393Scg149915 
29836393Scg149915 	if ((ret = radeon_check_and_fixup_packet3(dev_priv,
29846393Scg149915 	    filp_priv, cmdbuf, &cmdsz))) {
29856393Scg149915 		DRM_ERROR("Packet verification failed\n");
29866393Scg149915 		return (ret);
29876393Scg149915 	}
29886393Scg149915 
29896393Scg149915 	if (!orig_nbox)
29906393Scg149915 		goto out;
29916393Scg149915 
29926393Scg149915 	do {
29936393Scg149915 		if (i < cmdbuf->nbox) {
29946393Scg149915 			if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof (box)))
29956393Scg149915 				return (EFAULT);
29966393Scg149915 			/*
29976393Scg149915 			 * FIXME The second and subsequent times round
29986393Scg149915 			 * this loop, send a WAIT_UNTIL_3D_IDLE before
29996393Scg149915 			 * calling emit_clip_rect(). This fixes a
30006393Scg149915 			 * lockup on fast machines when sending
30016393Scg149915 			 * several cliprects with a cmdbuf, as when
30026393Scg149915 			 * waving a 2D window over a 3D
30036393Scg149915 			 * window. Something in the commands from user
30046393Scg149915 			 * space seems to hang the card when they're
30056393Scg149915 			 * sent several times in a row. That would be
30066393Scg149915 			 * the correct place to fix it but this works
30076393Scg149915 			 * around it until I can figure that out - Tim
30086393Scg149915 			 * Smith
30096393Scg149915 			 */
30106393Scg149915 			if (i) {
30116393Scg149915 				BEGIN_RING(2);
30126393Scg149915 				RADEON_WAIT_UNTIL_3D_IDLE();
30136393Scg149915 				ADVANCE_RING();
30146393Scg149915 			}
30156393Scg149915 			radeon_emit_clip_rect(dev_priv, &box);
30166393Scg149915 		}
30176393Scg149915 
30186393Scg149915 		BEGIN_RING(cmdsz);
30196393Scg149915 		OUT_RING_TABLE(cmdbuf->buf, cmdsz);
30206393Scg149915 		ADVANCE_RING();
30216393Scg149915 
30226393Scg149915 	} while (++i < cmdbuf->nbox);
30236393Scg149915 	if (cmdbuf->nbox == 1)
30246393Scg149915 		cmdbuf->nbox = 0;
30256393Scg149915 
30266393Scg149915 out:
30276393Scg149915 	cmdbuf->buf += cmdsz * 4;
30286393Scg149915 	cmdbuf->bufsz -= cmdsz * 4;
30296393Scg149915 	return (0);
30306393Scg149915 }
30316393Scg149915 
30326393Scg149915 static int
radeon_emit_wait(drm_device_t * dev,int flags)30336393Scg149915 radeon_emit_wait(drm_device_t *dev, int flags)
30346393Scg149915 {
30356393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
30366393Scg149915 	RING_LOCALS;
30376393Scg149915 
30386393Scg149915 	DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
30396393Scg149915 	switch (flags) {
30406393Scg149915 	case RADEON_WAIT_2D:
30416393Scg149915 		BEGIN_RING(2);
30426393Scg149915 		RADEON_WAIT_UNTIL_2D_IDLE();
30436393Scg149915 		ADVANCE_RING();
30446393Scg149915 		break;
30456393Scg149915 	case RADEON_WAIT_3D:
30466393Scg149915 		BEGIN_RING(2);
30476393Scg149915 		RADEON_WAIT_UNTIL_3D_IDLE();
30486393Scg149915 		ADVANCE_RING();
30496393Scg149915 		break;
30506393Scg149915 	case RADEON_WAIT_2D | RADEON_WAIT_3D:
30516393Scg149915 		BEGIN_RING(2);
30526393Scg149915 		RADEON_WAIT_UNTIL_IDLE();
30536393Scg149915 		ADVANCE_RING();
30546393Scg149915 		break;
30556393Scg149915 	default:
30566393Scg149915 		return (EINVAL);
30576393Scg149915 	}
30586393Scg149915 
30596393Scg149915 	return (0);
30606393Scg149915 }
30616393Scg149915 
30626393Scg149915 /*ARGSUSED*/
radeon_cp_cmdbuf(DRM_IOCTL_ARGS)30636393Scg149915 static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
30646393Scg149915 {
30656393Scg149915 	DRM_DEVICE;
30666393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
30676393Scg149915 	drm_device_dma_t *dma = dev->dma;
30686393Scg149915 	drm_buf_t *buf = NULL;
30696393Scg149915 	int idx;
30706393Scg149915 	drm_radeon_kcmd_buffer_t cmdbuf;
30716393Scg149915 	drm_radeon_cmd_header_t header;
30726393Scg149915 	int orig_nbox, orig_bufsz;
30736393Scg149915 	char *kbuf = NULL;
30746393Scg149915 
30756393Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
30766393Scg149915 
30776393Scg149915 	if (!dev_priv) {
30786393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
30796393Scg149915 		return (EINVAL);
30806393Scg149915 	}
30816393Scg149915 
30826393Scg149915 #ifdef _MULTI_DATAMODEL
30836393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
30846393Scg149915 		drm_radeon_kcmd_buffer_32_t cmdbuf32;
30856393Scg149915 
30866393Scg149915 		DRM_COPYFROM_WITH_RETURN(&cmdbuf32, (void *)data,
30876393Scg149915 		    sizeof (cmdbuf32));
30886393Scg149915 		cmdbuf.bufsz = cmdbuf32.bufsz;
30896393Scg149915 		cmdbuf.buf = (void *)(uintptr_t)cmdbuf32.buf;
30906393Scg149915 		cmdbuf.nbox = cmdbuf32.nbox;
30916393Scg149915 		cmdbuf.boxes = (void *)(uintptr_t)cmdbuf32.boxes;
30926393Scg149915 	} else {
30936393Scg149915 #endif
30946393Scg149915 		DRM_COPYFROM_WITH_RETURN(&cmdbuf, (void *) data,
30956393Scg149915 		    sizeof (cmdbuf));
30966393Scg149915 #ifdef _MULTI_DATAMODEL
30976393Scg149915 	}
30986393Scg149915 #endif
30996393Scg149915 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
31006393Scg149915 	VB_AGE_TEST_WITH_RETURN(dev_priv);
31016393Scg149915 
31026393Scg149915 	if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
31036393Scg149915 		return (EINVAL);
31046393Scg149915 	}
31056393Scg149915 
31066393Scg149915 	/*
31076393Scg149915 	 * Allocate an in-kernel area and copy in the cmdbuf. Do this
31086393Scg149915 	 * to avoid races between checking values and using those values
31096393Scg149915 	 * in other code, and simply to avoid a lot of function calls
31106393Scg149915 	 * to copy in data.
31116393Scg149915 	 */
31126393Scg149915 	orig_bufsz = cmdbuf.bufsz;
31136393Scg149915 	if (orig_bufsz != 0) {
31146393Scg149915 		kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
31156393Scg149915 		if (kbuf == NULL)
31166393Scg149915 			return (ENOMEM);
31176393Scg149915 		if (DRM_COPY_FROM_USER(kbuf, (void *)cmdbuf.buf,
31186393Scg149915 		    cmdbuf.bufsz)) {
31196393Scg149915 			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
31206393Scg149915 			return (EFAULT);
31216393Scg149915 		}
31226393Scg149915 		cmdbuf.buf = kbuf;
31236393Scg149915 	}
31246393Scg149915 
31256393Scg149915 	orig_nbox = cmdbuf.nbox;
31266393Scg149915 
31276393Scg149915 	if (dev_priv->microcode_version == UCODE_R300) {
31286393Scg149915 		int temp;
31296393Scg149915 		temp = r300_do_cp_cmdbuf(dev, fpriv, &cmdbuf);
31306393Scg149915 
31316393Scg149915 		if (orig_bufsz != 0)
31326393Scg149915 			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
31336393Scg149915 
31346393Scg149915 		return (temp);
31356393Scg149915 	}
31366393Scg149915 
31376393Scg149915 	/* microcode_version != r300 */
31386393Scg149915 	while (cmdbuf.bufsz >= sizeof (header)) {
31396393Scg149915 
31406393Scg149915 		header.i = *(int *)(uintptr_t)cmdbuf.buf;
31416393Scg149915 		cmdbuf.buf += sizeof (header);
31426393Scg149915 		cmdbuf.bufsz -= sizeof (header);
31436393Scg149915 
31446393Scg149915 		switch (header.header.cmd_type) {
31456393Scg149915 		case RADEON_CMD_PACKET:
31466393Scg149915 			DRM_DEBUG("RADEON_CMD_PACKET\n");
31476393Scg149915 			if (radeon_emit_packets
31486393Scg149915 			    (dev_priv, fpriv, header, &cmdbuf)) {
31496393Scg149915 				DRM_ERROR("radeon_emit_packets failed\n");
31506393Scg149915 				goto err;
31516393Scg149915 			}
31526393Scg149915 			break;
31536393Scg149915 
31546393Scg149915 		case RADEON_CMD_SCALARS:
31556393Scg149915 			DRM_DEBUG("RADEON_CMD_SCALARS\n");
31566393Scg149915 			if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
31576393Scg149915 				DRM_ERROR("radeon_emit_scalars failed\n");
31586393Scg149915 				goto err;
31596393Scg149915 			}
31606393Scg149915 			break;
31616393Scg149915 
31626393Scg149915 		case RADEON_CMD_VECTORS:
31636393Scg149915 			DRM_DEBUG("RADEON_CMD_VECTORS\n");
31646393Scg149915 			if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
31656393Scg149915 				DRM_ERROR("radeon_emit_vectors failed\n");
31666393Scg149915 				goto err;
31676393Scg149915 			}
31686393Scg149915 			break;
31696393Scg149915 
31706393Scg149915 		case RADEON_CMD_DMA_DISCARD:
31716393Scg149915 			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
31726393Scg149915 			idx = header.dma.buf_idx;
31736393Scg149915 			if (idx < 0 || idx >= dma->buf_count) {
31746393Scg149915 				DRM_ERROR("buffer index %d (of %d max)\n",
31756393Scg149915 				    idx, dma->buf_count - 1);
31766393Scg149915 				goto err;
31776393Scg149915 			}
31786393Scg149915 
31796393Scg149915 			buf = dma->buflist[idx];
31806393Scg149915 			if (buf->filp != fpriv || buf->pending) {
31816393Scg149915 				DRM_ERROR("bad buffer %p %p %d\n",
31826393Scg149915 				    buf->filp, fpriv, buf->pending);
31836393Scg149915 				goto err;
31846393Scg149915 			}
31856393Scg149915 
31866393Scg149915 			radeon_cp_discard_buffer(dev, buf);
31876393Scg149915 			break;
31886393Scg149915 
31896393Scg149915 		case RADEON_CMD_PACKET3:
31906393Scg149915 			DRM_DEBUG("RADEON_CMD_PACKET3\n");
31916393Scg149915 			if (radeon_emit_packet3(dev, fpriv, &cmdbuf)) {
31926393Scg149915 				DRM_ERROR("radeon_emit_packet3 failed\n");
31936393Scg149915 				goto err;
31946393Scg149915 			}
31956393Scg149915 			break;
31966393Scg149915 
31976393Scg149915 		case RADEON_CMD_PACKET3_CLIP:
31986393Scg149915 			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
31996393Scg149915 			if (radeon_emit_packet3_cliprect
32006393Scg149915 			    (dev, fpriv, &cmdbuf, orig_nbox)) {
32016393Scg149915 				DRM_ERROR("radeon_emit_packet3_clip failed\n");
32026393Scg149915 				goto err;
32036393Scg149915 			}
32046393Scg149915 			break;
32056393Scg149915 
32066393Scg149915 		case RADEON_CMD_SCALARS2:
32076393Scg149915 			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
32086393Scg149915 			if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
32096393Scg149915 				DRM_ERROR("radeon_emit_scalars2 failed\n");
32106393Scg149915 				goto err;
32116393Scg149915 			}
32126393Scg149915 			break;
32136393Scg149915 
32146393Scg149915 		case RADEON_CMD_WAIT:
32156393Scg149915 			DRM_DEBUG("RADEON_CMD_WAIT\n");
32166393Scg149915 			if (radeon_emit_wait(dev, header.wait.flags)) {
32176393Scg149915 				DRM_ERROR("radeon_emit_wait failed\n");
32186393Scg149915 				goto err;
32196393Scg149915 			}
32206393Scg149915 			break;
32216393Scg149915 		case RADEON_CMD_VECLINEAR:
32226393Scg149915 			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
32236393Scg149915 			if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
32246393Scg149915 				DRM_ERROR("radeon_emit_veclinear failed\n");
32256393Scg149915 				goto err;
32266393Scg149915 			}
32276393Scg149915 			break;
32286393Scg149915 
32296393Scg149915 		default:
32306393Scg149915 			DRM_ERROR("bad cmd_type %d at %p\n",
32316393Scg149915 			    header.header.cmd_type,
32326393Scg149915 			    cmdbuf.buf - sizeof (header));
32336393Scg149915 			goto err;
32346393Scg149915 		}
32356393Scg149915 	}
32366393Scg149915 
32376393Scg149915 	if (orig_bufsz != 0)
32386393Scg149915 		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
32396393Scg149915 
32406393Scg149915 	COMMIT_RING();
32416393Scg149915 	return (0);
32426393Scg149915 
32436393Scg149915 err:
32446393Scg149915 	if (orig_bufsz != 0)
32456393Scg149915 		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
32466393Scg149915 	return (EINVAL);
32476393Scg149915 }
32486393Scg149915 
32496393Scg149915 /*ARGSUSED*/
radeon_cp_getparam(DRM_IOCTL_ARGS)32506393Scg149915 static int radeon_cp_getparam(DRM_IOCTL_ARGS)
32516393Scg149915 {
32526393Scg149915 	DRM_DEVICE;
32536393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
32546393Scg149915 	drm_radeon_getparam_t param;
32556393Scg149915 	int value;
32566393Scg149915 
32576393Scg149915 	if (!dev_priv) {
32586393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
32596393Scg149915 		return (EINVAL);
32606393Scg149915 	}
32616393Scg149915 
32626393Scg149915 #ifdef _MULTI_DATAMODEL
32636393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
32646393Scg149915 		drm_radeon_getparam_32_t param32;
32656393Scg149915 
32666393Scg149915 		DRM_COPYFROM_WITH_RETURN(&param32,
32676393Scg149915 		    (drm_radeon_getparam_32_t *)data, sizeof (param32));
32686393Scg149915 		param.param = param32.param;
32696393Scg149915 		param.value = (void *)(uintptr_t)param32.value;
32706393Scg149915 	} else {
32716393Scg149915 #endif
32726393Scg149915 		DRM_COPYFROM_WITH_RETURN(&param,
32736393Scg149915 		    (drm_radeon_getparam_t *)data, sizeof (param));
32746393Scg149915 #ifdef _MULTI_DATAMODEL
32756393Scg149915 	}
32766393Scg149915 #endif
32776393Scg149915 	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
32786393Scg149915 
32796393Scg149915 	switch (param.param) {
32806393Scg149915 	case RADEON_PARAM_GART_BUFFER_OFFSET:
32816393Scg149915 		value = dev_priv->gart_buffers_offset;
32826393Scg149915 		break;
32836393Scg149915 	case RADEON_PARAM_LAST_FRAME:
32846393Scg149915 		dev_priv->stats.last_frame_reads++;
32856393Scg149915 		value = GET_SCRATCH(0);
32866393Scg149915 		break;
32876393Scg149915 	case RADEON_PARAM_LAST_DISPATCH:
32886393Scg149915 		value = GET_SCRATCH(1);
32896393Scg149915 		break;
32906393Scg149915 	case RADEON_PARAM_LAST_CLEAR:
32916393Scg149915 		dev_priv->stats.last_clear_reads++;
32926393Scg149915 		value = GET_SCRATCH(2);
32936393Scg149915 		break;
32946393Scg149915 	case RADEON_PARAM_IRQ_NR:
32956393Scg149915 		value = dev->irq;
32966393Scg149915 		break;
32976393Scg149915 	case RADEON_PARAM_GART_BASE:
32986393Scg149915 		value = dev_priv->gart_vm_start;
32996393Scg149915 		break;
33006393Scg149915 	case RADEON_PARAM_REGISTER_HANDLE:
33016393Scg149915 		value = dev_priv->mmio->offset;
33026393Scg149915 		break;
33036393Scg149915 	case RADEON_PARAM_STATUS_HANDLE:
33046393Scg149915 		value = dev_priv->ring_rptr_offset;
33056393Scg149915 		break;
33066393Scg149915 #ifndef __LP64__
33076393Scg149915 		/*
33086393Scg149915 		 * This ioctl() doesn't work on 64-bit platforms because
33096393Scg149915 		 * hw_lock is a pointer which can't fit into an int-sized
33106393Scg149915 		 * variable.  According to Michel Dänzer, the ioctl) is
33116393Scg149915 		 * only used on embedded platforms, so not supporting it
33126393Scg149915 		 * shouldn't be a problem.  If the same functionality is
33136393Scg149915 		 * needed on 64-bit platforms, a new ioctl() would have
33146393Scg149915 		 * to be added, so backwards-compatibility for the embedded
33156393Scg149915 		 * platforms can be maintained.  --davidm 4-Feb-2004.
33166393Scg149915 		 */
33176393Scg149915 	case RADEON_PARAM_SAREA_HANDLE:
33186393Scg149915 		/* The lock is the first dword in the sarea. */
33196393Scg149915 		value = (long)dev->lock.hw_lock;
33206393Scg149915 		break;
33216393Scg149915 #endif
33226393Scg149915 	case RADEON_PARAM_GART_TEX_HANDLE:
33236393Scg149915 		value = dev_priv->gart_textures_offset;
33246393Scg149915 		break;
33256393Scg149915 	case RADEON_PARAM_SCRATCH_OFFSET:
33266393Scg149915 		if (!dev_priv->writeback_works)
33276393Scg149915 			return (EINVAL);
33286393Scg149915 		value = RADEON_SCRATCH_REG_OFFSET;
33296393Scg149915 		break;
33306393Scg149915 
33316393Scg149915 	case RADEON_PARAM_CARD_TYPE:
33326393Scg149915 		if (dev_priv->flags & RADEON_IS_PCIE)
33336393Scg149915 			value = RADEON_CARD_PCIE;
33346393Scg149915 		else if (dev_priv->flags & RADEON_IS_AGP)
33356393Scg149915 			value = RADEON_CARD_AGP;
33366393Scg149915 		else
33376393Scg149915 			value = RADEON_CARD_PCI;
33386393Scg149915 		break;
33396393Scg149915 	case RADEON_PARAM_VBLANK_CRTC:
33406393Scg149915 		value = radeon_vblank_crtc_get(dev);
33416393Scg149915 		break;
33426393Scg149915 	default:
33436393Scg149915 		return (EINVAL);
33446393Scg149915 	}
33456393Scg149915 
33466393Scg149915 	if (DRM_COPY_TO_USER(param.value, &value, sizeof (int))) {
33476393Scg149915 		DRM_ERROR("copy_to_user\n");
33486393Scg149915 		return (EFAULT);
33496393Scg149915 	}
33506393Scg149915 	return (0);
33516393Scg149915 }
33526393Scg149915 
33536393Scg149915 /*ARGSUSED*/
radeon_cp_setparam(DRM_IOCTL_ARGS)33546393Scg149915 static int radeon_cp_setparam(DRM_IOCTL_ARGS)
33556393Scg149915 {
33566393Scg149915 	DRM_DEVICE;
33576393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
33586393Scg149915 	drm_radeon_setparam_t sp;
33596393Scg149915 	struct drm_radeon_driver_file_fields *radeon_priv;
33606393Scg149915 
33616393Scg149915 	if (!dev_priv) {
33626393Scg149915 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
33636393Scg149915 		return (EINVAL);
33646393Scg149915 	}
33656393Scg149915 
33666393Scg149915 #ifdef _MULTI_DATAMODEL
33676393Scg149915 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
33686393Scg149915 		drm_radeon_setparam_32_t sp32;
33696393Scg149915 
33706393Scg149915 		DRM_COPYFROM_WITH_RETURN(&sp32, (void *) data, sizeof (sp32));
33716393Scg149915 		sp.param = sp32.param;
33726393Scg149915 		sp.value = sp32.value;
33736393Scg149915 	} else {
33746393Scg149915 #endif
33756393Scg149915 	DRM_COPYFROM_WITH_RETURN(&sp, (void *) data, sizeof (sp));
33766393Scg149915 #ifdef _MULTI_DATAMODEL
33776393Scg149915 	}
33786393Scg149915 #endif
33796393Scg149915 	switch (sp.param) {
33806393Scg149915 	case RADEON_SETPARAM_FB_LOCATION:
33816393Scg149915 		radeon_priv = fpriv->driver_priv;
33826393Scg149915 		radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
33836393Scg149915 		break;
33846393Scg149915 	case RADEON_SETPARAM_SWITCH_TILING:
33856393Scg149915 		if (sp.value == 0) {
33866393Scg149915 			DRM_DEBUG("color tiling disabled\n");
33876393Scg149915 			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
33886393Scg149915 			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
33896393Scg149915 			dev_priv->sarea_priv->tiling_enabled = 0;
33906393Scg149915 		} else if (sp.value == 1) {
33916393Scg149915 			DRM_DEBUG("color tiling enabled\n");
33926393Scg149915 			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
33936393Scg149915 			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
33946393Scg149915 			dev_priv->sarea_priv->tiling_enabled = 1;
33956393Scg149915 		}
33966393Scg149915 		break;
33976393Scg149915 	case RADEON_SETPARAM_PCIGART_LOCATION:
33986393Scg149915 		dev_priv->pcigart_offset = (unsigned long)sp.value;
33996393Scg149915 		break;
34006393Scg149915 	case RADEON_SETPARAM_NEW_MEMMAP:
34016393Scg149915 		dev_priv->new_memmap = (int)sp.value;
34026393Scg149915 		break;
34036393Scg149915 	case RADEON_SETPARAM_VBLANK_CRTC:
34046393Scg149915 		return (radeon_vblank_crtc_set(dev, sp.value));
34056393Scg149915 	default:
34066393Scg149915 		DRM_DEBUG("Invalid parameter %d\n", sp.param);
34076393Scg149915 		return (EINVAL);
34086393Scg149915 	}
34096393Scg149915 
34106393Scg149915 	return (0);
34116393Scg149915 }
34126393Scg149915 
34136393Scg149915 /*
34146393Scg149915  * When a client dies:
34156393Scg149915  *    - Check for and clean up flipped page state
34166393Scg149915  *    - Free any alloced GART memory.
34176393Scg149915  *    - Free any alloced radeon surfaces.
34186393Scg149915  *
34196393Scg149915  * DRM infrastructure takes care of reclaiming dma buffers.
34206393Scg149915  */
34216393Scg149915 void
radeon_driver_preclose(drm_device_t * dev,drm_file_t * filp)34226393Scg149915 radeon_driver_preclose(drm_device_t *dev, drm_file_t *filp)
34236393Scg149915 {
34246393Scg149915 	if (dev->dev_private) {
34256393Scg149915 		drm_radeon_private_t *dev_priv = dev->dev_private;
34266393Scg149915 		if (dev_priv->page_flipping) {
34276393Scg149915 			(void) radeon_do_cleanup_pageflip(dev);
34286393Scg149915 		}
34296393Scg149915 		radeon_mem_release(filp, dev_priv->gart_heap);
34306393Scg149915 		radeon_mem_release(filp, dev_priv->fb_heap);
34316393Scg149915 		radeon_surfaces_release(filp, dev_priv);
34326393Scg149915 	}
34336393Scg149915 }
34346393Scg149915 
34356393Scg149915 void
radeon_driver_lastclose(drm_device_t * dev)34366393Scg149915 radeon_driver_lastclose(drm_device_t *dev)
34376393Scg149915 {
34386393Scg149915 	radeon_do_release(dev);
34396393Scg149915 }
34406393Scg149915 
34416393Scg149915 int
radeon_driver_open(drm_device_t * dev,drm_file_t * filp_priv)34426393Scg149915 radeon_driver_open(drm_device_t *dev, drm_file_t *filp_priv)
34436393Scg149915 {
34446393Scg149915 	drm_radeon_private_t *dev_priv = dev->dev_private;
34456393Scg149915 	struct drm_radeon_driver_file_fields *radeon_priv;
34466393Scg149915 
34476393Scg149915 	radeon_priv =
34486393Scg149915 	    (struct drm_radeon_driver_file_fields *)
34496393Scg149915 	    drm_alloc(sizeof (*radeon_priv), DRM_MEM_FILES);
34506393Scg149915 
34516393Scg149915 	if (!radeon_priv)
34526393Scg149915 		return (-ENOMEM);
34536393Scg149915 
34546393Scg149915 	filp_priv->driver_priv = radeon_priv;
34556393Scg149915 
34566393Scg149915 	if (dev_priv)
34576393Scg149915 		radeon_priv->radeon_fb_delta = dev_priv->fb_location;
34586393Scg149915 	else
34596393Scg149915 		radeon_priv->radeon_fb_delta = 0;
34606393Scg149915 	return (0);
34616393Scg149915 }
34626393Scg149915 
34636393Scg149915 /*ARGSUSED*/
34646393Scg149915 void
radeon_driver_postclose(drm_device_t * dev,drm_file_t * filp_priv)34656393Scg149915 radeon_driver_postclose(drm_device_t *dev, drm_file_t *filp_priv)
34666393Scg149915 {
34676393Scg149915 	struct drm_radeon_driver_file_fields *radeon_priv =
34686393Scg149915 	    filp_priv->driver_priv;
34696393Scg149915 
34706393Scg149915 	drm_free(radeon_priv, sizeof (* radeon_priv), DRM_MEM_FILES);
34716393Scg149915 }
34726393Scg149915 
34736393Scg149915 drm_ioctl_desc_t radeon_ioctls[] = {
34746393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] =
34756393Scg149915 	    {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
34766393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_START)] =
34776393Scg149915 	    {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
34786393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] =
34796393Scg149915 	    {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
34806393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] =
34816393Scg149915 	    {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
34826393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] =
34836393Scg149915 	    {radeon_cp_idle, DRM_AUTH},
34846393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] =
34856393Scg149915 	    {radeon_cp_resume, DRM_AUTH},
34866393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_RESET)] =
34876393Scg149915 	    {radeon_engine_reset, DRM_AUTH},
34886393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] =
34896393Scg149915 	    {radeon_fullscreen, DRM_AUTH},
34906393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_SWAP)] =
34916393Scg149915 	    {radeon_cp_swap, DRM_AUTH},
34926393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CLEAR)] =
34936393Scg149915 	    {radeon_cp_clear, DRM_AUTH},
34946393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_VERTEX)] =
34956393Scg149915 	    {radeon_cp_vertex, DRM_AUTH},
34966393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_INDICES)] =
34976393Scg149915 	    {radeon_cp_indices, DRM_AUTH},
34986393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] =
34996393Scg149915 	    {radeon_cp_texture, DRM_AUTH},
35006393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] =
35016393Scg149915 	    {radeon_cp_stipple, DRM_AUTH},
35026393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] =
35036393Scg149915 	    {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
35046393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] =
35056393Scg149915 	    {radeon_cp_vertex2, DRM_AUTH},
35066393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] =
35076393Scg149915 	    {radeon_cp_cmdbuf, DRM_AUTH},
35086393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] =
35096393Scg149915 	    {radeon_cp_getparam, DRM_AUTH},
35106393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_FLIP)] =
35116393Scg149915 	    {radeon_cp_flip, DRM_AUTH},
35126393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_ALLOC)] =
35136393Scg149915 	    {radeon_mem_alloc, DRM_AUTH},
35146393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_FREE)] =
35156393Scg149915 	    {radeon_mem_free, DRM_AUTH},
35166393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] =
35176393Scg149915 	    {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
35186393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] =
35196393Scg149915 	    {radeon_irq_emit, DRM_AUTH},
35206393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] =
35216393Scg149915 	    {radeon_irq_wait, DRM_AUTH},
35226393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] =
35236393Scg149915 	    {radeon_cp_setparam, DRM_AUTH},
35246393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] =
35256393Scg149915 	    {radeon_surface_alloc, DRM_AUTH},
35266393Scg149915 	[DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] =
35276393Scg149915 	    {radeon_surface_free, DRM_AUTH}
35286393Scg149915 };
35296393Scg149915 
35306393Scg149915 int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
3531