1 /* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*-
2 * Created: Fri Nov 24 22:07:58 2000 by gareth@valinux.com
3 */
4 /*-
5 * Copyright 2000 Gareth Hughes
6 * Copyright 2002 Frank C. Earl
7 * Copyright 2002-2003 Leif Delgass
8 * All Rights Reserved.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the next
18 * paragraph) shall be included in all copies or substantial portions of the
19 * Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Gareth Hughes <gareth@valinux.com>
30 * Frank C. Earl <fearl@airmail.net>
31 * Leif Delgass <ldelgass@retinalburn.net>
32 * Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: releng/6.4/sys/dev/drm/mach64_drv.h 153401 2005-12-14 00:52:59Z anholt $");
37
38 #ifndef __MACH64_DRV_H__
39 #define __MACH64_DRV_H__
40
41 /* General customization:
42 */
43
44 #define DRIVER_AUTHOR "Gareth Hughes, Leif Delgass, José Fonseca"
45
46 #define DRIVER_NAME "mach64"
47 #define DRIVER_DESC "DRM module for the ATI Rage Pro"
48 #define DRIVER_DATE "20020904"
49
50 #define DRIVER_MAJOR 1
51 #define DRIVER_MINOR 0
52 #define DRIVER_PATCHLEVEL 0
53
54 /* FIXME: remove these when not needed */
55 /* Development driver options */
56 #define MACH64_EXTRA_CHECKING 0 /* Extra sanity checks for DMA/freelist management */
57 #define MACH64_VERBOSE 0 /* Verbose debugging output */
58
59 typedef struct drm_mach64_freelist {
60 struct list_head list; /* List pointers for free_list, placeholders, or pending list */
61 drm_buf_t *buf; /* Pointer to the buffer */
62 int discard; /* This flag is set when we're done (re)using a buffer */
63 u32 ring_ofs; /* dword offset in ring of last descriptor for this buffer */
64 } drm_mach64_freelist_t;
65
66 typedef struct drm_mach64_descriptor_ring {
67 drm_dma_handle_t *dmah; /* Handle to pci dma memory */
68 void *start; /* write pointer (cpu address) to start of descriptor ring */
69 u32 start_addr; /* bus address of beginning of descriptor ring */
70 int size; /* size of ring in bytes */
71
72 u32 head_addr; /* bus address of descriptor ring head */
73 u32 head; /* dword offset of descriptor ring head */
74 u32 tail; /* dword offset of descriptor ring tail */
75 u32 tail_mask; /* mask used to wrap ring */
76 int space; /* number of free bytes in ring */
77 } drm_mach64_descriptor_ring_t;
78
79 typedef struct drm_mach64_private {
80 drm_mach64_sarea_t *sarea_priv;
81
82 int is_pci;
83 drm_mach64_dma_mode_t driver_mode; /* Async DMA, sync DMA, or MMIO */
84
85 int usec_timeout; /* Timeout for the wait functions */
86
87 drm_mach64_descriptor_ring_t ring; /* DMA descriptor table (ring buffer) */
88 int ring_running; /* Is bus mastering is enabled */
89
90 struct list_head free_list; /* Free-list head */
91 struct list_head placeholders; /* Placeholder list for buffers held by clients */
92 struct list_head pending; /* Buffers pending completion */
93
94 u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES]; /* dword ring offsets of most recent frame swaps */
95
96 unsigned int fb_bpp;
97 unsigned int front_offset, front_pitch;
98 unsigned int back_offset, back_pitch;
99
100 unsigned int depth_bpp;
101 unsigned int depth_offset, depth_pitch;
102
103 u32 front_offset_pitch;
104 u32 back_offset_pitch;
105 u32 depth_offset_pitch;
106
107 drm_local_map_t *sarea;
108 drm_local_map_t *fb;
109 drm_local_map_t *mmio;
110 drm_local_map_t *ring_map;
111 drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */
112 drm_local_map_t *agp_textures;
113 } drm_mach64_private_t;
114
115 extern drm_ioctl_desc_t mach64_ioctls[];
116 extern int mach64_max_ioctl;
117
118 /* mach64_dma.c */
119 extern int mach64_dma_init(DRM_IOCTL_ARGS);
120 extern int mach64_dma_idle(DRM_IOCTL_ARGS);
121 extern int mach64_dma_flush(DRM_IOCTL_ARGS);
122 extern int mach64_engine_reset(DRM_IOCTL_ARGS);
123 extern int mach64_dma_buffers(DRM_IOCTL_ARGS);
124 extern void mach64_driver_lastclose(drm_device_t * dev);
125
126 extern int mach64_init_freelist(drm_device_t * dev);
127 extern void mach64_destroy_freelist(drm_device_t * dev);
128 extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv);
129
130 extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv,
131 int entries);
132 extern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv);
133 extern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n);
134 extern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv);
135 extern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv);
136 extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv);
137 extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv);
138 extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv);
139
140 extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv);
141 extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv);
142 extern int mach64_do_cleanup_dma(drm_device_t * dev);
143
144 /* mach64_state.c */
145 extern int mach64_dma_clear(DRM_IOCTL_ARGS);
146 extern int mach64_dma_swap(DRM_IOCTL_ARGS);
147 extern int mach64_dma_vertex(DRM_IOCTL_ARGS);
148 extern int mach64_dma_blit(DRM_IOCTL_ARGS);
149 extern int mach64_get_param(DRM_IOCTL_ARGS);
150 extern int mach64_driver_vblank_wait(drm_device_t * dev,
151 unsigned int *sequence);
152
153 extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
154 extern void mach64_driver_irq_preinstall(drm_device_t * dev);
155 extern void mach64_driver_irq_postinstall(drm_device_t * dev);
156 extern void mach64_driver_irq_uninstall(drm_device_t * dev);
157
158 /* ================================================================
159 * Registers
160 */
161
162 #define MACH64_AGP_BASE 0x0148
163 #define MACH64_AGP_CNTL 0x014c
164 #define MACH64_ALPHA_TST_CNTL 0x0550
165
166 #define MACH64_DSP_CONFIG 0x0420
167 #define MACH64_DSP_ON_OFF 0x0424
168 #define MACH64_EXT_MEM_CNTL 0x04ac
169 #define MACH64_GEN_TEST_CNTL 0x04d0
170 #define MACH64_HW_DEBUG 0x047c
171 #define MACH64_MEM_ADDR_CONFIG 0x0434
172 #define MACH64_MEM_BUF_CNTL 0x042c
173 #define MACH64_MEM_CNTL 0x04b0
174
175 #define MACH64_BM_ADDR 0x0648
176 #define MACH64_BM_COMMAND 0x0188
177 #define MACH64_BM_DATA 0x0648
178 #define MACH64_BM_FRAME_BUF_OFFSET 0x0180
179 #define MACH64_BM_GUI_TABLE 0x01b8
180 #define MACH64_BM_GUI_TABLE_CMD 0x064c
181 # define MACH64_CIRCULAR_BUF_SIZE_16KB (0 << 0)
182 # define MACH64_CIRCULAR_BUF_SIZE_32KB (1 << 0)
183 # define MACH64_CIRCULAR_BUF_SIZE_64KB (2 << 0)
184 # define MACH64_CIRCULAR_BUF_SIZE_128KB (3 << 0)
185 # define MACH64_LAST_DESCRIPTOR (1 << 31)
186 #define MACH64_BM_HOSTDATA 0x0644
187 #define MACH64_BM_STATUS 0x018c
188 #define MACH64_BM_SYSTEM_MEM_ADDR 0x0184
189 #define MACH64_BM_SYSTEM_TABLE 0x01bc
190 #define MACH64_BUS_CNTL 0x04a0
191 # define MACH64_BUS_MSTR_RESET (1 << 1)
192 # define MACH64_BUS_APER_REG_DIS (1 << 4)
193 # define MACH64_BUS_FLUSH_BUF (1 << 2)
194 # define MACH64_BUS_MASTER_DIS (1 << 6)
195 # define MACH64_BUS_EXT_REG_EN (1 << 27)
196
197 #define MACH64_CLR_CMP_CLR 0x0700
198 #define MACH64_CLR_CMP_CNTL 0x0708
199 #define MACH64_CLR_CMP_MASK 0x0704
200 #define MACH64_CONFIG_CHIP_ID 0x04e0
201 #define MACH64_CONFIG_CNTL 0x04dc
202 #define MACH64_CONFIG_STAT0 0x04e4
203 #define MACH64_CONFIG_STAT1 0x0494
204 #define MACH64_CONFIG_STAT2 0x0498
205 #define MACH64_CONTEXT_LOAD_CNTL 0x072c
206 #define MACH64_CONTEXT_MASK 0x0720
207 #define MACH64_COMPOSITE_SHADOW_ID 0x0798
208 #define MACH64_CRC_SIG 0x04e8
209 #define MACH64_CUSTOM_MACRO_CNTL 0x04d4
210
211 #define MACH64_DP_BKGD_CLR 0x06c0
212 #define MACH64_DP_FOG_CLR 0x06c4
213 #define MACH64_DP_FGRD_BKGD_CLR 0x06e0
214 #define MACH64_DP_FRGD_CLR 0x06c4
215 #define MACH64_DP_FGRD_CLR_MIX 0x06dc
216
217 #define MACH64_DP_MIX 0x06d4
218 # define BKGD_MIX_NOT_D (0 << 0)
219 # define BKGD_MIX_ZERO (1 << 0)
220 # define BKGD_MIX_ONE (2 << 0)
221 # define MACH64_BKGD_MIX_D (3 << 0)
222 # define BKGD_MIX_NOT_S (4 << 0)
223 # define BKGD_MIX_D_XOR_S (5 << 0)
224 # define BKGD_MIX_NOT_D_XOR_S (6 << 0)
225 # define MACH64_BKGD_MIX_S (7 << 0)
226 # define BKGD_MIX_NOT_D_OR_NOT_S (8 << 0)
227 # define BKGD_MIX_D_OR_NOT_S (9 << 0)
228 # define BKGD_MIX_NOT_D_OR_S (10 << 0)
229 # define BKGD_MIX_D_OR_S (11 << 0)
230 # define BKGD_MIX_D_AND_S (12 << 0)
231 # define BKGD_MIX_NOT_D_AND_S (13 << 0)
232 # define BKGD_MIX_D_AND_NOT_S (14 << 0)
233 # define BKGD_MIX_NOT_D_AND_NOT_S (15 << 0)
234 # define BKGD_MIX_D_PLUS_S_DIV2 (23 << 0)
235 # define FRGD_MIX_NOT_D (0 << 16)
236 # define FRGD_MIX_ZERO (1 << 16)
237 # define FRGD_MIX_ONE (2 << 16)
238 # define FRGD_MIX_D (3 << 16)
239 # define FRGD_MIX_NOT_S (4 << 16)
240 # define FRGD_MIX_D_XOR_S (5 << 16)
241 # define FRGD_MIX_NOT_D_XOR_S (6 << 16)
242 # define MACH64_FRGD_MIX_S (7 << 16)
243 # define FRGD_MIX_NOT_D_OR_NOT_S (8 << 16)
244 # define FRGD_MIX_D_OR_NOT_S (9 << 16)
245 # define FRGD_MIX_NOT_D_OR_S (10 << 16)
246 # define FRGD_MIX_D_OR_S (11 << 16)
247 # define FRGD_MIX_D_AND_S (12 << 16)
248 # define FRGD_MIX_NOT_D_AND_S (13 << 16)
249 # define FRGD_MIX_D_AND_NOT_S (14 << 16)
250 # define FRGD_MIX_NOT_D_AND_NOT_S (15 << 16)
251 # define FRGD_MIX_D_PLUS_S_DIV2 (23 << 16)
252
253 #define MACH64_DP_PIX_WIDTH 0x06d0
254 # define MACH64_HOST_TRIPLE_ENABLE (1 << 13)
255 # define MACH64_BYTE_ORDER_MSB_TO_LSB (0 << 24)
256 # define MACH64_BYTE_ORDER_LSB_TO_MSB (1 << 24)
257
258 #define MACH64_DP_SRC 0x06d8
259 # define MACH64_BKGD_SRC_BKGD_CLR (0 << 0)
260 # define MACH64_BKGD_SRC_FRGD_CLR (1 << 0)
261 # define MACH64_BKGD_SRC_HOST (2 << 0)
262 # define MACH64_BKGD_SRC_BLIT (3 << 0)
263 # define MACH64_BKGD_SRC_PATTERN (4 << 0)
264 # define MACH64_BKGD_SRC_3D (5 << 0)
265 # define MACH64_FRGD_SRC_BKGD_CLR (0 << 8)
266 # define MACH64_FRGD_SRC_FRGD_CLR (1 << 8)
267 # define MACH64_FRGD_SRC_HOST (2 << 8)
268 # define MACH64_FRGD_SRC_BLIT (3 << 8)
269 # define MACH64_FRGD_SRC_PATTERN (4 << 8)
270 # define MACH64_FRGD_SRC_3D (5 << 8)
271 # define MACH64_MONO_SRC_ONE (0 << 16)
272 # define MACH64_MONO_SRC_PATTERN (1 << 16)
273 # define MACH64_MONO_SRC_HOST (2 << 16)
274 # define MACH64_MONO_SRC_BLIT (3 << 16)
275
276 #define MACH64_DP_WRITE_MASK 0x06c8
277
278 #define MACH64_DST_CNTL 0x0530
279 # define MACH64_DST_X_RIGHT_TO_LEFT (0 << 0)
280 # define MACH64_DST_X_LEFT_TO_RIGHT (1 << 0)
281 # define MACH64_DST_Y_BOTTOM_TO_TOP (0 << 1)
282 # define MACH64_DST_Y_TOP_TO_BOTTOM (1 << 1)
283 # define MACH64_DST_X_MAJOR (0 << 2)
284 # define MACH64_DST_Y_MAJOR (1 << 2)
285 # define MACH64_DST_X_TILE (1 << 3)
286 # define MACH64_DST_Y_TILE (1 << 4)
287 # define MACH64_DST_LAST_PEL (1 << 5)
288 # define MACH64_DST_POLYGON_ENABLE (1 << 6)
289 # define MACH64_DST_24_ROTATION_ENABLE (1 << 7)
290
291 #define MACH64_DST_HEIGHT_WIDTH 0x0518
292 #define MACH64_DST_OFF_PITCH 0x0500
293 #define MACH64_DST_WIDTH_HEIGHT 0x06ec
294 #define MACH64_DST_X_Y 0x06e8
295 #define MACH64_DST_Y_X 0x050c
296
297 #define MACH64_FIFO_STAT 0x0710
298 # define MACH64_FIFO_SLOT_MASK 0x0000ffff
299 # define MACH64_FIFO_ERR (1 << 31)
300
301 #define MACH64_GEN_TEST_CNTL 0x04d0
302 # define MACH64_GUI_ENGINE_ENABLE (1 << 8)
303 #define MACH64_GUI_CMDFIFO_DEBUG 0x0170
304 #define MACH64_GUI_CMDFIFO_DATA 0x0174
305 #define MACH64_GUI_CNTL 0x0178
306 # define MACH64_CMDFIFO_SIZE_MASK 0x00000003ul
307 # define MACH64_CMDFIFO_SIZE_192 0x00000000ul
308 # define MACH64_CMDFIFO_SIZE_128 0x00000001ul
309 # define MACH64_CMDFIFO_SIZE_64 0x00000002ul
310 #define MACH64_GUI_STAT 0x0738
311 # define MACH64_GUI_ACTIVE (1 << 0)
312 #define MACH64_GUI_TRAJ_CNTL 0x0730
313
314 #define MACH64_HOST_CNTL 0x0640
315 #define MACH64_HOST_DATA0 0x0600
316
317 #define MACH64_ONE_OVER_AREA 0x029c
318 #define MACH64_ONE_OVER_AREA_UC 0x0300
319
320 #define MACH64_PAT_REG0 0x0680
321 #define MACH64_PAT_REG1 0x0684
322
323 #define MACH64_SC_LEFT 0x06a0
324 #define MACH64_SC_RIGHT 0x06a4
325 #define MACH64_SC_LEFT_RIGHT 0x06a8
326 #define MACH64_SC_TOP 0x06ac
327 #define MACH64_SC_BOTTOM 0x06b0
328 #define MACH64_SC_TOP_BOTTOM 0x06b4
329
330 #define MACH64_SCALE_3D_CNTL 0x05fc
331 #define MACH64_SCRATCH_REG0 0x0480
332 #define MACH64_SCRATCH_REG1 0x0484
333 #define MACH64_SECONDARY_TEX_OFF 0x0778
334 #define MACH64_SETUP_CNTL 0x0304
335 #define MACH64_SRC_CNTL 0x05b4
336 # define MACH64_SRC_BM_ENABLE (1 << 8)
337 # define MACH64_SRC_BM_SYNC (1 << 9)
338 # define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM (0 << 10)
339 # define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME (1 << 10)
340 # define MACH64_SRC_BM_OP_REG_TO_SYSTEM (2 << 10)
341 # define MACH64_SRC_BM_OP_SYSTEM_TO_REG (3 << 10)
342 #define MACH64_SRC_HEIGHT1 0x0594
343 #define MACH64_SRC_HEIGHT2 0x05ac
344 #define MACH64_SRC_HEIGHT1_WIDTH1 0x0598
345 #define MACH64_SRC_HEIGHT2_WIDTH2 0x05b0
346 #define MACH64_SRC_OFF_PITCH 0x0580
347 #define MACH64_SRC_WIDTH1 0x0590
348 #define MACH64_SRC_Y_X 0x058c
349
350 #define MACH64_TEX_0_OFF 0x05c0
351 #define MACH64_TEX_CNTL 0x0774
352 #define MACH64_TEX_SIZE_PITCH 0x0770
353 #define MACH64_TIMER_CONFIG 0x0428
354
355 #define MACH64_VERTEX_1_ARGB 0x0254
356 #define MACH64_VERTEX_1_S 0x0240
357 #define MACH64_VERTEX_1_SECONDARY_S 0x0328
358 #define MACH64_VERTEX_1_SECONDARY_T 0x032c
359 #define MACH64_VERTEX_1_SECONDARY_W 0x0330
360 #define MACH64_VERTEX_1_SPEC_ARGB 0x024c
361 #define MACH64_VERTEX_1_T 0x0244
362 #define MACH64_VERTEX_1_W 0x0248
363 #define MACH64_VERTEX_1_X_Y 0x0258
364 #define MACH64_VERTEX_1_Z 0x0250
365 #define MACH64_VERTEX_2_ARGB 0x0274
366 #define MACH64_VERTEX_2_S 0x0260
367 #define MACH64_VERTEX_2_SECONDARY_S 0x0334
368 #define MACH64_VERTEX_2_SECONDARY_T 0x0338
369 #define MACH64_VERTEX_2_SECONDARY_W 0x033c
370 #define MACH64_VERTEX_2_SPEC_ARGB 0x026c
371 #define MACH64_VERTEX_2_T 0x0264
372 #define MACH64_VERTEX_2_W 0x0268
373 #define MACH64_VERTEX_2_X_Y 0x0278
374 #define MACH64_VERTEX_2_Z 0x0270
375 #define MACH64_VERTEX_3_ARGB 0x0294
376 #define MACH64_VERTEX_3_S 0x0280
377 #define MACH64_VERTEX_3_SECONDARY_S 0x02a0
378 #define MACH64_VERTEX_3_SECONDARY_T 0x02a4
379 #define MACH64_VERTEX_3_SECONDARY_W 0x02a8
380 #define MACH64_VERTEX_3_SPEC_ARGB 0x028c
381 #define MACH64_VERTEX_3_T 0x0284
382 #define MACH64_VERTEX_3_W 0x0288
383 #define MACH64_VERTEX_3_X_Y 0x0298
384 #define MACH64_VERTEX_3_Z 0x0290
385
386 #define MACH64_Z_CNTL 0x054c
387 #define MACH64_Z_OFF_PITCH 0x0548
388
389 #define MACH64_CRTC_VLINE_CRNT_VLINE 0x0410
390 # define MACH64_CRTC_VLINE_MASK 0x000007ff
391 # define MACH64_CRTC_CRNT_VLINE_MASK 0x07ff0000
392 #define MACH64_CRTC_OFF_PITCH 0x0414
393 #define MACH64_CRTC_INT_CNTL 0x0418
394 # define MACH64_CRTC_VBLANK (1 << 0)
395 # define MACH64_CRTC_VBLANK_INT_EN (1 << 1)
396 # define MACH64_CRTC_VBLANK_INT (1 << 2)
397 # define MACH64_CRTC_VLINE_INT_EN (1 << 3)
398 # define MACH64_CRTC_VLINE_INT (1 << 4)
399 # define MACH64_CRTC_VLINE_SYNC (1 << 5) /* 0=even, 1=odd */
400 # define MACH64_CRTC_FRAME (1 << 6) /* 0=even, 1=odd */
401 # define MACH64_CRTC_SNAPSHOT_INT_EN (1 << 7)
402 # define MACH64_CRTC_SNAPSHOT_INT (1 << 8)
403 # define MACH64_CRTC_I2C_INT_EN (1 << 9)
404 # define MACH64_CRTC_I2C_INT (1 << 10)
405 # define MACH64_CRTC2_VBLANK (1 << 11) /* LT Pro */
406 # define MACH64_CRTC2_VBLANK_INT_EN (1 << 12) /* LT Pro */
407 # define MACH64_CRTC2_VBLANK_INT (1 << 13) /* LT Pro */
408 # define MACH64_CRTC2_VLINE_INT_EN (1 << 14) /* LT Pro */
409 # define MACH64_CRTC2_VLINE_INT (1 << 15) /* LT Pro */
410 # define MACH64_CRTC_CAPBUF0_INT_EN (1 << 16)
411 # define MACH64_CRTC_CAPBUF0_INT (1 << 17)
412 # define MACH64_CRTC_CAPBUF1_INT_EN (1 << 18)
413 # define MACH64_CRTC_CAPBUF1_INT (1 << 19)
414 # define MACH64_CRTC_OVERLAY_EOF_INT_EN (1 << 20)
415 # define MACH64_CRTC_OVERLAY_EOF_INT (1 << 21)
416 # define MACH64_CRTC_ONESHOT_CAP_INT_EN (1 << 22)
417 # define MACH64_CRTC_ONESHOT_CAP_INT (1 << 23)
418 # define MACH64_CRTC_BUSMASTER_EOL_INT_EN (1 << 24)
419 # define MACH64_CRTC_BUSMASTER_EOL_INT (1 << 25)
420 # define MACH64_CRTC_GP_INT_EN (1 << 26)
421 # define MACH64_CRTC_GP_INT (1 << 27)
422 # define MACH64_CRTC2_VLINE_SYNC (1 << 28) /* LT Pro */ /* 0=even, 1=odd */
423 # define MACH64_CRTC_SNAPSHOT2_INT_EN (1 << 29) /* LT Pro */
424 # define MACH64_CRTC_SNAPSHOT2_INT (1 << 30) /* LT Pro */
425 # define MACH64_CRTC_VBLANK2_INT (1 << 31)
426 # define MACH64_CRTC_INT_ENS \
427 ( \
428 MACH64_CRTC_VBLANK_INT_EN | \
429 MACH64_CRTC_VLINE_INT_EN | \
430 MACH64_CRTC_SNAPSHOT_INT_EN | \
431 MACH64_CRTC_I2C_INT_EN | \
432 MACH64_CRTC2_VBLANK_INT_EN | \
433 MACH64_CRTC2_VLINE_INT_EN | \
434 MACH64_CRTC_CAPBUF0_INT_EN | \
435 MACH64_CRTC_CAPBUF1_INT_EN | \
436 MACH64_CRTC_OVERLAY_EOF_INT_EN | \
437 MACH64_CRTC_ONESHOT_CAP_INT_EN | \
438 MACH64_CRTC_BUSMASTER_EOL_INT_EN | \
439 MACH64_CRTC_GP_INT_EN | \
440 MACH64_CRTC_SNAPSHOT2_INT_EN | \
441 0 \
442 )
443 # define MACH64_CRTC_INT_ACKS \
444 ( \
445 MACH64_CRTC_VBLANK_INT | \
446 MACH64_CRTC_VLINE_INT | \
447 MACH64_CRTC_SNAPSHOT_INT | \
448 MACH64_CRTC_I2C_INT | \
449 MACH64_CRTC2_VBLANK_INT | \
450 MACH64_CRTC2_VLINE_INT | \
451 MACH64_CRTC_CAPBUF0_INT | \
452 MACH64_CRTC_CAPBUF1_INT | \
453 MACH64_CRTC_OVERLAY_EOF_INT | \
454 MACH64_CRTC_ONESHOT_CAP_INT | \
455 MACH64_CRTC_BUSMASTER_EOL_INT | \
456 MACH64_CRTC_GP_INT | \
457 MACH64_CRTC_SNAPSHOT2_INT | \
458 MACH64_CRTC_VBLANK2_INT | \
459 0 \
460 )
461
462 #define MACH64_DATATYPE_CI8 2
463 #define MACH64_DATATYPE_ARGB1555 3
464 #define MACH64_DATATYPE_RGB565 4
465 #define MACH64_DATATYPE_ARGB8888 6
466 #define MACH64_DATATYPE_RGB332 7
467 #define MACH64_DATATYPE_Y8 8
468 #define MACH64_DATATYPE_RGB8 9
469 #define MACH64_DATATYPE_VYUY422 11
470 #define MACH64_DATATYPE_YVYU422 12
471 #define MACH64_DATATYPE_AYUV444 14
472 #define MACH64_DATATYPE_ARGB4444 15
473
474 #define MACH64_READ(reg) DRM_READ32(dev_priv->mmio, (reg) )
475 #define MACH64_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio, (reg), (val) )
476
477 #define DWMREG0 0x0400
478 #define DWMREG0_END 0x07ff
479 #define DWMREG1 0x0000
480 #define DWMREG1_END 0x03ff
481
482 #define ISREG0(r) (((r) >= DWMREG0) && ((r) <= DWMREG0_END))
483 #define DMAREG0(r) (((r) - DWMREG0) >> 2)
484 #define DMAREG1(r) ((((r) - DWMREG1) >> 2 ) | 0x0100)
485 #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
486
487 #define MMREG0 0x0000
488 #define MMREG0_END 0x00ff
489
490 #define ISMMREG0(r) (((r) >= MMREG0) && ((r) <= MMREG0_END))
491 #define MMSELECT0(r) (((r) << 2) + DWMREG0)
492 #define MMSELECT1(r) (((((r) & 0xff) << 2) + DWMREG1))
493 #define MMSELECT(r) (ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r))
494
495 /* ================================================================
496 * DMA constants
497 */
498
499 /* DMA descriptor field indices:
500 * The descriptor fields are loaded into the read-only
501 * BM_* system bus master registers during a bus-master operation
502 */
503 #define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */
504 #define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */
505 #define MACH64_DMA_COMMAND 2 /* BM_COMMAND */
506 #define MACH64_DMA_RESERVED 3 /* BM_STATUS */
507
508 /* BM_COMMAND descriptor field flags */
509 #define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */
510 #define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */
511
512 #define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */
513 #define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */
514
515 /* ================================================================
516 * Misc helper macros
517 */
518
519 static __inline__ void mach64_set_dma_eol(volatile u32 * addr)
520 {
521 #if defined(__i386__)
522 int nr = 31;
523
524 /* Taken from include/asm-i386/bitops.h linux header */
525 __asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr)
526 :"Ir"(nr));
527 #elif defined(__powerpc__)
528 u32 old;
529 u32 mask = cpu_to_le32(MACH64_DMA_EOL);
530
531 /* Taken from the include/asm-ppc/bitops.h linux header */
532 __asm__ __volatile__("\n\
533 1: lwarx %0,0,%3 \n\
534 or %0,%0,%2 \n\
535 stwcx. %0,0,%3 \n\
536 bne- 1b":"=&r"(old), "=m"(*addr)
537 :"r"(mask), "r"(addr), "m"(*addr)
538 :"cc");
539 #elif defined(__alpha__)
540 u32 temp;
541 u32 mask = MACH64_DMA_EOL;
542
543 /* Taken from the include/asm-alpha/bitops.h linux header */
544 __asm__ __volatile__("1: ldl_l %0,%3\n"
545 " bis %0,%2,%0\n"
546 " stl_c %0,%1\n"
547 " beq %0,2f\n"
548 ".subsection 2\n"
549 "2: br 1b\n"
550 ".previous":"=&r"(temp), "=m"(*addr)
551 :"Ir"(mask), "m"(*addr));
552 #else
553 u32 mask = cpu_to_le32(MACH64_DMA_EOL);
554
555 *addr |= mask;
556 #endif
557 }
558
559 static __inline__ void mach64_clear_dma_eol(volatile u32 * addr)
560 {
561 #if defined(__i386__)
562 int nr = 31;
563
564 /* Taken from include/asm-i386/bitops.h linux header */
565 __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr)
566 :"Ir"(nr));
567 #elif defined(__powerpc__)
568 u32 old;
569 u32 mask = cpu_to_le32(MACH64_DMA_EOL);
570
571 /* Taken from the include/asm-ppc/bitops.h linux header */
572 __asm__ __volatile__("\n\
573 1: lwarx %0,0,%3 \n\
574 andc %0,%0,%2 \n\
575 stwcx. %0,0,%3 \n\
576 bne- 1b":"=&r"(old), "=m"(*addr)
577 :"r"(mask), "r"(addr), "m"(*addr)
578 :"cc");
579 #elif defined(__alpha__)
580 u32 temp;
581 u32 mask = ~MACH64_DMA_EOL;
582
583 /* Taken from the include/asm-alpha/bitops.h linux header */
584 __asm__ __volatile__("1: ldl_l %0,%3\n"
585 " and %0,%2,%0\n"
586 " stl_c %0,%1\n"
587 " beq %0,2f\n"
588 ".subsection 2\n"
589 "2: br 1b\n"
590 ".previous":"=&r"(temp), "=m"(*addr)
591 :"Ir"(mask), "m"(*addr));
592 #else
593 u32 mask = cpu_to_le32(~MACH64_DMA_EOL);
594
595 *addr &= mask;
596 #endif
597 }
598
599 static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv)
600 {
601 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
602
603 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
604 __FUNCTION__,
605 ring->head_addr, ring->head, ring->tail, ring->space);
606
607 if (mach64_do_wait_for_idle(dev_priv) < 0) {
608 mach64_do_engine_reset(dev_priv);
609 }
610
611 if (dev_priv->driver_mode != MACH64_MODE_MMIO) {
612 /* enable bus mastering and block 1 registers */
613 MACH64_WRITE(MACH64_BUS_CNTL,
614 (MACH64_READ(MACH64_BUS_CNTL) &
615 ~MACH64_BUS_MASTER_DIS)
616 | MACH64_BUS_EXT_REG_EN);
617 mach64_do_wait_for_idle(dev_priv);
618 }
619
620 /* reset descriptor table ring head */
621 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
622 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
623
624 dev_priv->ring_running = 1;
625 }
626
627 static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
628 drm_mach64_descriptor_ring_t * ring)
629 {
630 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
631 __FUNCTION__,
632 ring->head_addr, ring->head, ring->tail, ring->space);
633
634 /* reset descriptor table ring head */
635 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
636 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
637
638 if (dev_priv->driver_mode == MACH64_MODE_MMIO) {
639 mach64_do_dispatch_pseudo_dma(dev_priv);
640 } else {
641 /* enable GUI bus mastering, and sync the bus master to the GUI */
642 MACH64_WRITE(MACH64_SRC_CNTL,
643 MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
644 MACH64_SRC_BM_OP_SYSTEM_TO_REG);
645
646 /* kick off the transfer */
647 MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0);
648 if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) {
649 if ((mach64_do_wait_for_idle(dev_priv)) < 0) {
650 DRM_ERROR("%s: idle failed, resetting engine\n",
651 __FUNCTION__);
652 mach64_dump_engine_info(dev_priv);
653 mach64_do_engine_reset(dev_priv);
654 return;
655 }
656 mach64_do_release_used_buffers(dev_priv);
657 }
658 }
659 }
660
661 static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv,
662 drm_mach64_descriptor_ring_t * ring)
663 {
664 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
665 __FUNCTION__,
666 ring->head_addr, ring->head, ring->tail, ring->space);
667
668 if (!dev_priv->ring_running) {
669 mach64_ring_start(dev_priv);
670
671 if (ring->head != ring->tail) {
672 mach64_ring_resume(dev_priv, ring);
673 }
674 } else {
675 /* GUI_ACTIVE must be read before BM_GUI_TABLE to
676 * correctly determine the ring head
677 */
678 int gui_active =
679 MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE;
680
681 ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0;
682
683 if (gui_active) {
684 /* If not idle, BM_GUI_TABLE points one descriptor
685 * past the current head
686 */
687 if (ring->head_addr == ring->start_addr) {
688 ring->head_addr += ring->size;
689 }
690 ring->head_addr -= 4 * sizeof(u32);
691 }
692
693 if (ring->head_addr < ring->start_addr ||
694 ring->head_addr >= ring->start_addr + ring->size) {
695 DRM_ERROR("bad ring head address: 0x%08x\n",
696 ring->head_addr);
697 mach64_dump_ring_info(dev_priv);
698 mach64_do_engine_reset(dev_priv);
699 return;
700 }
701
702 ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32);
703
704 if (!gui_active && ring->head != ring->tail) {
705 mach64_ring_resume(dev_priv, ring);
706 }
707 }
708 }
709
710 static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv)
711 {
712 DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
713 __FUNCTION__,
714 dev_priv->ring.head_addr, dev_priv->ring.head,
715 dev_priv->ring.tail, dev_priv->ring.space);
716
717 /* restore previous SRC_CNTL to disable busmastering */
718 mach64_do_wait_for_fifo(dev_priv, 1);
719 MACH64_WRITE(MACH64_SRC_CNTL, 0);
720
721 /* disable busmastering but keep the block 1 registers enabled */
722 mach64_do_wait_for_idle(dev_priv);
723 MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL)
724 | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN);
725
726 dev_priv->ring_running = 0;
727 }
728
729 static __inline__ void
730 mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv)
731 {
732 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
733
734 DRM_DEBUG("%s\n", __FUNCTION__);
735
736 mach64_ring_tick(dev_priv, ring);
737
738 ring->space = (ring->head - ring->tail) * sizeof(u32);
739 if (ring->space <= 0) {
740 ring->space += ring->size;
741 }
742 }
743
744 /* ================================================================
745 * DMA descriptor ring macros
746 */
747
748 #define RING_LOCALS \
749 int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring
750
751 #define RING_WRITE_OFS _ring_write
752
753 #define BEGIN_RING( n ) \
754 do { \
755 if ( MACH64_VERBOSE ) { \
756 DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
757 (n), __FUNCTION__ ); \
758 } \
759 if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
760 int ret; \
761 if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \
762 DRM_ERROR( "wait_ring failed, resetting engine\n"); \
763 mach64_dump_engine_info( dev_priv ); \
764 mach64_do_engine_reset( dev_priv ); \
765 return ret; \
766 } \
767 } \
768 dev_priv->ring.space -= (n) * sizeof(u32); \
769 _ring = (u32 *) dev_priv->ring.start; \
770 _ring_tail = _ring_write = dev_priv->ring.tail; \
771 _ring_mask = dev_priv->ring.tail_mask; \
772 } while (0)
773
774 #define OUT_RING( x ) \
775 do { \
776 if ( MACH64_VERBOSE ) { \
777 DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
778 (unsigned int)(x), _ring_write ); \
779 } \
780 _ring[_ring_write++] = cpu_to_le32( x ); \
781 _ring_write &= _ring_mask; \
782 } while (0)
783
784 #define ADVANCE_RING() \
785 do { \
786 if ( MACH64_VERBOSE ) { \
787 DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
788 _ring_write, _ring_tail ); \
789 } \
790 DRM_MEMORYBARRIER(); \
791 mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \
792 DRM_MEMORYBARRIER(); \
793 dev_priv->ring.tail = _ring_write; \
794 mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \
795 } while (0)
796
797 /* ================================================================
798 * DMA macros
799 */
800
801 #define DMALOCALS \
802 drm_mach64_freelist_t *_entry = NULL; \
803 drm_buf_t *_buf = NULL; \
804 u32 *_buf_wptr; int _outcount
805
806 #define GETBUFPTR( __buf ) \
807 ((dev_priv->is_pci) ? \
808 ((u32 *)(__buf)->address) : \
809 ((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset)))
810
811 #define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address)
812
813 #define GETRINGOFFSET() (_entry->ring_ofs)
814
815 static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t *
816 dev_priv,
817 drm_mach64_freelist_t **
818 entry, drm_buf_t * buf)
819 {
820 struct list_head *ptr;
821 #if MACH64_EXTRA_CHECKING
822 if (list_empty(&dev_priv->pending)) {
823 DRM_ERROR("Empty pending list in %s\n", __FUNCTION__);
824 return DRM_ERR(EINVAL);
825 }
826 #endif
827 ptr = dev_priv->pending.prev;
828 *entry = list_entry(ptr, drm_mach64_freelist_t, list);
829 while ((*entry)->buf != buf) {
830 if (ptr == &dev_priv->pending) {
831 return DRM_ERR(EFAULT);
832 }
833 ptr = ptr->prev;
834 *entry = list_entry(ptr, drm_mach64_freelist_t, list);
835 }
836 return 0;
837 }
838
839 #define DMASETPTR( _p ) \
840 do { \
841 _buf = (_p); \
842 _outcount = 0; \
843 _buf_wptr = GETBUFPTR( _buf ); \
844 } while(0)
845
846 /* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */
847 #define DMAGETPTR( filp, dev_priv, n ) \
848 do { \
849 if ( MACH64_VERBOSE ) { \
850 DRM_INFO( "DMAGETPTR( %d ) in %s\n", \
851 n, __FUNCTION__ ); \
852 } \
853 _buf = mach64_freelist_get( dev_priv ); \
854 if (_buf == NULL) { \
855 DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", \
856 __FUNCTION__ ); \
857 return DRM_ERR(EAGAIN); \
858 } \
859 if (_buf->pending) { \
860 DRM_ERROR("%s: pending buf in DMAGETPTR\n", \
861 __FUNCTION__ ); \
862 return DRM_ERR(EFAULT); \
863 } \
864 _buf->filp = filp; \
865 _outcount = 0; \
866 \
867 _buf_wptr = GETBUFPTR( _buf ); \
868 } while (0)
869
870 #define DMAOUTREG( reg, val ) \
871 do { \
872 if ( MACH64_VERBOSE ) { \
873 DRM_INFO( " DMAOUTREG( 0x%x = 0x%08x )\n", \
874 reg, val ); \
875 } \
876 _buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg)); \
877 _buf_wptr[_outcount++] = cpu_to_le32((val)); \
878 _buf->used += 8; \
879 } while (0)
880
881 #define DMAADVANCE( dev_priv, _discard ) \
882 do { \
883 struct list_head *ptr; \
884 RING_LOCALS; \
885 \
886 if ( MACH64_VERBOSE ) { \
887 DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \
888 } \
889 \
890 if (_buf->used <= 0) { \
891 DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n", \
892 __FUNCTION__, _buf->idx ); \
893 return DRM_ERR(EFAULT); \
894 } \
895 if (_buf->pending) { \
896 /* This is a resued buffer, so we need to find it in the pending list */ \
897 int ret; \
898 if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \
899 DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \
900 __FUNCTION__, _buf->idx ); \
901 return ret; \
902 } \
903 if (_entry->discard) { \
904 DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \
905 __FUNCTION__, _buf->idx ); \
906 return DRM_ERR(EFAULT); \
907 } \
908 } else { \
909 if (list_empty(&dev_priv->placeholders)) { \
910 DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n", \
911 __FUNCTION__ ); \
912 return DRM_ERR(EFAULT); \
913 } \
914 ptr = dev_priv->placeholders.next; \
915 list_del(ptr); \
916 _entry = list_entry(ptr, drm_mach64_freelist_t, list); \
917 _buf->pending = 1; \
918 _entry->buf = _buf; \
919 list_add_tail(ptr, &dev_priv->pending); \
920 } \
921 _entry->discard = (_discard); \
922 ADD_BUF_TO_RING( dev_priv ); \
923 } while (0)
924
925 #define DMADISCARDBUF() \
926 do { \
927 if (_entry == NULL) { \
928 int ret; \
929 if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \
930 DRM_ERROR( "%s: couldn't find pending buf %d\n", \
931 __FUNCTION__, _buf->idx ); \
932 return ret; \
933 } \
934 } \
935 _entry->discard = 1; \
936 } while(0)
937
938 #define ADD_BUF_TO_RING( dev_priv ) \
939 do { \
940 int bytes, pages, remainder; \
941 u32 address, page; \
942 int i; \
943 \
944 bytes = _buf->used; \
945 address = GETBUFADDR( _buf ); \
946 \
947 pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \
948 \
949 BEGIN_RING( pages * 4 ); \
950 \
951 for ( i = 0 ; i < pages-1 ; i++ ) { \
952 page = address + i * MACH64_DMA_CHUNKSIZE; \
953 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \
954 OUT_RING( page ); \
955 OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \
956 OUT_RING( 0 ); \
957 } \
958 \
959 /* generate the final descriptor for any remaining commands in this buffer */ \
960 page = address + i * MACH64_DMA_CHUNKSIZE; \
961 remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \
962 \
963 /* Save dword offset of last descriptor for this buffer. \
964 * This is needed to check for completion of the buffer in freelist_get \
965 */ \
966 _entry->ring_ofs = RING_WRITE_OFS; \
967 \
968 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \
969 OUT_RING( page ); \
970 OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \
971 OUT_RING( 0 ); \
972 \
973 ADVANCE_RING(); \
974 } while(0)
975
976 #define DMAADVANCEHOSTDATA( dev_priv ) \
977 do { \
978 struct list_head *ptr; \
979 RING_LOCALS; \
980 \
981 if ( MACH64_VERBOSE ) { \
982 DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \
983 } \
984 \
985 if (_buf->used <= 0) { \
986 DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n", \
987 __FUNCTION__, _buf->idx ); \
988 return DRM_ERR(EFAULT); \
989 } \
990 if (list_empty(&dev_priv->placeholders)) { \
991 DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n", \
992 __FUNCTION__ ); \
993 return DRM_ERR(EFAULT); \
994 } \
995 \
996 ptr = dev_priv->placeholders.next; \
997 list_del(ptr); \
998 _entry = list_entry(ptr, drm_mach64_freelist_t, list); \
999 _entry->buf = _buf; \
1000 _entry->buf->pending = 1; \
1001 list_add_tail(ptr, &dev_priv->pending); \
1002 _entry->discard = 1; \
1003 ADD_HOSTDATA_BUF_TO_RING( dev_priv ); \
1004 } while (0)
1005
1006 #define ADD_HOSTDATA_BUF_TO_RING( dev_priv ) \
1007 do { \
1008 int bytes, pages, remainder; \
1009 u32 address, page; \
1010 int i; \
1011 \
1012 bytes = _buf->used - MACH64_HOSTDATA_BLIT_OFFSET; \
1013 pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; \
1014 address = GETBUFADDR( _buf ); \
1015 \
1016 BEGIN_RING( 4 + pages * 4 ); \
1017 \
1018 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); \
1019 OUT_RING( address ); \
1020 OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); \
1021 OUT_RING( 0 ); \
1022 \
1023 address += MACH64_HOSTDATA_BLIT_OFFSET; \
1024 \
1025 for ( i = 0 ; i < pages-1 ; i++ ) { \
1026 page = address + i * MACH64_DMA_CHUNKSIZE; \
1027 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \
1028 OUT_RING( page ); \
1029 OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); \
1030 OUT_RING( 0 ); \
1031 } \
1032 \
1033 /* generate the final descriptor for any remaining commands in this buffer */ \
1034 page = address + i * MACH64_DMA_CHUNKSIZE; \
1035 remainder = bytes - i * MACH64_DMA_CHUNKSIZE; \
1036 \
1037 /* Save dword offset of last descriptor for this buffer. \
1038 * This is needed to check for completion of the buffer in freelist_get \
1039 */ \
1040 _entry->ring_ofs = RING_WRITE_OFS; \
1041 \
1042 OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \
1043 OUT_RING( page ); \
1044 OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); \
1045 OUT_RING( 0 ); \
1046 \
1047 ADVANCE_RING(); \
1048 } while(0)
1049
1050 #endif /* __MACH64_DRV_H__ */
Cache object: cd9be7c991cff8d4c855e0e76894deab
|