xref: /onnv-gate/usr/src/uts/intel/io/drm/i915_gem_debug.c (revision 11260:eb8c6f2097e8)
1*11260SMiao.Chen@Sun.COM /* BEGIN CSTYLED */
2*11260SMiao.Chen@Sun.COM 
3*11260SMiao.Chen@Sun.COM /*
4*11260SMiao.Chen@Sun.COM  * Copyright (c) 2009, Intel Corporation.
5*11260SMiao.Chen@Sun.COM  * All Rights Reserved.
6*11260SMiao.Chen@Sun.COM  *
7*11260SMiao.Chen@Sun.COM  * Permission is hereby granted, free of charge, to any person obtaining a
8*11260SMiao.Chen@Sun.COM  * copy of this software and associated documentation files (the "Software"),
9*11260SMiao.Chen@Sun.COM  * to deal in the Software without restriction, including without limitation
10*11260SMiao.Chen@Sun.COM  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*11260SMiao.Chen@Sun.COM  * and/or sell copies of the Software, and to permit persons to whom the
12*11260SMiao.Chen@Sun.COM  * Software is furnished to do so, subject to the following conditions:
13*11260SMiao.Chen@Sun.COM  *
14*11260SMiao.Chen@Sun.COM  * The above copyright notice and this permission notice (including the next
15*11260SMiao.Chen@Sun.COM  * paragraph) shall be included in all copies or substantial portions of the
16*11260SMiao.Chen@Sun.COM  * Software.
17*11260SMiao.Chen@Sun.COM  *
18*11260SMiao.Chen@Sun.COM  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*11260SMiao.Chen@Sun.COM  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*11260SMiao.Chen@Sun.COM  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21*11260SMiao.Chen@Sun.COM  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*11260SMiao.Chen@Sun.COM  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23*11260SMiao.Chen@Sun.COM  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24*11260SMiao.Chen@Sun.COM  * IN THE SOFTWARE.
25*11260SMiao.Chen@Sun.COM  *
26*11260SMiao.Chen@Sun.COM  * Authors:
27*11260SMiao.Chen@Sun.COM  *    Keith Packard <keithp@keithp.com>
28*11260SMiao.Chen@Sun.COM  *
29*11260SMiao.Chen@Sun.COM  */
30*11260SMiao.Chen@Sun.COM 
31*11260SMiao.Chen@Sun.COM /*
32*11260SMiao.Chen@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
33*11260SMiao.Chen@Sun.COM  * Use is subject to license terms.
34*11260SMiao.Chen@Sun.COM  */
35*11260SMiao.Chen@Sun.COM 
36*11260SMiao.Chen@Sun.COM #include "drmP.h"
37*11260SMiao.Chen@Sun.COM #include "drm.h"
38*11260SMiao.Chen@Sun.COM #include "i915_drm.h"
39*11260SMiao.Chen@Sun.COM #include "i915_drv.h"
40*11260SMiao.Chen@Sun.COM 
41*11260SMiao.Chen@Sun.COM #define BUFFER_FAIL(_count, _len, _name) { 			\
42*11260SMiao.Chen@Sun.COM 	DRM_ERROR("Buffer size too small in %s (%d < %d)\n",	\
43*11260SMiao.Chen@Sun.COM 	    (_name), (_count), (_len));				\
44*11260SMiao.Chen@Sun.COM 	(*failures)++;						\
45*11260SMiao.Chen@Sun.COM 	return count;						\
46*11260SMiao.Chen@Sun.COM }
47*11260SMiao.Chen@Sun.COM 
48*11260SMiao.Chen@Sun.COM 
49*11260SMiao.Chen@Sun.COM static uint32_t saved_s2 = 0, saved_s4 = 0;
50*11260SMiao.Chen@Sun.COM static char saved_s2_set = 0, saved_s4_set = 0;
51*11260SMiao.Chen@Sun.COM 
52*11260SMiao.Chen@Sun.COM static float
int_as_float(uint32_t intval)53*11260SMiao.Chen@Sun.COM int_as_float(uint32_t intval)
54*11260SMiao.Chen@Sun.COM {
55*11260SMiao.Chen@Sun.COM     union intfloat {
56*11260SMiao.Chen@Sun.COM 	uint32_t i;
57*11260SMiao.Chen@Sun.COM 	float f;
58*11260SMiao.Chen@Sun.COM     } uval;
59*11260SMiao.Chen@Sun.COM 
60*11260SMiao.Chen@Sun.COM     uval.i = intval;
61*11260SMiao.Chen@Sun.COM     return uval.f;
62*11260SMiao.Chen@Sun.COM }
63*11260SMiao.Chen@Sun.COM 
64*11260SMiao.Chen@Sun.COM static void
instr_out(uint32_t * data,uint32_t hw_offset,unsigned int index,const char * fmt,...)65*11260SMiao.Chen@Sun.COM instr_out(uint32_t *data, uint32_t hw_offset, unsigned int index,
66*11260SMiao.Chen@Sun.COM 	  const char *fmt, ...)
67*11260SMiao.Chen@Sun.COM {
68*11260SMiao.Chen@Sun.COM 
69*11260SMiao.Chen@Sun.COM     DRM_ERROR("0x%08x: 0x%08x:%s ", hw_offset + index * 4, data[index],
70*11260SMiao.Chen@Sun.COM 	    index == 0 ? "" : "  ");
71*11260SMiao.Chen@Sun.COM         va_list ap;
72*11260SMiao.Chen@Sun.COM 
73*11260SMiao.Chen@Sun.COM         va_start(ap, fmt);
74*11260SMiao.Chen@Sun.COM         vcmn_err(CE_WARN, fmt, ap);
75*11260SMiao.Chen@Sun.COM         va_end(ap);
76*11260SMiao.Chen@Sun.COM 
77*11260SMiao.Chen@Sun.COM }
78*11260SMiao.Chen@Sun.COM 
79*11260SMiao.Chen@Sun.COM static int
decode_mi(uint32_t * data,int count,uint32_t hw_offset,int * failures)80*11260SMiao.Chen@Sun.COM decode_mi(uint32_t *data, int count, uint32_t hw_offset, int *failures)
81*11260SMiao.Chen@Sun.COM {
82*11260SMiao.Chen@Sun.COM     unsigned int opcode;
83*11260SMiao.Chen@Sun.COM 
84*11260SMiao.Chen@Sun.COM     struct {
85*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
86*11260SMiao.Chen@Sun.COM 	int min_len;
87*11260SMiao.Chen@Sun.COM 	int max_len;
88*11260SMiao.Chen@Sun.COM 	char *name;
89*11260SMiao.Chen@Sun.COM     } opcodes_mi[] = {
90*11260SMiao.Chen@Sun.COM 	{ 0x08, 1, 1, "MI_ARB_ON_OFF" },
91*11260SMiao.Chen@Sun.COM 	{ 0x0a, 1, 1, "MI_BATCH_BUFFER_END" },
92*11260SMiao.Chen@Sun.COM 	{ 0x31, 2, 2, "MI_BATCH_BUFFER_START" },
93*11260SMiao.Chen@Sun.COM 	{ 0x14, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
94*11260SMiao.Chen@Sun.COM 	{ 0x04, 1, 1, "MI_FLUSH" },
95*11260SMiao.Chen@Sun.COM 	{ 0x22, 3, 3, "MI_LOAD_REGISTER_IMM" },
96*11260SMiao.Chen@Sun.COM 	{ 0x13, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
97*11260SMiao.Chen@Sun.COM 	{ 0x12, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
98*11260SMiao.Chen@Sun.COM 	{ 0x00, 1, 1, "MI_NOOP" },
99*11260SMiao.Chen@Sun.COM 	{ 0x11, 2, 2, "MI_OVERLAY_FLIP" },
100*11260SMiao.Chen@Sun.COM 	{ 0x07, 1, 1, "MI_REPORT_HEAD" },
101*11260SMiao.Chen@Sun.COM 	{ 0x18, 2, 2, "MI_SET_CONTEXT" },
102*11260SMiao.Chen@Sun.COM 	{ 0x20, 3, 4, "MI_STORE_DATA_IMM" },
103*11260SMiao.Chen@Sun.COM 	{ 0x21, 3, 4, "MI_STORE_DATA_INDEX" },
104*11260SMiao.Chen@Sun.COM 	{ 0x24, 3, 3, "MI_STORE_REGISTER_MEM" },
105*11260SMiao.Chen@Sun.COM 	{ 0x02, 1, 1, "MI_USER_INTERRUPT" },
106*11260SMiao.Chen@Sun.COM 	{ 0x03, 1, 1, "MI_WAIT_FOR_EVENT" },
107*11260SMiao.Chen@Sun.COM     };
108*11260SMiao.Chen@Sun.COM 
109*11260SMiao.Chen@Sun.COM 
110*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_mi) / sizeof(opcodes_mi[0]);
111*11260SMiao.Chen@Sun.COM 	 opcode++) {
112*11260SMiao.Chen@Sun.COM 	if ((data[0] & 0x1f800000) >> 23 == opcodes_mi[opcode].opcode) {
113*11260SMiao.Chen@Sun.COM 	    unsigned int len = 1, i;
114*11260SMiao.Chen@Sun.COM 
115*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_mi[opcode].name);
116*11260SMiao.Chen@Sun.COM 	    if (opcodes_mi[opcode].max_len > 1) {
117*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0x000000ff) + 2;
118*11260SMiao.Chen@Sun.COM 		if (len < opcodes_mi[opcode].min_len ||
119*11260SMiao.Chen@Sun.COM 		    len > opcodes_mi[opcode].max_len)
120*11260SMiao.Chen@Sun.COM 		{
121*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad length in %s\n",
122*11260SMiao.Chen@Sun.COM 			    opcodes_mi[opcode].name);
123*11260SMiao.Chen@Sun.COM 		}
124*11260SMiao.Chen@Sun.COM 	    }
125*11260SMiao.Chen@Sun.COM 
126*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
127*11260SMiao.Chen@Sun.COM 		if (i >= count)
128*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, opcodes_mi[opcode].name);
129*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
130*11260SMiao.Chen@Sun.COM 	    }
131*11260SMiao.Chen@Sun.COM 
132*11260SMiao.Chen@Sun.COM 	    return len;
133*11260SMiao.Chen@Sun.COM 	}
134*11260SMiao.Chen@Sun.COM     }
135*11260SMiao.Chen@Sun.COM 
136*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "MI UNKNOWN\n");
137*11260SMiao.Chen@Sun.COM     (*failures)++;
138*11260SMiao.Chen@Sun.COM     return 1;
139*11260SMiao.Chen@Sun.COM }
140*11260SMiao.Chen@Sun.COM 
141*11260SMiao.Chen@Sun.COM static int
decode_2d(uint32_t * data,int count,uint32_t hw_offset,int * failures)142*11260SMiao.Chen@Sun.COM decode_2d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
143*11260SMiao.Chen@Sun.COM {
144*11260SMiao.Chen@Sun.COM     unsigned int opcode, len;
145*11260SMiao.Chen@Sun.COM     char *format = NULL;
146*11260SMiao.Chen@Sun.COM 
147*11260SMiao.Chen@Sun.COM     struct {
148*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
149*11260SMiao.Chen@Sun.COM 	int min_len;
150*11260SMiao.Chen@Sun.COM 	int max_len;
151*11260SMiao.Chen@Sun.COM 	char *name;
152*11260SMiao.Chen@Sun.COM     } opcodes_2d[] = {
153*11260SMiao.Chen@Sun.COM 	{ 0x40, 5, 5, "COLOR_BLT" },
154*11260SMiao.Chen@Sun.COM 	{ 0x43, 6, 6, "SRC_COPY_BLT" },
155*11260SMiao.Chen@Sun.COM 	{ 0x01, 8, 8, "XY_SETUP_BLT" },
156*11260SMiao.Chen@Sun.COM 	{ 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" },
157*11260SMiao.Chen@Sun.COM 	{ 0x03, 3, 3, "XY_SETUP_CLIP_BLT" },
158*11260SMiao.Chen@Sun.COM 	{ 0x24, 2, 2, "XY_PIXEL_BLT" },
159*11260SMiao.Chen@Sun.COM 	{ 0x25, 3, 3, "XY_SCANLINES_BLT" },
160*11260SMiao.Chen@Sun.COM 	{ 0x26, 4, 4, "Y_TEXT_BLT" },
161*11260SMiao.Chen@Sun.COM 	{ 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" },
162*11260SMiao.Chen@Sun.COM 	{ 0x50, 6, 6, "XY_COLOR_BLT" },
163*11260SMiao.Chen@Sun.COM 	{ 0x51, 6, 6, "XY_PAT_BLT" },
164*11260SMiao.Chen@Sun.COM 	{ 0x76, 8, 8, "XY_PAT_CHROMA_BLT" },
165*11260SMiao.Chen@Sun.COM 	{ 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" },
166*11260SMiao.Chen@Sun.COM 	{ 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" },
167*11260SMiao.Chen@Sun.COM 	{ 0x52, 9, 9, "XY_MONO_PAT_BLT" },
168*11260SMiao.Chen@Sun.COM 	{ 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" },
169*11260SMiao.Chen@Sun.COM 	{ 0x53, 8, 8, "XY_SRC_COPY_BLT" },
170*11260SMiao.Chen@Sun.COM 	{ 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" },
171*11260SMiao.Chen@Sun.COM 	{ 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" },
172*11260SMiao.Chen@Sun.COM 	{ 0x55, 9, 9, "XY_FULL_BLT" },
173*11260SMiao.Chen@Sun.COM 	{ 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" },
174*11260SMiao.Chen@Sun.COM 	{ 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" },
175*11260SMiao.Chen@Sun.COM 	{ 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" },
176*11260SMiao.Chen@Sun.COM 	{ 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" },
177*11260SMiao.Chen@Sun.COM 	{ 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" },
178*11260SMiao.Chen@Sun.COM     };
179*11260SMiao.Chen@Sun.COM 
180*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0x1fc00000) >> 22) {
181*11260SMiao.Chen@Sun.COM     case 0x50:
182*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
183*11260SMiao.Chen@Sun.COM 		  "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n",
184*11260SMiao.Chen@Sun.COM 		  (data[0] & (1 << 20)) ? "en" : "dis",
185*11260SMiao.Chen@Sun.COM 		  (data[0] & (1 << 21)) ? "en" : "dis",
186*11260SMiao.Chen@Sun.COM 		  (data[0] >> 11) & 1);
187*11260SMiao.Chen@Sun.COM 
188*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x000000ff) + 2;
189*11260SMiao.Chen@Sun.COM 	if (len != 6)
190*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in XY_COLOR_BLT\n");
191*11260SMiao.Chen@Sun.COM 	if (count < 6)
192*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "XY_COLOR_BLT");
193*11260SMiao.Chen@Sun.COM 
194*11260SMiao.Chen@Sun.COM 	switch ((data[1] >> 24) & 0x3) {
195*11260SMiao.Chen@Sun.COM 	case 0:
196*11260SMiao.Chen@Sun.COM 	    format="8";
197*11260SMiao.Chen@Sun.COM 	    break;
198*11260SMiao.Chen@Sun.COM 	case 1:
199*11260SMiao.Chen@Sun.COM 	    format="565";
200*11260SMiao.Chen@Sun.COM 	    break;
201*11260SMiao.Chen@Sun.COM 	case 2:
202*11260SMiao.Chen@Sun.COM 	    format="1555";
203*11260SMiao.Chen@Sun.COM 	    break;
204*11260SMiao.Chen@Sun.COM 	case 3:
205*11260SMiao.Chen@Sun.COM 	    format="8888";
206*11260SMiao.Chen@Sun.COM 	    break;
207*11260SMiao.Chen@Sun.COM 	}
208*11260SMiao.Chen@Sun.COM 
209*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "format %s, pitch %d, "
210*11260SMiao.Chen@Sun.COM 		  "clipping %sabled\n", format,
211*11260SMiao.Chen@Sun.COM 		  (short)(data[1] & 0xffff),
212*11260SMiao.Chen@Sun.COM 		  data[1] & (1 << 30) ? "en" : "dis");
213*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "(%d,%d)\n",
214*11260SMiao.Chen@Sun.COM 		  data[2] & 0xffff, data[2] >> 16);
215*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "(%d,%d)\n",
216*11260SMiao.Chen@Sun.COM 		  data[3] & 0xffff, data[3] >> 16);
217*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 4, "offset 0x%08x\n", data[4]);
218*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 5, "color\n");
219*11260SMiao.Chen@Sun.COM 	return len;
220*11260SMiao.Chen@Sun.COM     case 0x53:
221*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
222*11260SMiao.Chen@Sun.COM 		  "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, "
223*11260SMiao.Chen@Sun.COM 		  "src tile %d, dst tile %d)\n",
224*11260SMiao.Chen@Sun.COM 		  (data[0] & (1 << 20)) ? "en" : "dis",
225*11260SMiao.Chen@Sun.COM 		  (data[0] & (1 << 21)) ? "en" : "dis",
226*11260SMiao.Chen@Sun.COM 		  (data[0] >> 15) & 1,
227*11260SMiao.Chen@Sun.COM 		  (data[0] >> 11) & 1);
228*11260SMiao.Chen@Sun.COM 
229*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x000000ff) + 2;
230*11260SMiao.Chen@Sun.COM 	if (len != 8)
231*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in XY_SRC_COPY_BLT\n");
232*11260SMiao.Chen@Sun.COM 	if (count < 8)
233*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "XY_SRC_COPY_BLT");
234*11260SMiao.Chen@Sun.COM 
235*11260SMiao.Chen@Sun.COM 	switch ((data[1] >> 24) & 0x3) {
236*11260SMiao.Chen@Sun.COM 	case 0:
237*11260SMiao.Chen@Sun.COM 	    format="8";
238*11260SMiao.Chen@Sun.COM 	    break;
239*11260SMiao.Chen@Sun.COM 	case 1:
240*11260SMiao.Chen@Sun.COM 	    format="565";
241*11260SMiao.Chen@Sun.COM 	    break;
242*11260SMiao.Chen@Sun.COM 	case 2:
243*11260SMiao.Chen@Sun.COM 	    format="1555";
244*11260SMiao.Chen@Sun.COM 	    break;
245*11260SMiao.Chen@Sun.COM 	case 3:
246*11260SMiao.Chen@Sun.COM 	    format="8888";
247*11260SMiao.Chen@Sun.COM 	    break;
248*11260SMiao.Chen@Sun.COM 	}
249*11260SMiao.Chen@Sun.COM 
250*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "format %s, dst pitch %d, "
251*11260SMiao.Chen@Sun.COM 		  "clipping %sabled\n", format,
252*11260SMiao.Chen@Sun.COM 		  (short)(data[1] & 0xffff),
253*11260SMiao.Chen@Sun.COM 		  data[1] & (1 << 30) ? "en" : "dis");
254*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "dst (%d,%d)\n",
255*11260SMiao.Chen@Sun.COM 		  data[2] & 0xffff, data[2] >> 16);
256*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "dst (%d,%d)\n",
257*11260SMiao.Chen@Sun.COM 		  data[3] & 0xffff, data[3] >> 16);
258*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 4, "dst offset 0x%08x\n", data[4]);
259*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 5, "src (%d,%d)\n",
260*11260SMiao.Chen@Sun.COM 		  data[5] & 0xffff, data[5] >> 16);
261*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 6, "src pitch %d\n",
262*11260SMiao.Chen@Sun.COM 		  (short)(data[6] & 0xffff));
263*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 7, "src offset 0x%08x\n", data[7]);
264*11260SMiao.Chen@Sun.COM 	return len;
265*11260SMiao.Chen@Sun.COM     }
266*11260SMiao.Chen@Sun.COM 
267*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_2d) / sizeof(opcodes_2d[0]);
268*11260SMiao.Chen@Sun.COM 	 opcode++) {
269*11260SMiao.Chen@Sun.COM 	if ((data[0] & 0x1fc00000) >> 22 == opcodes_2d[opcode].opcode) {
270*11260SMiao.Chen@Sun.COM 	    unsigned int i;
271*11260SMiao.Chen@Sun.COM 
272*11260SMiao.Chen@Sun.COM 	    len = 1;
273*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_2d[opcode].name);
274*11260SMiao.Chen@Sun.COM 	    if (opcodes_2d[opcode].max_len > 1) {
275*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0x000000ff) + 2;
276*11260SMiao.Chen@Sun.COM 		if (len < opcodes_2d[opcode].min_len ||
277*11260SMiao.Chen@Sun.COM 		    len > opcodes_2d[opcode].max_len)
278*11260SMiao.Chen@Sun.COM 		{
279*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad count in %s\n", opcodes_2d[opcode].name);
280*11260SMiao.Chen@Sun.COM 		}
281*11260SMiao.Chen@Sun.COM 	    }
282*11260SMiao.Chen@Sun.COM 
283*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
284*11260SMiao.Chen@Sun.COM 		if (i >= count)
285*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, opcodes_2d[opcode].name);
286*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
287*11260SMiao.Chen@Sun.COM 	    }
288*11260SMiao.Chen@Sun.COM 
289*11260SMiao.Chen@Sun.COM 	    return len;
290*11260SMiao.Chen@Sun.COM 	}
291*11260SMiao.Chen@Sun.COM     }
292*11260SMiao.Chen@Sun.COM 
293*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "2D UNKNOWN\n");
294*11260SMiao.Chen@Sun.COM     (*failures)++;
295*11260SMiao.Chen@Sun.COM     return 1;
296*11260SMiao.Chen@Sun.COM }
297*11260SMiao.Chen@Sun.COM 
298*11260SMiao.Chen@Sun.COM /*ARGSUSED*/
299*11260SMiao.Chen@Sun.COM static int
decode_3d_1c(uint32_t * data,int count,uint32_t hw_offset,int * failures)300*11260SMiao.Chen@Sun.COM decode_3d_1c(uint32_t *data, int count, uint32_t hw_offset, int *failures)
301*11260SMiao.Chen@Sun.COM {
302*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0x00f80000) >> 19) {
303*11260SMiao.Chen@Sun.COM     case 0x11:
304*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_DEPTH_SUBRECTANGLE_DISALBE\n");
305*11260SMiao.Chen@Sun.COM 	return 1;
306*11260SMiao.Chen@Sun.COM     case 0x10:
307*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_SCISSOR_ENABLE\n");
308*11260SMiao.Chen@Sun.COM 	return 1;
309*11260SMiao.Chen@Sun.COM     case 0x01:
310*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_MAP_COORD_SET_I830\n");
311*11260SMiao.Chen@Sun.COM 	return 1;
312*11260SMiao.Chen@Sun.COM     case 0x0a:
313*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_MAP_CUBE_I830\n");
314*11260SMiao.Chen@Sun.COM 	return 1;
315*11260SMiao.Chen@Sun.COM     case 0x05:
316*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_MAP_TEX_STREAM_I830\n");
317*11260SMiao.Chen@Sun.COM 	return 1;
318*11260SMiao.Chen@Sun.COM     }
319*11260SMiao.Chen@Sun.COM 
320*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
321*11260SMiao.Chen@Sun.COM     (*failures)++;
322*11260SMiao.Chen@Sun.COM     return 1;
323*11260SMiao.Chen@Sun.COM }
324*11260SMiao.Chen@Sun.COM 
325*11260SMiao.Chen@Sun.COM static int
decode_3d_1d(uint32_t * data,int count,uint32_t hw_offset,int * failures,int i830)326*11260SMiao.Chen@Sun.COM decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i830)
327*11260SMiao.Chen@Sun.COM {
328*11260SMiao.Chen@Sun.COM     unsigned int len, i, c, opcode, word, map, sampler, instr;
329*11260SMiao.Chen@Sun.COM 
330*11260SMiao.Chen@Sun.COM     struct {
331*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
332*11260SMiao.Chen@Sun.COM 	int i830_only;
333*11260SMiao.Chen@Sun.COM 	int min_len;
334*11260SMiao.Chen@Sun.COM 	int max_len;
335*11260SMiao.Chen@Sun.COM 	char *name;
336*11260SMiao.Chen@Sun.COM     } opcodes_3d_1d[] = {
337*11260SMiao.Chen@Sun.COM 	{ 0x8e, 0, 3, 3, "3DSTATE_BUFFER_INFO" },
338*11260SMiao.Chen@Sun.COM 	{ 0x86, 0, 4, 4, "3DSTATE_CHROMA_KEY" },
339*11260SMiao.Chen@Sun.COM 	{ 0x9c, 0, 1, 1, "3DSTATE_CLEAR_PARAMETERS" },
340*11260SMiao.Chen@Sun.COM 	{ 0x88, 0, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
341*11260SMiao.Chen@Sun.COM 	{ 0x99, 0, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
342*11260SMiao.Chen@Sun.COM 	{ 0x9a, 0, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
343*11260SMiao.Chen@Sun.COM 	{ 0x98, 0, 2, 2, "3DSTATE_DEFAULT_Z" },
344*11260SMiao.Chen@Sun.COM 	{ 0x97, 0, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
345*11260SMiao.Chen@Sun.COM 	{ 0x85, 0, 2, 2, "3DSTATE_DEST_BUFFER_VARIABLES" },
346*11260SMiao.Chen@Sun.COM 	{ 0x80, 0, 5, 5, "3DSTATE_DRAWING_RECTANGLE" },
347*11260SMiao.Chen@Sun.COM 	{ 0x8e, 0, 3, 3, "3DSTATE_BUFFER_INFO" },
348*11260SMiao.Chen@Sun.COM 	{ 0x9d, 0, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
349*11260SMiao.Chen@Sun.COM 	{ 0x9e, 0, 4, 4, "3DSTATE_MONO_FILTER" },
350*11260SMiao.Chen@Sun.COM 	{ 0x89, 0, 4, 4, "3DSTATE_FOG_MODE" },
351*11260SMiao.Chen@Sun.COM 	{ 0x8f, 0, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
352*11260SMiao.Chen@Sun.COM 	{ 0x81, 0, 3, 3, "3DSTATE_SCISSOR_RECTANGLE" },
353*11260SMiao.Chen@Sun.COM 	{ 0x83, 0, 2, 2, "3DSTATE_SPAN_STIPPLE" },
354*11260SMiao.Chen@Sun.COM 	{ 0x8c, 1, 2, 2, "3DSTATE_MAP_COORD_TRANSFORM_I830" },
355*11260SMiao.Chen@Sun.COM 	{ 0x8b, 1, 2, 2, "3DSTATE_MAP_VERTEX_TRANSFORM_I830" },
356*11260SMiao.Chen@Sun.COM 	{ 0x8d, 1, 3, 3, "3DSTATE_W_STATE_I830" },
357*11260SMiao.Chen@Sun.COM 	{ 0x01, 1, 2, 2, "3DSTATE_COLOR_FACTOR_I830" },
358*11260SMiao.Chen@Sun.COM 	{ 0x02, 1, 2, 2, "3DSTATE_MAP_COORD_SETBIND_I830" },
359*11260SMiao.Chen@Sun.COM     };
360*11260SMiao.Chen@Sun.COM 
361*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0x00ff0000) >> 16) {
362*11260SMiao.Chen@Sun.COM     case 0x07:
363*11260SMiao.Chen@Sun.COM 	/* This instruction is unusual.  A 0 length means just 1 DWORD instead of
364*11260SMiao.Chen@Sun.COM 	 * 2.  The 0 length is specified in one place to be unsupported, but
365*11260SMiao.Chen@Sun.COM 	 * stated to be required in another, and 0 length LOAD_INDIRECTs appear
366*11260SMiao.Chen@Sun.COM 	 * to cause no harm at least.
367*11260SMiao.Chen@Sun.COM 	 */
368*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_LOAD_INDIRECT\n");
369*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x000000ff) + 1;
370*11260SMiao.Chen@Sun.COM 	i = 1;
371*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x01 << 8)) {
372*11260SMiao.Chen@Sun.COM 	    if (i + 2 >= count)
373*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
374*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "SIS.0\n");
375*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "SIS.1\n");
376*11260SMiao.Chen@Sun.COM 	}
377*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x02 << 8)) {
378*11260SMiao.Chen@Sun.COM 	    if (i + 1 >= count)
379*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
380*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "DIS.0\n");
381*11260SMiao.Chen@Sun.COM 	}
382*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x04 << 8)) {
383*11260SMiao.Chen@Sun.COM 	    if (i + 2 >= count)
384*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
385*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "SSB.0\n");
386*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "SSB.1\n");
387*11260SMiao.Chen@Sun.COM 	}
388*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x08 << 8)) {
389*11260SMiao.Chen@Sun.COM 	    if (i + 2 >= count)
390*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
391*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "MSB.0\n");
392*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "MSB.1\n");
393*11260SMiao.Chen@Sun.COM 	}
394*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x10 << 8)) {
395*11260SMiao.Chen@Sun.COM 	    if (i + 2 >= count)
396*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
397*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PSP.0\n");
398*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PSP.1\n");
399*11260SMiao.Chen@Sun.COM 	}
400*11260SMiao.Chen@Sun.COM 	if (data[0] & (0x20 << 8)) {
401*11260SMiao.Chen@Sun.COM 	    if (i + 2 >= count)
402*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_LOAD_INDIRECT");
403*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PSC.0\n");
404*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PSC.1\n");
405*11260SMiao.Chen@Sun.COM 	}
406*11260SMiao.Chen@Sun.COM 	if (len != i) {
407*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_LOAD_INDIRECT\n");
408*11260SMiao.Chen@Sun.COM 	    (*failures)++;
409*11260SMiao.Chen@Sun.COM 	    return len;
410*11260SMiao.Chen@Sun.COM 	}
411*11260SMiao.Chen@Sun.COM 	return len;
412*11260SMiao.Chen@Sun.COM     case 0x04:
413*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_1\n");
414*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x0000000f) + 2;
415*11260SMiao.Chen@Sun.COM 	i = 1;
416*11260SMiao.Chen@Sun.COM 	for (word = 0; word <= 7; word++) {
417*11260SMiao.Chen@Sun.COM 	    if (data[0] & (1 << (4 + word))) {
418*11260SMiao.Chen@Sun.COM 		if (i >= count)
419*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, "3DSTATE_LOAD_STATE_IMMEDIATE_1");
420*11260SMiao.Chen@Sun.COM 
421*11260SMiao.Chen@Sun.COM 		/* save vertex state for decode */
422*11260SMiao.Chen@Sun.COM 		if (word == 2) {
423*11260SMiao.Chen@Sun.COM 		    saved_s2_set = 1;
424*11260SMiao.Chen@Sun.COM 		    saved_s2 = data[i];
425*11260SMiao.Chen@Sun.COM 		}
426*11260SMiao.Chen@Sun.COM 		if (word == 4) {
427*11260SMiao.Chen@Sun.COM 		    saved_s4_set = 1;
428*11260SMiao.Chen@Sun.COM 		    saved_s4 = data[i];
429*11260SMiao.Chen@Sun.COM 		}
430*11260SMiao.Chen@Sun.COM 
431*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "S%d\n", word);
432*11260SMiao.Chen@Sun.COM 	    }
433*11260SMiao.Chen@Sun.COM 	}
434*11260SMiao.Chen@Sun.COM 	if (len != i) {
435*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_LOAD_INDIRECT\n");
436*11260SMiao.Chen@Sun.COM 	    (*failures)++;
437*11260SMiao.Chen@Sun.COM 	}
438*11260SMiao.Chen@Sun.COM 	return len;
439*11260SMiao.Chen@Sun.COM     case 0x00:
440*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_MAP_STATE\n");
441*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x0000003f) + 2;
442*11260SMiao.Chen@Sun.COM 
443*11260SMiao.Chen@Sun.COM 	i = 1;
444*11260SMiao.Chen@Sun.COM 	for (map = 0; map <= 15; map++) {
445*11260SMiao.Chen@Sun.COM 	    if (data[1] & (1 << map)) {
446*11260SMiao.Chen@Sun.COM 		if (i + 3 >= count)
447*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, "3DSTATE_MAP_STATE");
448*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "map %d MS2\n", map);
449*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "map %d MS3\n", map);
450*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "map %d MS4\n", map);
451*11260SMiao.Chen@Sun.COM 	    }
452*11260SMiao.Chen@Sun.COM 	}
453*11260SMiao.Chen@Sun.COM 	if (len != i) {
454*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_MAP_STATE\n");
455*11260SMiao.Chen@Sun.COM 	    (*failures)++;
456*11260SMiao.Chen@Sun.COM 	    return len;
457*11260SMiao.Chen@Sun.COM 	}
458*11260SMiao.Chen@Sun.COM 	return len;
459*11260SMiao.Chen@Sun.COM     case 0x06:
460*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_PIXEL_SHADER_CONSTANTS\n");
461*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x000000ff) + 2;
462*11260SMiao.Chen@Sun.COM 
463*11260SMiao.Chen@Sun.COM 	i = 1;
464*11260SMiao.Chen@Sun.COM 	for (c = 0; c <= 31; c++) {
465*11260SMiao.Chen@Sun.COM 	    if (data[1] & (1 << c)) {
466*11260SMiao.Chen@Sun.COM 		if (i + 4 >= count)
467*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, "3DSTATE_PIXEL_SHADER_CONSTANTS");
468*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "C%d.X = %f\n",
469*11260SMiao.Chen@Sun.COM 			  c, int_as_float(data[i]));
470*11260SMiao.Chen@Sun.COM 		i++;
471*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "C%d.Y = %f\n",
472*11260SMiao.Chen@Sun.COM 			  c, int_as_float(data[i]));
473*11260SMiao.Chen@Sun.COM 		i++;
474*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "C%d.Z = %f\n",
475*11260SMiao.Chen@Sun.COM 			  c, int_as_float(data[i]));
476*11260SMiao.Chen@Sun.COM 		i++;
477*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "C%d.W = %f\n",
478*11260SMiao.Chen@Sun.COM 			  c, int_as_float(data[i]));
479*11260SMiao.Chen@Sun.COM 		i++;
480*11260SMiao.Chen@Sun.COM 	    }
481*11260SMiao.Chen@Sun.COM 	}
482*11260SMiao.Chen@Sun.COM 	if (len != i) {
483*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_MAP_STATE\n");
484*11260SMiao.Chen@Sun.COM 	    (*failures)++;
485*11260SMiao.Chen@Sun.COM 	}
486*11260SMiao.Chen@Sun.COM 	return len;
487*11260SMiao.Chen@Sun.COM     case 0x05:
488*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_PIXEL_SHADER_PROGRAM\n");
489*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x000000ff) + 2;
490*11260SMiao.Chen@Sun.COM 	if ((len - 1) % 3 != 0 || len > 370) {
491*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_PIXEL_SHADER_PROGRAM\n");
492*11260SMiao.Chen@Sun.COM 	    (*failures)++;
493*11260SMiao.Chen@Sun.COM 	}
494*11260SMiao.Chen@Sun.COM 	i = 1;
495*11260SMiao.Chen@Sun.COM 	for (instr = 0; instr < (len - 1) / 3; instr++) {
496*11260SMiao.Chen@Sun.COM 	    if (i + 3 >= count)
497*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, len, "3DSTATE_MAP_STATE");
498*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PS%03x\n", instr);
499*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PS%03x\n", instr);
500*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, i++, "PS%03x\n", instr);
501*11260SMiao.Chen@Sun.COM 	}
502*11260SMiao.Chen@Sun.COM 	return len;
503*11260SMiao.Chen@Sun.COM     case 0x01:
504*11260SMiao.Chen@Sun.COM 	if (i830)
505*11260SMiao.Chen@Sun.COM 	    break;
506*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DSTATE_SAMPLER_STATE\n");
507*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x0000003f) + 2;
508*11260SMiao.Chen@Sun.COM 	i = 1;
509*11260SMiao.Chen@Sun.COM 	for (sampler = 0; sampler <= 15; sampler++) {
510*11260SMiao.Chen@Sun.COM 	    if (data[1] & (1 << sampler)) {
511*11260SMiao.Chen@Sun.COM 		if (i + 3 >= count)
512*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, "3DSTATE_SAMPLER_STATE");
513*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "sampler %d SS2\n",
514*11260SMiao.Chen@Sun.COM 			  sampler);
515*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "sampler %d SS3\n",
516*11260SMiao.Chen@Sun.COM 			  sampler);
517*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i++, "sampler %d SS4\n",
518*11260SMiao.Chen@Sun.COM 			  sampler);
519*11260SMiao.Chen@Sun.COM 	    }
520*11260SMiao.Chen@Sun.COM 	}
521*11260SMiao.Chen@Sun.COM 	if (len != i) {
522*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_SAMPLER_STATE\n");
523*11260SMiao.Chen@Sun.COM 	    (*failures)++;
524*11260SMiao.Chen@Sun.COM 	}
525*11260SMiao.Chen@Sun.COM 	return len;
526*11260SMiao.Chen@Sun.COM     }
527*11260SMiao.Chen@Sun.COM 
528*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_3d_1d) / sizeof(opcodes_3d_1d[0]);
529*11260SMiao.Chen@Sun.COM 	 opcode++)
530*11260SMiao.Chen@Sun.COM     {
531*11260SMiao.Chen@Sun.COM 	if (opcodes_3d_1d[opcode].i830_only && !i830)
532*11260SMiao.Chen@Sun.COM 	    continue;
533*11260SMiao.Chen@Sun.COM 
534*11260SMiao.Chen@Sun.COM 	if (((data[0] & 0x00ff0000) >> 16) == opcodes_3d_1d[opcode].opcode) {
535*11260SMiao.Chen@Sun.COM 	    len = 1;
536*11260SMiao.Chen@Sun.COM 
537*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_3d_1d[opcode].name);
538*11260SMiao.Chen@Sun.COM 	    if (opcodes_3d_1d[opcode].max_len > 1) {
539*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0x0000ffff) + 2;
540*11260SMiao.Chen@Sun.COM 		if (len < opcodes_3d_1d[opcode].min_len ||
541*11260SMiao.Chen@Sun.COM 		    len > opcodes_3d_1d[opcode].max_len)
542*11260SMiao.Chen@Sun.COM 		{
543*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad count in %s\n",
544*11260SMiao.Chen@Sun.COM 			    opcodes_3d_1d[opcode].name);
545*11260SMiao.Chen@Sun.COM 		    (*failures)++;
546*11260SMiao.Chen@Sun.COM 		}
547*11260SMiao.Chen@Sun.COM 	    }
548*11260SMiao.Chen@Sun.COM 
549*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
550*11260SMiao.Chen@Sun.COM 		if (i >= count)
551*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len,  opcodes_3d_1d[opcode].name);
552*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
553*11260SMiao.Chen@Sun.COM 	    }
554*11260SMiao.Chen@Sun.COM 
555*11260SMiao.Chen@Sun.COM 	    return len;
556*11260SMiao.Chen@Sun.COM 	}
557*11260SMiao.Chen@Sun.COM     }
558*11260SMiao.Chen@Sun.COM 
559*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
560*11260SMiao.Chen@Sun.COM     (*failures)++;
561*11260SMiao.Chen@Sun.COM     return 1;
562*11260SMiao.Chen@Sun.COM }
563*11260SMiao.Chen@Sun.COM 
564*11260SMiao.Chen@Sun.COM static int
decode_3d_primitive(uint32_t * data,int count,uint32_t hw_offset,int * failures)565*11260SMiao.Chen@Sun.COM decode_3d_primitive(uint32_t *data, int count, uint32_t hw_offset,
566*11260SMiao.Chen@Sun.COM 		    int *failures)
567*11260SMiao.Chen@Sun.COM {
568*11260SMiao.Chen@Sun.COM     char immediate = (data[0] & (1 << 23)) == 0;
569*11260SMiao.Chen@Sun.COM     unsigned int len, i;
570*11260SMiao.Chen@Sun.COM     char *primtype;
571*11260SMiao.Chen@Sun.COM 
572*11260SMiao.Chen@Sun.COM     switch ((data[0] >> 18) & 0xf) {
573*11260SMiao.Chen@Sun.COM     case 0x0: primtype = "TRILIST"; break;
574*11260SMiao.Chen@Sun.COM     case 0x1: primtype = "TRISTRIP"; break;
575*11260SMiao.Chen@Sun.COM     case 0x2: primtype = "TRISTRIP_REVERSE"; break;
576*11260SMiao.Chen@Sun.COM     case 0x3: primtype = "TRIFAN"; break;
577*11260SMiao.Chen@Sun.COM     case 0x4: primtype = "POLYGON"; break;
578*11260SMiao.Chen@Sun.COM     case 0x5: primtype = "LINELIST"; break;
579*11260SMiao.Chen@Sun.COM     case 0x6: primtype = "LINESTRIP"; break;
580*11260SMiao.Chen@Sun.COM     case 0x7: primtype = "RECTLIST"; break;
581*11260SMiao.Chen@Sun.COM     case 0x8: primtype = "POINTLIST"; break;
582*11260SMiao.Chen@Sun.COM     case 0x9: primtype = "DIB"; break;
583*11260SMiao.Chen@Sun.COM     case 0xa: primtype = "CLEAR_RECT"; break;
584*11260SMiao.Chen@Sun.COM     default: primtype = "unknown"; break;
585*11260SMiao.Chen@Sun.COM     }
586*11260SMiao.Chen@Sun.COM 
587*11260SMiao.Chen@Sun.COM     /* XXX: 3DPRIM_DIB not supported */
588*11260SMiao.Chen@Sun.COM     if (immediate) {
589*11260SMiao.Chen@Sun.COM 	len = (data[0] & 0x0003ffff) + 2;
590*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0, "3DPRIMITIVE inline %s\n", primtype);
591*11260SMiao.Chen@Sun.COM 	if (count < len)
592*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len,  "3DPRIMITIVE inline");
593*11260SMiao.Chen@Sun.COM 	if (!saved_s2_set || !saved_s4_set) {
594*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("unknown vertex format\n");
595*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
596*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i,
597*11260SMiao.Chen@Sun.COM 			  "           vertex data (%f float)\n",
598*11260SMiao.Chen@Sun.COM 			  int_as_float(data[i]));
599*11260SMiao.Chen@Sun.COM 	    }
600*11260SMiao.Chen@Sun.COM 	} else {
601*11260SMiao.Chen@Sun.COM 	    unsigned int vertex = 0;
602*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len;) {
603*11260SMiao.Chen@Sun.COM 		unsigned int tc;
604*11260SMiao.Chen@Sun.COM 
605*11260SMiao.Chen@Sun.COM #define VERTEX_OUT(fmt, ...) {					\
606*11260SMiao.Chen@Sun.COM     if (i < len)							\
607*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, i, " V%d."fmt"\n", vertex, __VA_ARGS__); \
608*11260SMiao.Chen@Sun.COM     else								\
609*11260SMiao.Chen@Sun.COM 	DRM_ERROR(" missing data in V%d\n", vertex);			\
610*11260SMiao.Chen@Sun.COM     i++;								\
611*11260SMiao.Chen@Sun.COM }
612*11260SMiao.Chen@Sun.COM 
613*11260SMiao.Chen@Sun.COM 		VERTEX_OUT("X = %f", int_as_float(data[i]));
614*11260SMiao.Chen@Sun.COM 		VERTEX_OUT("Y = %f", int_as_float(data[i]));
615*11260SMiao.Chen@Sun.COM 	        switch (saved_s4 >> 6 & 0x7) {
616*11260SMiao.Chen@Sun.COM 		case 0x1:
617*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("Z = %f", int_as_float(data[i]));
618*11260SMiao.Chen@Sun.COM 		    break;
619*11260SMiao.Chen@Sun.COM 		case 0x2:
620*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("Z = %f", int_as_float(data[i]));
621*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("W = %f", int_as_float(data[i]));
622*11260SMiao.Chen@Sun.COM 		    break;
623*11260SMiao.Chen@Sun.COM 		case 0x3:
624*11260SMiao.Chen@Sun.COM 		    break;
625*11260SMiao.Chen@Sun.COM 		case 0x4:
626*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("W = %f", int_as_float(data[i]));
627*11260SMiao.Chen@Sun.COM 		    break;
628*11260SMiao.Chen@Sun.COM 		default:
629*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("bad S4 position mask\n");
630*11260SMiao.Chen@Sun.COM 		}
631*11260SMiao.Chen@Sun.COM 
632*11260SMiao.Chen@Sun.COM 		if (saved_s4 & (1 << 10)) {
633*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("color = (A=0x%02x, R=0x%02x, G=0x%02x, "
634*11260SMiao.Chen@Sun.COM 			       "B=0x%02x)",
635*11260SMiao.Chen@Sun.COM 			       data[i] >> 24,
636*11260SMiao.Chen@Sun.COM 			       (data[i] >> 16) & 0xff,
637*11260SMiao.Chen@Sun.COM 			       (data[i] >> 8) & 0xff,
638*11260SMiao.Chen@Sun.COM 			       data[i] & 0xff);
639*11260SMiao.Chen@Sun.COM 		}
640*11260SMiao.Chen@Sun.COM 		if (saved_s4 & (1 << 11)) {
641*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("spec = (A=0x%02x, R=0x%02x, G=0x%02x, "
642*11260SMiao.Chen@Sun.COM 			       "B=0x%02x)",
643*11260SMiao.Chen@Sun.COM 			       data[i] >> 24,
644*11260SMiao.Chen@Sun.COM 			       (data[i] >> 16) & 0xff,
645*11260SMiao.Chen@Sun.COM 			       (data[i] >> 8) & 0xff,
646*11260SMiao.Chen@Sun.COM 			       data[i] & 0xff);
647*11260SMiao.Chen@Sun.COM 		}
648*11260SMiao.Chen@Sun.COM 		if (saved_s4 & (1 << 12))
649*11260SMiao.Chen@Sun.COM 		    VERTEX_OUT("width = 0x%08x)", data[i]);
650*11260SMiao.Chen@Sun.COM 
651*11260SMiao.Chen@Sun.COM 		for (tc = 0; tc <= 7; tc++) {
652*11260SMiao.Chen@Sun.COM 		    switch ((saved_s2 >> (tc * 4)) & 0xf) {
653*11260SMiao.Chen@Sun.COM 		    case 0x0:
654*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
655*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
656*11260SMiao.Chen@Sun.COM 			break;
657*11260SMiao.Chen@Sun.COM 		    case 0x1:
658*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
659*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
660*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i]));
661*11260SMiao.Chen@Sun.COM 			break;
662*11260SMiao.Chen@Sun.COM 		    case 0x2:
663*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
664*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i]));
665*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i]));
666*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.W = %f", tc, int_as_float(data[i]));
667*11260SMiao.Chen@Sun.COM 			break;
668*11260SMiao.Chen@Sun.COM 		    case 0x3:
669*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i]));
670*11260SMiao.Chen@Sun.COM 			break;
671*11260SMiao.Chen@Sun.COM 		    case 0x4:
672*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]);
673*11260SMiao.Chen@Sun.COM 			break;
674*11260SMiao.Chen@Sun.COM 		    case 0x5:
675*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]);
676*11260SMiao.Chen@Sun.COM 			VERTEX_OUT("T%d.ZW = 0x%08x half-float", tc, data[i]);
677*11260SMiao.Chen@Sun.COM 			break;
678*11260SMiao.Chen@Sun.COM 		    case 0xf:
679*11260SMiao.Chen@Sun.COM 			break;
680*11260SMiao.Chen@Sun.COM 		    default:
681*11260SMiao.Chen@Sun.COM 			DRM_ERROR("bad S2.T%d format\n", tc);
682*11260SMiao.Chen@Sun.COM 		    }
683*11260SMiao.Chen@Sun.COM 		}
684*11260SMiao.Chen@Sun.COM 		vertex++;
685*11260SMiao.Chen@Sun.COM 	    }
686*11260SMiao.Chen@Sun.COM 	}
687*11260SMiao.Chen@Sun.COM     } else {
688*11260SMiao.Chen@Sun.COM 	/* indirect vertices */
689*11260SMiao.Chen@Sun.COM 	len = data[0] & 0x0000ffff; /* index count */
690*11260SMiao.Chen@Sun.COM 	if (data[0] & (1 << 17)) {
691*11260SMiao.Chen@Sun.COM 	    /* random vertex access */
692*11260SMiao.Chen@Sun.COM 	    if (count < (len + 1) / 2 + 1)
693*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, (len + 1) / 2 + 1, "3DPRIMITIVE random indirect");
694*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0,
695*11260SMiao.Chen@Sun.COM 		      "3DPRIMITIVE random indirect %s (%d)\n", primtype, len);
696*11260SMiao.Chen@Sun.COM 	    if (len == 0) {
697*11260SMiao.Chen@Sun.COM 		/* vertex indices continue until 0xffff is found */
698*11260SMiao.Chen@Sun.COM 		for (i = 1; i < count; i++) {
699*11260SMiao.Chen@Sun.COM 		    if ((data[i] & 0xffff) == 0xffff) {
700*11260SMiao.Chen@Sun.COM 			instr_out(data, hw_offset, i,
701*11260SMiao.Chen@Sun.COM 				  "            indices: (terminator)\n");
702*11260SMiao.Chen@Sun.COM 			return i;
703*11260SMiao.Chen@Sun.COM 		    } else if ((data[i] >> 16) == 0xffff) {
704*11260SMiao.Chen@Sun.COM 			instr_out(data, hw_offset, i,
705*11260SMiao.Chen@Sun.COM 				  "            indices: 0x%04x, "
706*11260SMiao.Chen@Sun.COM 				  "(terminator)\n",
707*11260SMiao.Chen@Sun.COM 				  data[i] & 0xffff);
708*11260SMiao.Chen@Sun.COM 			return i;
709*11260SMiao.Chen@Sun.COM 		    } else {
710*11260SMiao.Chen@Sun.COM 			instr_out(data, hw_offset, i,
711*11260SMiao.Chen@Sun.COM 				  "            indices: 0x%04x, 0x%04x\n",
712*11260SMiao.Chen@Sun.COM 				  data[i] & 0xffff, data[i] >> 16);
713*11260SMiao.Chen@Sun.COM 		    }
714*11260SMiao.Chen@Sun.COM 		}
715*11260SMiao.Chen@Sun.COM 		DRM_ERROR("3DPRIMITIVE: no terminator found in index buffer\n");
716*11260SMiao.Chen@Sun.COM 		(*failures)++;
717*11260SMiao.Chen@Sun.COM 		return count;
718*11260SMiao.Chen@Sun.COM 	    } else {
719*11260SMiao.Chen@Sun.COM 		/* fixed size vertex index buffer */
720*11260SMiao.Chen@Sun.COM 		for (i = 0; i < len; i += 2) {
721*11260SMiao.Chen@Sun.COM 		    if (i * 2 == len - 1) {
722*11260SMiao.Chen@Sun.COM 			instr_out(data, hw_offset, i,
723*11260SMiao.Chen@Sun.COM 				  "            indices: 0x%04x\n",
724*11260SMiao.Chen@Sun.COM 				  data[i] & 0xffff);
725*11260SMiao.Chen@Sun.COM 		    } else {
726*11260SMiao.Chen@Sun.COM 			instr_out(data, hw_offset, i,
727*11260SMiao.Chen@Sun.COM 				  "            indices: 0x%04x, 0x%04x\n",
728*11260SMiao.Chen@Sun.COM 				  data[i] & 0xffff, data[i] >> 16);
729*11260SMiao.Chen@Sun.COM 		    }
730*11260SMiao.Chen@Sun.COM 		}
731*11260SMiao.Chen@Sun.COM 	    }
732*11260SMiao.Chen@Sun.COM 	    return (len + 1) / 2 + 1;
733*11260SMiao.Chen@Sun.COM 	} else {
734*11260SMiao.Chen@Sun.COM 	    /* sequential vertex access */
735*11260SMiao.Chen@Sun.COM 	    if (count < 2)
736*11260SMiao.Chen@Sun.COM 		BUFFER_FAIL(count, 2, "3DPRIMITIVE seq indirect");
737*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0,
738*11260SMiao.Chen@Sun.COM 		      "3DPRIMITIVE sequential indirect %s, %d starting from "
739*11260SMiao.Chen@Sun.COM 		      "%d\n", primtype, len, data[1] & 0xffff);
740*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 1, "           start\n");
741*11260SMiao.Chen@Sun.COM 	    return 2;
742*11260SMiao.Chen@Sun.COM 	}
743*11260SMiao.Chen@Sun.COM     }
744*11260SMiao.Chen@Sun.COM 
745*11260SMiao.Chen@Sun.COM     return len;
746*11260SMiao.Chen@Sun.COM }
747*11260SMiao.Chen@Sun.COM 
748*11260SMiao.Chen@Sun.COM static int
decode_3d(uint32_t * data,int count,uint32_t hw_offset,int * failures)749*11260SMiao.Chen@Sun.COM decode_3d(uint32_t *data, int count, uint32_t hw_offset, int *failures)
750*11260SMiao.Chen@Sun.COM {
751*11260SMiao.Chen@Sun.COM     unsigned int opcode;
752*11260SMiao.Chen@Sun.COM 
753*11260SMiao.Chen@Sun.COM     struct {
754*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
755*11260SMiao.Chen@Sun.COM 	int min_len;
756*11260SMiao.Chen@Sun.COM 	int max_len;
757*11260SMiao.Chen@Sun.COM 	char *name;
758*11260SMiao.Chen@Sun.COM     } opcodes_3d[] = {
759*11260SMiao.Chen@Sun.COM 	{ 0x06, 1, 1, "3DSTATE_ANTI_ALIASING" },
760*11260SMiao.Chen@Sun.COM 	{ 0x08, 1, 1, "3DSTATE_BACKFACE_STENCIL_OPS" },
761*11260SMiao.Chen@Sun.COM 	{ 0x09, 1, 1, "3DSTATE_BACKFACE_STENCIL_MASKS" },
762*11260SMiao.Chen@Sun.COM 	{ 0x16, 1, 1, "3DSTATE_COORD_SET_BINDINGS" },
763*11260SMiao.Chen@Sun.COM 	{ 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
764*11260SMiao.Chen@Sun.COM 	{ 0x0b, 1, 1, "3DSTATE_INDEPENDENT_ALPHA_BLEND" },
765*11260SMiao.Chen@Sun.COM 	{ 0x0d, 1, 1, "3DSTATE_MODES_4" },
766*11260SMiao.Chen@Sun.COM 	{ 0x0c, 1, 1, "3DSTATE_MODES_5" },
767*11260SMiao.Chen@Sun.COM 	{ 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
768*11260SMiao.Chen@Sun.COM     };
769*11260SMiao.Chen@Sun.COM 
770*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0x1f000000) >> 24) {
771*11260SMiao.Chen@Sun.COM     case 0x1f:
772*11260SMiao.Chen@Sun.COM 	return decode_3d_primitive(data, count, hw_offset, failures);
773*11260SMiao.Chen@Sun.COM     case 0x1d:
774*11260SMiao.Chen@Sun.COM 	return decode_3d_1d(data, count, hw_offset, failures, 0);
775*11260SMiao.Chen@Sun.COM     case 0x1c:
776*11260SMiao.Chen@Sun.COM 	return decode_3d_1c(data, count, hw_offset, failures);
777*11260SMiao.Chen@Sun.COM     }
778*11260SMiao.Chen@Sun.COM 
779*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_3d) / sizeof(opcodes_3d[0]);
780*11260SMiao.Chen@Sun.COM 	 opcode++) {
781*11260SMiao.Chen@Sun.COM 	if ((data[0] & 0x1f000000) >> 24 == opcodes_3d[opcode].opcode) {
782*11260SMiao.Chen@Sun.COM 	    unsigned int len = 1, i;
783*11260SMiao.Chen@Sun.COM 
784*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_3d[opcode].name);
785*11260SMiao.Chen@Sun.COM 	    if (opcodes_3d[opcode].max_len > 1) {
786*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0xff) + 2;
787*11260SMiao.Chen@Sun.COM 		if (len < opcodes_3d[opcode].min_len ||
788*11260SMiao.Chen@Sun.COM 		    len > opcodes_3d[opcode].max_len)
789*11260SMiao.Chen@Sun.COM 		{
790*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad count in %s\n", opcodes_3d[opcode].name);
791*11260SMiao.Chen@Sun.COM 		}
792*11260SMiao.Chen@Sun.COM 	    }
793*11260SMiao.Chen@Sun.COM 
794*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
795*11260SMiao.Chen@Sun.COM 		if (i >= count)
796*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, opcodes_3d[opcode].name);
797*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
798*11260SMiao.Chen@Sun.COM 	    }
799*11260SMiao.Chen@Sun.COM 	    return len;
800*11260SMiao.Chen@Sun.COM 	}
801*11260SMiao.Chen@Sun.COM     }
802*11260SMiao.Chen@Sun.COM 
803*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
804*11260SMiao.Chen@Sun.COM     (*failures)++;
805*11260SMiao.Chen@Sun.COM     return 1;
806*11260SMiao.Chen@Sun.COM }
807*11260SMiao.Chen@Sun.COM 
808*11260SMiao.Chen@Sun.COM static const char *
get_965_surfacetype(unsigned int surfacetype)809*11260SMiao.Chen@Sun.COM get_965_surfacetype(unsigned int surfacetype)
810*11260SMiao.Chen@Sun.COM {
811*11260SMiao.Chen@Sun.COM     switch (surfacetype) {
812*11260SMiao.Chen@Sun.COM     case 0: return "1D";
813*11260SMiao.Chen@Sun.COM     case 1: return "2D";
814*11260SMiao.Chen@Sun.COM     case 2: return "3D";
815*11260SMiao.Chen@Sun.COM     case 3: return "CUBE";
816*11260SMiao.Chen@Sun.COM     case 4: return "BUFFER";
817*11260SMiao.Chen@Sun.COM     case 7: return "NULL";
818*11260SMiao.Chen@Sun.COM     default: return "unknown";
819*11260SMiao.Chen@Sun.COM     }
820*11260SMiao.Chen@Sun.COM }
821*11260SMiao.Chen@Sun.COM 
822*11260SMiao.Chen@Sun.COM static const char *
get_965_depthformat(unsigned int depthformat)823*11260SMiao.Chen@Sun.COM get_965_depthformat(unsigned int depthformat)
824*11260SMiao.Chen@Sun.COM {
825*11260SMiao.Chen@Sun.COM     switch (depthformat) {
826*11260SMiao.Chen@Sun.COM     case 0: return "s8_z24float";
827*11260SMiao.Chen@Sun.COM     case 1: return "z32float";
828*11260SMiao.Chen@Sun.COM     case 2: return "z24s8";
829*11260SMiao.Chen@Sun.COM     case 5: return "z16";
830*11260SMiao.Chen@Sun.COM     default: return "unknown";
831*11260SMiao.Chen@Sun.COM     }
832*11260SMiao.Chen@Sun.COM }
833*11260SMiao.Chen@Sun.COM 
834*11260SMiao.Chen@Sun.COM static int
decode_3d_965(uint32_t * data,int count,uint32_t hw_offset,int * failures)835*11260SMiao.Chen@Sun.COM decode_3d_965(uint32_t *data, int count, uint32_t hw_offset, int *failures)
836*11260SMiao.Chen@Sun.COM {
837*11260SMiao.Chen@Sun.COM     unsigned int opcode, len;
838*11260SMiao.Chen@Sun.COM 
839*11260SMiao.Chen@Sun.COM     struct {
840*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
841*11260SMiao.Chen@Sun.COM 	int min_len;
842*11260SMiao.Chen@Sun.COM 	int max_len;
843*11260SMiao.Chen@Sun.COM 	char *name;
844*11260SMiao.Chen@Sun.COM     } opcodes_3d[] = {
845*11260SMiao.Chen@Sun.COM 	{ 0x6000, 3, 3, "URB_FENCE" },
846*11260SMiao.Chen@Sun.COM 	{ 0x6001, 2, 2, "CS_URB_STATE" },
847*11260SMiao.Chen@Sun.COM 	{ 0x6002, 2, 2, "CONSTANT_BUFFER" },
848*11260SMiao.Chen@Sun.COM 	{ 0x6101, 6, 6, "STATE_BASE_ADDRESS" },
849*11260SMiao.Chen@Sun.COM 	{ 0x6102, 2, 2 , "STATE_SIP" },
850*11260SMiao.Chen@Sun.COM 	{ 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" },
851*11260SMiao.Chen@Sun.COM 	{ 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" },
852*11260SMiao.Chen@Sun.COM 	{ 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" },
853*11260SMiao.Chen@Sun.COM 	{ 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" },
854*11260SMiao.Chen@Sun.COM 	{ 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" },
855*11260SMiao.Chen@Sun.COM 	{ 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" },
856*11260SMiao.Chen@Sun.COM 	{ 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" },
857*11260SMiao.Chen@Sun.COM 	{ 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" },
858*11260SMiao.Chen@Sun.COM 	/* 0x7808: 3DSTATE_VERTEX_BUFFERS */
859*11260SMiao.Chen@Sun.COM 	/* 0x7809: 3DSTATE_VERTEX_ELEMENTS */
860*11260SMiao.Chen@Sun.COM 	{ 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
861*11260SMiao.Chen@Sun.COM 	{ 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" },
862*11260SMiao.Chen@Sun.COM 	{ 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" },
863*11260SMiao.Chen@Sun.COM 	{ 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" },
864*11260SMiao.Chen@Sun.COM 	{ 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" },
865*11260SMiao.Chen@Sun.COM 	{ 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" },
866*11260SMiao.Chen@Sun.COM 	{ 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" },
867*11260SMiao.Chen@Sun.COM 	{ 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
868*11260SMiao.Chen@Sun.COM 	{ 0x7b00, 6, 6, "3DPRIMITIVE" },
869*11260SMiao.Chen@Sun.COM     };
870*11260SMiao.Chen@Sun.COM 
871*11260SMiao.Chen@Sun.COM     len = (data[0] & 0x0000ffff) + 2;
872*11260SMiao.Chen@Sun.COM 
873*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0xffff0000) >> 16) {
874*11260SMiao.Chen@Sun.COM     case 0x6101:
875*11260SMiao.Chen@Sun.COM 	if (len != 6)
876*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in STATE_BASE_ADDRESS\n");
877*11260SMiao.Chen@Sun.COM 	if (count < 6)
878*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "STATE_BASE_ADDRESS");
879*11260SMiao.Chen@Sun.COM 
880*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
881*11260SMiao.Chen@Sun.COM 		  "STATE_BASE_ADDRESS\n");
882*11260SMiao.Chen@Sun.COM 
883*11260SMiao.Chen@Sun.COM 	if (data[1] & 1) {
884*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 1, "General state at 0x%08x\n",
885*11260SMiao.Chen@Sun.COM 		      data[1] & ~1);
886*11260SMiao.Chen@Sun.COM 	} else
887*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 1, "General state not updated\n");
888*11260SMiao.Chen@Sun.COM 
889*11260SMiao.Chen@Sun.COM 	if (data[2] & 1) {
890*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 2, "Surface state at 0x%08x\n",
891*11260SMiao.Chen@Sun.COM 		      data[2] & ~1);
892*11260SMiao.Chen@Sun.COM 	} else
893*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 2, "Surface state not updated\n");
894*11260SMiao.Chen@Sun.COM 
895*11260SMiao.Chen@Sun.COM 	if (data[3] & 1) {
896*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 3, "Indirect state at 0x%08x\n",
897*11260SMiao.Chen@Sun.COM 		      data[3] & ~1);
898*11260SMiao.Chen@Sun.COM 	} else
899*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 3, "Indirect state not updated\n");
900*11260SMiao.Chen@Sun.COM 
901*11260SMiao.Chen@Sun.COM 	if (data[4] & 1) {
902*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 4, "General state upper bound 0x%08x\n",
903*11260SMiao.Chen@Sun.COM 		      data[4] & ~1);
904*11260SMiao.Chen@Sun.COM 	} else
905*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 4, "General state not updated\n");
906*11260SMiao.Chen@Sun.COM 
907*11260SMiao.Chen@Sun.COM 	if (data[5] & 1) {
908*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 5, "Indirect state upper bound 0x%08x\n",
909*11260SMiao.Chen@Sun.COM 		      data[5] & ~1);
910*11260SMiao.Chen@Sun.COM 	} else
911*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 5, "Indirect state not updated\n");
912*11260SMiao.Chen@Sun.COM 
913*11260SMiao.Chen@Sun.COM 	return len;
914*11260SMiao.Chen@Sun.COM     case 0x7800:
915*11260SMiao.Chen@Sun.COM 	if (len != 7)
916*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_PIPELINED_POINTERS\n");
917*11260SMiao.Chen@Sun.COM 	if (count < 7)
918*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "3DSTATE_PIPELINED_POINTERS");
919*11260SMiao.Chen@Sun.COM 
920*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
921*11260SMiao.Chen@Sun.COM 		  "3DSTATE_PIPELINED_POINTERS\n");
922*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "VS state\n");
923*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "GS state\n");
924*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "Clip state\n");
925*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 4, "SF state\n");
926*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 5, "WM state\n");
927*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 6, "CC state\n");
928*11260SMiao.Chen@Sun.COM 	return len;
929*11260SMiao.Chen@Sun.COM     case 0x7801:
930*11260SMiao.Chen@Sun.COM 	if (len != 6)
931*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_BINDING_TABLE_POINTERS\n");
932*11260SMiao.Chen@Sun.COM 	if (count < 6)
933*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "3DSTATE_BINDING_TABLE_POINTERS");
934*11260SMiao.Chen@Sun.COM 
935*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
936*11260SMiao.Chen@Sun.COM 		  "3DSTATE_BINDING_TABLE_POINTERS\n");
937*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "VS binding table\n");
938*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "GS binding table\n");
939*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "Clip binding table\n");
940*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 4, "SF binding table\n");
941*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 5, "WM binding table\n");
942*11260SMiao.Chen@Sun.COM 
943*11260SMiao.Chen@Sun.COM 	return len;
944*11260SMiao.Chen@Sun.COM 
945*11260SMiao.Chen@Sun.COM     case 0x7900:
946*11260SMiao.Chen@Sun.COM 	if (len != 4)
947*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_DRAWING_RECTANGLE\n");
948*11260SMiao.Chen@Sun.COM 	if (count < 4)
949*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "3DSTATE_DRAWING_RECTANGLE");
950*11260SMiao.Chen@Sun.COM 
951*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
952*11260SMiao.Chen@Sun.COM 		  "3DSTATE_DRAWING_RECTANGLE\n");
953*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "top left: %d,%d\n",
954*11260SMiao.Chen@Sun.COM 		  data[1] & 0xffff,
955*11260SMiao.Chen@Sun.COM 		  (data[1] >> 16) & 0xffff);
956*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "bottom right: %d,%d\n",
957*11260SMiao.Chen@Sun.COM 		  data[2] & 0xffff,
958*11260SMiao.Chen@Sun.COM 		  (data[2] >> 16) & 0xffff);
959*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "origin: %d,%d\n",
960*11260SMiao.Chen@Sun.COM 		  (int)data[3] & 0xffff,
961*11260SMiao.Chen@Sun.COM 		  ((int)data[3] >> 16) & 0xffff);
962*11260SMiao.Chen@Sun.COM 
963*11260SMiao.Chen@Sun.COM 	return len;
964*11260SMiao.Chen@Sun.COM 
965*11260SMiao.Chen@Sun.COM     case 0x7905:
966*11260SMiao.Chen@Sun.COM 	if (len != 5)
967*11260SMiao.Chen@Sun.COM 	    DRM_ERROR("Bad count in 3DSTATE_DEPTH_BUFFER\n");
968*11260SMiao.Chen@Sun.COM 	if (count < 5)
969*11260SMiao.Chen@Sun.COM 	    BUFFER_FAIL(count, len, "3DSTATE_DEPTH_BUFFER");
970*11260SMiao.Chen@Sun.COM 
971*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 0,
972*11260SMiao.Chen@Sun.COM 		  "3DSTATE_DEPTH_BUFFER\n");
973*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 1, "%s, %s, pitch = %d bytes, %stiled\n",
974*11260SMiao.Chen@Sun.COM 		  get_965_surfacetype(data[1] >> 29),
975*11260SMiao.Chen@Sun.COM 		  get_965_depthformat((data[1] >> 18) & 0x7),
976*11260SMiao.Chen@Sun.COM 		  (data[1] & 0x0001ffff) + 1,
977*11260SMiao.Chen@Sun.COM 		  data[1] & (1 << 27) ? "" : "not ");
978*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 2, "depth offset\n");
979*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 3, "%dx%d\n",
980*11260SMiao.Chen@Sun.COM 		  ((data[3] & 0x0007ffc0) >> 6) + 1,
981*11260SMiao.Chen@Sun.COM 		  ((data[3] & 0xfff80000) >> 19) + 1);
982*11260SMiao.Chen@Sun.COM 	instr_out(data, hw_offset, 4, "volume depth\n");
983*11260SMiao.Chen@Sun.COM 
984*11260SMiao.Chen@Sun.COM 	return len;
985*11260SMiao.Chen@Sun.COM     }
986*11260SMiao.Chen@Sun.COM 
987*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_3d) / sizeof(opcodes_3d[0]);
988*11260SMiao.Chen@Sun.COM 	 opcode++) {
989*11260SMiao.Chen@Sun.COM 	if ((data[0] & 0xffff0000) >> 16 == opcodes_3d[opcode].opcode) {
990*11260SMiao.Chen@Sun.COM 	    unsigned int i;
991*11260SMiao.Chen@Sun.COM 	    len = 1;
992*11260SMiao.Chen@Sun.COM 
993*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_3d[opcode].name);
994*11260SMiao.Chen@Sun.COM 	    if (opcodes_3d[opcode].max_len > 1) {
995*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0xff) + 2;
996*11260SMiao.Chen@Sun.COM 		if (len < opcodes_3d[opcode].min_len ||
997*11260SMiao.Chen@Sun.COM 		    len > opcodes_3d[opcode].max_len)
998*11260SMiao.Chen@Sun.COM 		{
999*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad count in %s\n", opcodes_3d[opcode].name);
1000*11260SMiao.Chen@Sun.COM 		}
1001*11260SMiao.Chen@Sun.COM 	    }
1002*11260SMiao.Chen@Sun.COM 
1003*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
1004*11260SMiao.Chen@Sun.COM 		if (i >= count)
1005*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, opcodes_3d[opcode].name);
1006*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
1007*11260SMiao.Chen@Sun.COM 	    }
1008*11260SMiao.Chen@Sun.COM 	    return len;
1009*11260SMiao.Chen@Sun.COM 	}
1010*11260SMiao.Chen@Sun.COM     }
1011*11260SMiao.Chen@Sun.COM 
1012*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
1013*11260SMiao.Chen@Sun.COM     (*failures)++;
1014*11260SMiao.Chen@Sun.COM     return 1;
1015*11260SMiao.Chen@Sun.COM }
1016*11260SMiao.Chen@Sun.COM 
1017*11260SMiao.Chen@Sun.COM 
1018*11260SMiao.Chen@Sun.COM static int
decode_3d_i830(uint32_t * data,int count,uint32_t hw_offset,int * failures)1019*11260SMiao.Chen@Sun.COM decode_3d_i830(uint32_t *data, int count, uint32_t hw_offset, int *failures)
1020*11260SMiao.Chen@Sun.COM {
1021*11260SMiao.Chen@Sun.COM     unsigned int opcode;
1022*11260SMiao.Chen@Sun.COM 
1023*11260SMiao.Chen@Sun.COM     struct {
1024*11260SMiao.Chen@Sun.COM 	uint32_t opcode;
1025*11260SMiao.Chen@Sun.COM 	int min_len;
1026*11260SMiao.Chen@Sun.COM 	int max_len;
1027*11260SMiao.Chen@Sun.COM 	char *name;
1028*11260SMiao.Chen@Sun.COM     } opcodes_3d[] = {
1029*11260SMiao.Chen@Sun.COM 	{ 0x02, 1, 1, "3DSTATE_MODES_3" },
1030*11260SMiao.Chen@Sun.COM 	{ 0x03, 1, 1, "3DSTATE_ENABLES_1"},
1031*11260SMiao.Chen@Sun.COM 	{ 0x04, 1, 1, "3DSTATE_ENABLES_2"},
1032*11260SMiao.Chen@Sun.COM 	{ 0x05, 1, 1, "3DSTATE_VFT0"},
1033*11260SMiao.Chen@Sun.COM 	{ 0x06, 1, 1, "3DSTATE_AA"},
1034*11260SMiao.Chen@Sun.COM 	{ 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
1035*11260SMiao.Chen@Sun.COM 	{ 0x08, 1, 1, "3DSTATE_MODES_1" },
1036*11260SMiao.Chen@Sun.COM 	{ 0x09, 1, 1, "3DSTATE_STENCIL_TEST" },
1037*11260SMiao.Chen@Sun.COM 	{ 0x0a, 1, 1, "3DSTATE_VFT1"},
1038*11260SMiao.Chen@Sun.COM 	{ 0x0b, 1, 1, "3DSTATE_INDPT_ALPHA_BLEND" },
1039*11260SMiao.Chen@Sun.COM 	{ 0x0c, 1, 1, "3DSTATE_MODES_5" },
1040*11260SMiao.Chen@Sun.COM 	{ 0x0d, 1, 1, "3DSTATE_MAP_BLEND_OP" },
1041*11260SMiao.Chen@Sun.COM 	{ 0x0e, 1, 1, "3DSTATE_MAP_BLEND_ARG" },
1042*11260SMiao.Chen@Sun.COM 	{ 0x0f, 1, 1, "3DSTATE_MODES_2" },
1043*11260SMiao.Chen@Sun.COM 	{ 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
1044*11260SMiao.Chen@Sun.COM 	{ 0x16, 1, 1, "3DSTATE_MODES_4" },
1045*11260SMiao.Chen@Sun.COM     };
1046*11260SMiao.Chen@Sun.COM 
1047*11260SMiao.Chen@Sun.COM     switch ((data[0] & 0x1f000000) >> 24) {
1048*11260SMiao.Chen@Sun.COM     case 0x1f:
1049*11260SMiao.Chen@Sun.COM 	return decode_3d_primitive(data, count, hw_offset, failures);
1050*11260SMiao.Chen@Sun.COM     case 0x1d:
1051*11260SMiao.Chen@Sun.COM 	return decode_3d_1d(data, count, hw_offset, failures, 1);
1052*11260SMiao.Chen@Sun.COM     case 0x1c:
1053*11260SMiao.Chen@Sun.COM 	return decode_3d_1c(data, count, hw_offset, failures);
1054*11260SMiao.Chen@Sun.COM     }
1055*11260SMiao.Chen@Sun.COM 
1056*11260SMiao.Chen@Sun.COM     for (opcode = 0; opcode < sizeof(opcodes_3d) / sizeof(opcodes_3d[0]);
1057*11260SMiao.Chen@Sun.COM 	 opcode++) {
1058*11260SMiao.Chen@Sun.COM 	if ((data[0] & 0x1f000000) >> 24 == opcodes_3d[opcode].opcode) {
1059*11260SMiao.Chen@Sun.COM 	    unsigned int len = 1, i;
1060*11260SMiao.Chen@Sun.COM 
1061*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, 0, "%s\n", opcodes_3d[opcode].name);
1062*11260SMiao.Chen@Sun.COM 	    if (opcodes_3d[opcode].max_len > 1) {
1063*11260SMiao.Chen@Sun.COM 		len = (data[0] & 0xff) + 2;
1064*11260SMiao.Chen@Sun.COM 		if (len < opcodes_3d[opcode].min_len ||
1065*11260SMiao.Chen@Sun.COM 		    len > opcodes_3d[opcode].max_len)
1066*11260SMiao.Chen@Sun.COM 		{
1067*11260SMiao.Chen@Sun.COM 		    DRM_ERROR("Bad count in %s\n", opcodes_3d[opcode].name);
1068*11260SMiao.Chen@Sun.COM 		}
1069*11260SMiao.Chen@Sun.COM 	    }
1070*11260SMiao.Chen@Sun.COM 
1071*11260SMiao.Chen@Sun.COM 	    for (i = 1; i < len; i++) {
1072*11260SMiao.Chen@Sun.COM 		if (i >= count)
1073*11260SMiao.Chen@Sun.COM 		    BUFFER_FAIL(count, len, opcodes_3d[opcode].name);
1074*11260SMiao.Chen@Sun.COM 		instr_out(data, hw_offset, i, "dword %d\n", i);
1075*11260SMiao.Chen@Sun.COM 	    }
1076*11260SMiao.Chen@Sun.COM 	    return len;
1077*11260SMiao.Chen@Sun.COM 	}
1078*11260SMiao.Chen@Sun.COM     }
1079*11260SMiao.Chen@Sun.COM 
1080*11260SMiao.Chen@Sun.COM     instr_out(data, hw_offset, 0, "3D UNKNOWN\n");
1081*11260SMiao.Chen@Sun.COM     (*failures)++;
1082*11260SMiao.Chen@Sun.COM     return 1;
1083*11260SMiao.Chen@Sun.COM }
1084*11260SMiao.Chen@Sun.COM 
i915_gem_command_decode(uint32_t * data,int count,uint32_t hw_offset,struct drm_device * dev)1085*11260SMiao.Chen@Sun.COM void i915_gem_command_decode(uint32_t *data, int count, uint32_t hw_offset, struct drm_device *dev)
1086*11260SMiao.Chen@Sun.COM {
1087*11260SMiao.Chen@Sun.COM     int index = 0;
1088*11260SMiao.Chen@Sun.COM     int failures = 0;
1089*11260SMiao.Chen@Sun.COM 
1090*11260SMiao.Chen@Sun.COM    while (index < count) {
1091*11260SMiao.Chen@Sun.COM 	switch ((data[index] & 0xe0000000) >> 29) {
1092*11260SMiao.Chen@Sun.COM 	case 0x0:
1093*11260SMiao.Chen@Sun.COM 	    index += decode_mi(data + index, count - index,
1094*11260SMiao.Chen@Sun.COM 			       hw_offset + index * 4, &failures);
1095*11260SMiao.Chen@Sun.COM 	    break;
1096*11260SMiao.Chen@Sun.COM 	case 0x2:
1097*11260SMiao.Chen@Sun.COM 	    index += decode_2d(data + index, count - index,
1098*11260SMiao.Chen@Sun.COM 			       hw_offset + index * 4, &failures);
1099*11260SMiao.Chen@Sun.COM 	    break;
1100*11260SMiao.Chen@Sun.COM 	case 0x3:
1101*11260SMiao.Chen@Sun.COM 	    if (IS_I965G(dev)) {
1102*11260SMiao.Chen@Sun.COM 		index += decode_3d_965(data + index, count - index,
1103*11260SMiao.Chen@Sun.COM 				       hw_offset + index * 4, &failures);
1104*11260SMiao.Chen@Sun.COM 	    } else if (IS_I9XX(dev)) {
1105*11260SMiao.Chen@Sun.COM 		index += decode_3d(data + index, count - index,
1106*11260SMiao.Chen@Sun.COM 				   hw_offset + index * 4, &failures);
1107*11260SMiao.Chen@Sun.COM 	    } else {
1108*11260SMiao.Chen@Sun.COM 		index += decode_3d_i830(data + index, count - index,
1109*11260SMiao.Chen@Sun.COM 					hw_offset + index * 4, &failures);
1110*11260SMiao.Chen@Sun.COM 	    }
1111*11260SMiao.Chen@Sun.COM 	    break;
1112*11260SMiao.Chen@Sun.COM 	default:
1113*11260SMiao.Chen@Sun.COM 	    instr_out(data, hw_offset, index, "UNKNOWN\n");
1114*11260SMiao.Chen@Sun.COM 	    failures++;
1115*11260SMiao.Chen@Sun.COM 	    index++;
1116*11260SMiao.Chen@Sun.COM 	    break;
1117*11260SMiao.Chen@Sun.COM 	}
1118*11260SMiao.Chen@Sun.COM     }
1119*11260SMiao.Chen@Sun.COM }
1120*11260SMiao.Chen@Sun.COM 
1121