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