1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * This header file contains the macros used to access the hardware.  These
28 * macros assume that 32-bit access is possible, which is true for most
29 * applications.  Projects using 16-bit compilers (the Windows98 display
30 * driver) and special purpose applications (such as Darwin) need to define
31 * their own versions of these macros, which typically call a subroutine.
32 * */
33
34/* ACCESS TO THE CPU REGISTERS */
35
36#define WRITE_REG8(offset, value) 			\
37	(*(volatile unsigned char *)(gfx_virt_regptr + (offset))) = (value)
38
39#define WRITE_REG16(offset, value) 			\
40	(*(volatile unsigned short *)(gfx_virt_regptr + (offset))) = (value)
41
42#define WRITE_REG32(offset, value) 			\
43	(*(volatile unsigned long *)(gfx_virt_regptr + (offset))) = (value)
44
45#define READ_REG16(offset) 					\
46    (*(volatile unsigned short *)(gfx_virt_regptr + (offset)))
47
48#define READ_REG32(offset) 					\
49    (*(volatile unsigned long *)(gfx_virt_regptr + (offset)))
50
51/* ACCESS TO THE ACCELERATOR REGISTERS (REDCLOUD ONLY) */
52
53#define WRITE_GP8(offset, value) 			\
54	(*(volatile unsigned char *)(gfx_virt_gpptr + (offset))) = (value)
55
56#define WRITE_GP16(offset, value) 			\
57	(*(volatile unsigned short *)(gfx_virt_gpptr + (offset))) = (value)
58
59#define WRITE_GP32(offset, value) 			\
60	(*(volatile unsigned long *)(gfx_virt_gpptr + (offset))) = (value)
61
62#define READ_GP16(offset) 					\
63    (*(volatile unsigned short *)(gfx_virt_gpptr + (offset)))
64
65#define READ_GP32(offset) 					\
66    (*(volatile unsigned long *)(gfx_virt_gpptr + (offset)))
67
68/* ACCESS TO THE FRAME BUFFER */
69
70#define WRITE_FB32(offset, value) 			\
71	(*(volatile unsigned long *)(gfx_virt_fbptr + (offset))) = (value)
72
73#define WRITE_FB16(offset, value) 			\
74	(*(volatile unsigned short *)(gfx_virt_fbptr + (offset))) = (value)
75
76#define WRITE_FB8(offset, value) 			\
77	(*(volatile unsigned char *)(gfx_virt_fbptr + (offset))) = (value)
78
79/* ACCESS TO THE VIDEO HARDWARE */
80
81#define READ_VID32(offset) 					\
82	(*(volatile unsigned long *)(gfx_virt_vidptr + (offset)))
83
84#define WRITE_VID32(offset, value) 			\
85	(*(volatile unsigned long *)(gfx_virt_vidptr + (offset))) = (value)
86
87/* ACCESS TO THE VIP HARDWARE */
88
89#define READ_VIP32(offset) 					\
90	(*(volatile unsigned long *)(gfx_virt_vipptr + (offset)))
91
92#define WRITE_VIP32(offset, value)			\
93	(*(volatile unsigned long *)(gfx_virt_vipptr + (offset))) = (value)
94
95/* ACCESS TO THE SCRATCHPAD RAM */
96
97#define WRITE_SCRATCH32(offset, value)		\
98	(*(volatile unsigned long *)(gfx_virt_spptr + (offset))) = (value)
99
100#define WRITE_SCRATCH16(offset, value) 		\
101	(*(volatile unsigned short *)(gfx_virt_spptr + (offset))) = (value)
102
103#define WRITE_SCRATCH8(offset, value) 		\
104	(*(volatile unsigned char *)(gfx_virt_spptr + (offset))) = (value)
105
106#define READ_SCRATCH16(offset) 				\
107    (*(volatile unsigned short *)(gfx_virt_spptr + (offset)))
108
109#define READ_SCRATCH32(offset) \
110    (*(volatile unsigned long *)(gfx_virt_spptr + (offset)))
111
112/* ACCESS TO MSRS */
113
114void gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr,
115                       unsigned long *ptrHigh, unsigned long *ptrLow);
116void gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr,
117                      unsigned long *ptrHigh, unsigned long *ptrLow);
118
119#define MSR_READ( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) 	\
120	gfx_msr_asm_read( ((unsigned short)(MBD_MSR_CAP)), address, 		\
121					valueHigh_ptr, valueLow_ptr )
122
123#define MSR_WRITE( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) 	\
124	gfx_msr_asm_write( ((unsigned short)(MBD_MSR_CAP)), address, 		\
125					valueHigh_ptr, valueLow_ptr )
126
127/* OPTIMIZATION MACROS */
128/* The following macros have been added to allow more complete optimization of
129 * the bitmap-to-screen routines in Durango.  These routines also allow
130 * Durango to run properly within a 16-bit environment.
131 * */
132
133/*****************************************************************************
134 * Macro:	SET_SCRATCH_BASE
135 * Purpose: Record the base address of the BLT buffers. The
136 * 			WRITE_SCRATCH_STRINGxx macros assume that this address is used
137 * 			as the base for all writes.
138 *
139 * Arguments:
140 *    scratch_base -   offset into the GX base for the first BLT buffer byte.
141 ****************************************************************************/
142
143#define SET_SCRATCH_BASE(scratch_base) \
144	{ gfx_gx1_scratch_base = (unsigned long)gfx_virt_spptr + scratch_base; }
145
146#ifdef GFX_OPTIMIZE_ASSEMBLY
147
148/*****************************************************************************
149 * Macro:   WRITE_SCRATCH_STRING
150 * Purpose: Write multiple bytes to the scratchpad buffer
151 *
152 * Arguments:
153 *    dword_bytes  -   	number of bytes to transfer.  This number will always.
154 *                     	be a multiple of 4.  It cannot be modified within the
155 *                     	macro (ex. bytes -= 4)
156 *    bytes_extra  -   	number of non-DWORD aligned bytes
157 *    array        -   	pointer to an array of unsigned characters.
158 *    array_offset -   	offset into the array from which to pull the first
159 *    					character.
160 ****************************************************************************/
161
162#define WRITE_SCRATCH_STRING(dwords, bytes, array, array_offset)	\
163{                                                                   \
164	_asm { mov edi, gfx_gx1_scratch_base }                          \
165	_asm { mov esi, array }                                         \
166	_asm { add esi, array_offset }                                  \
167	_asm { mov ecx, dwords }                                        \
168	_asm { shr ecx, 2 }                                             \
169	_asm { rep movsd }                                              \
170	_asm { mov ecx, bytes }                                         \
171	_asm { rep movsb }                                              \
172}
173
174/*****************************************************************************
175 * Macro:   WRITE_FRAME_BUFFER_STRING32
176 * Purpose: Write multiple dwords to the Frame buffer
177 *
178 * Arguments:
179 *    fboffset     -   	offset to the beginning frame buffer location.
180 *    bytes        -   	number of bytes to transfer.  This number will always.
181 *                     	be a multiple of 4.  It cannot be modified within the
182 *                     	macro (ex. bytes -= 4)
183 *    array        -   	pointer to an array of unsigned characters.
184 *    array_offset -   	offset into the array from which to pull the first
185 *    					character.
186 ****************************************************************************/
187
188#define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset)	\
189{                                                                           \
190	_asm { mov ecx, bytes }                                                 \
191	_asm { shr ecx, 2 }                                                     \
192	_asm { cld }                                                            \
193	_asm { mov edi, gfx_virt_fbptr }                                        \
194	_asm { add edi, fboffset }                                              \
195	_asm { mov esi, array }                                                 \
196	_asm { add esi, array_offset }                                          \
197    _asm { rep movsd }                                                      \
198}
199
200#else
201
202/*****************************************************************************
203 * Macro:   WRITE_SCRATCH_STRING
204 * Purpose: Write multiple bytes to the scratchpad buffer
205 *
206 * Arguments:
207 *    dword_bytes  -   	number of bytes to transfer.  This number will always.
208 *                     	be a multiple of 4.  It cannot be modified within the
209 *                     	macro (ex. bytes -= 4)
210 *    bytes_extra  -   	number of non-DWORD aligned bytes
211 *    array        -   	pointer to an array of unsigned characters.
212 *    array_offset -   	offset into the array from which to pull the first
213 *    					character.
214 ****************************************************************************/
215
216#define WRITE_SCRATCH_STRING(dword_bytes, bytes_extra, array, array_offset)	\
217{                                                                           \
218	unsigned long i, j;                                                     \
219	unsigned long aroffset = (unsigned long)array + (array_offset);         \
220	                                                                        \
221	/* WRITE DWORDS */                                                      \
222	                                                                        \
223	for (i = 0; i < dword_bytes; i += 4)                                    \
224		*((volatile unsigned long *)(gfx_gx1_scratch_base + i)) = 			\
225			*((unsigned long *)(aroffset + i));								\
226	                                                                        \
227	/* WRITE BYTES */                                                       \
228	                                                                        \
229	j = i + bytes_extra;	                                                \
230	while (i < j) {	                                                        \
231		*((volatile unsigned char *)(gfx_gx1_scratch_base + i)) = 			\
232			*((unsigned char *)(aroffset + i));								\
233		i++;	                                                            \
234	}	                                                                    \
235}
236
237/*****************************************************************************
238 * Macro:   WRITE_FRAME_BUFFER_STRING32
239 * Purpose: Write multiple dwords to the Frame buffer
240 *
241 * Arguments:
242 *    fboffset     -   	offset to the beginning frame buffer location.
243 *    bytes        -   	number of bytes to transfer.  This number will always.
244 *                     	be a multiple of 4.  It cannot be modified within the
245 *                     	macro (ex. bytes -= 4)
246 *    array        -   	pointer to an array of unsigned characters.
247 *    array_offset -   	offset into the array from which to pull the first
248 *    					character.
249 ****************************************************************************/
250
251#define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset)	\
252{                                                                           \
253	unsigned long i;                                                        \
254	unsigned long aroffset = (unsigned long)array + (array_offset);         \
255	for (i = 0; i < bytes; i += 4)                                          \
256		WRITE_FB32 ((fboffset) + i, *((unsigned long *)(aroffset + i)));    \
257}
258
259#endif
260
261/*****************************************************************************
262 * Macro:   WRITE_FRAME_BUFFER_STRING8
263 * Purpose: Write multiple bytes to the frame buffer
264 *
265 * Arguments:
266 *    spoffset     -   	offset to the beginning frame buffer location.
267 *    bytes        -   	number of bytes to transfer.  This number cannot be
268 *    					modified within the macro (ex. bytes -= 4)
269 *    array        -  	pointer to an array of unsigned characters.
270 *    array_offset -   	offset into the array from which to pull the first
271 *    					character.
272 ****************************************************************************/
273
274#define WRITE_FRAME_BUFFER_STRING8(fboffset, bytes, array, array_offset)	\
275{                                                                           \
276	unsigned long i;                                                        \
277	unsigned long aroffset = (unsigned long)array + (array_offset);         \
278	for (i = 0; i < bytes; i++)                                             \
279		WRITE_FB8 ((fboffset) + i, *((unsigned char *)(aroffset + i)));     \
280}
281
282/*****************************************************************************
283 * Macro:   WRITE_GPREG_STRING32
284 * Purpose: Write multiple dwords to one GP register.
285 *
286 * Arguments:
287 *    regoffset    -   	Offset of the GP register to be written.
288 *    dwords       -   	number of dwords to transfer.  It cannot be modified
289 *    					within the macro (ex. dwords--)
290 *    counter      -   	name of a counter variable that can be used in a loop.
291 *    			  		This is used to optimize macros written in C.
292 *    array        -   	pointer to an array of unsigned characters.
293 *    array_offset -   	offset into the array from which to pull the first
294 *    					character.
295 *    temp         -   	name of a temporary variable that can be used for
296 *    					calculations.
297 *                     	This argument is also used for C-only macros.
298 ****************************************************************************/
299
300#define WRITE_GPREG_STRING32(regoffset, dwords, counter, array, 		\
301				array_offset, temp)           							\
302{                                                                       \
303	temp = (unsigned long)array + (array_offset);                       \
304	for (counter = 0; counter < dwords; counter++)                      \
305		WRITE_GP32 (regoffset, *((unsigned long *)temp + counter));     \
306}
307
308/*****************************************************************************
309 * Macro:   WRITE_GPREG_STRING8
310 * Purpose: Write 4 or less bytes to one GP register.
311 *
312 * Arguments:
313 *    regoffset    -   	Offset of the GP register to be written.
314 *    bytes        -   	number of bytes to transfer.  This number will always.
315 *                     	be less than 4.  It cannot be modified within the
316 *                     	macro (ex. bytes--)
317 *    shift        -   	name of a shift variable that can be used as a shift
318 *    					count.
319 *                     	This variable holds the initial shift value into the
320 *                     	GP register.
321 *    counter      -   	name of a counter variable that can be used in a loop.
322 *      				This is used to optimize macros written in C.
323 *    array        -   	pointer to an array of unsigned characters.
324 *    array_offset -   	offset into the array from which to pull the first
325 *    					character.
326 *    temp1        -   	name of a temporary variable that can be used for
327 *    					calculations.
328 *                     	This argument is also used for C-only macros.
329 *    temp2        -   	name of a temporary variable that can be used for
330 *    					calculations.
331 *                     	This argument is also used for C-only macros.
332 ****************************************************************************/
333#define WRITE_GPREG_STRING8(regoffset, bytes, shift, counter, array,	\
334				array_offset, temp1, temp2)           					\
335{                                                                       \
336	if (bytes) { 	                                                   	\
337		temp1 = (unsigned long)array + (array_offset);                  \
338		temp2 = 0;                                                      \
339		for (counter = 0; counter < bytes; counter++) {                 \
340			temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + 		\
341											counter)))) << shift;     	\
342			shift += 8;                                                 \
343		}                                                               \
344		WRITE_GP32 (regoffset, temp2);                                  \
345	}                                                                   \
346}
347
348/* END OF FILE */
349