]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- |
2 | * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com | |
3 | * | |
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | |
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | |
6 | * All Rights Reserved. | |
7 | * | |
8 | * Permission is hereby granted, free of charge, to any person obtaining a | |
9 | * copy of this software and associated documentation files (the "Software"), | |
10 | * to deal in the Software without restriction, including without limitation | |
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
12 | * and/or sell copies of the Software, and to permit persons to whom the | |
13 | * Software is furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice (including the next | |
16 | * paragraph) shall be included in all copies or substantial portions of the | |
17 | * Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
22 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
25 | * OTHER DEALINGS IN THE SOFTWARE. | |
26 | * | |
27 | * Authors: | |
28 | * Jeff Hartmann <jhartmann@valinux.com> | |
29 | * Keith Whitwell <keith@tungstengraphics.com> | |
30 | * | |
31 | * Rewritten by: | |
32 | * Gareth Hughes <gareth@valinux.com> | |
33 | */ | |
34 | ||
35 | #include "drmP.h" | |
36 | #include "drm.h" | |
37 | #include "mga_drm.h" | |
38 | #include "mga_drv.h" | |
39 | ||
40 | /* ================================================================ | |
41 | * DMA hardware state programming functions | |
42 | */ | |
43 | ||
f2b2cb79 NK |
44 | static void mga_emit_clip_rect(drm_mga_private_t *dev_priv, |
45 | struct drm_clip_rect *box) | |
1da177e4 LT |
46 | { |
47 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
48 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
49 | unsigned int pitch = dev_priv->front_pitch; | |
50 | DMA_LOCALS; | |
51 | ||
b5e89ed5 | 52 | BEGIN_DMA(2); |
1da177e4 LT |
53 | |
54 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). | |
55 | */ | |
e29971f9 | 56 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { |
6795c985 DA |
57 | DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, |
58 | MGA_LEN + MGA_EXEC, 0x80000000, | |
59 | MGA_DWGCTL, ctx->dwgctl, | |
60 | MGA_LEN + MGA_EXEC, 0x80000000); | |
1da177e4 | 61 | } |
6795c985 DA |
62 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
63 | MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, | |
b5e89ed5 | 64 | MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch); |
1da177e4 LT |
65 | |
66 | ADVANCE_DMA(); | |
67 | } | |
68 | ||
f2b2cb79 | 69 | static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv) |
1da177e4 LT |
70 | { |
71 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
72 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
73 | DMA_LOCALS; | |
74 | ||
b5e89ed5 | 75 | BEGIN_DMA(3); |
1da177e4 | 76 | |
b5e89ed5 DA |
77 | DMA_BLOCK(MGA_DSTORG, ctx->dstorg, |
78 | MGA_MACCESS, ctx->maccess, | |
79 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 | 80 | |
b5e89ed5 DA |
81 | DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, |
82 | MGA_FOGCOL, ctx->fogcolor, | |
83 | MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); | |
1da177e4 | 84 | |
b5e89ed5 DA |
85 | DMA_BLOCK(MGA_FCOL, ctx->fcol, |
86 | MGA_DMAPAD, 0x00000000, | |
87 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | |
1da177e4 LT |
88 | |
89 | ADVANCE_DMA(); | |
90 | } | |
91 | ||
f2b2cb79 | 92 | static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv) |
1da177e4 LT |
93 | { |
94 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
95 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
96 | DMA_LOCALS; | |
97 | ||
b5e89ed5 | 98 | BEGIN_DMA(4); |
1da177e4 | 99 | |
b5e89ed5 DA |
100 | DMA_BLOCK(MGA_DSTORG, ctx->dstorg, |
101 | MGA_MACCESS, ctx->maccess, | |
102 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 | 103 | |
b5e89ed5 DA |
104 | DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, |
105 | MGA_FOGCOL, ctx->fogcolor, | |
106 | MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); | |
1da177e4 | 107 | |
b5e89ed5 DA |
108 | DMA_BLOCK(MGA_WFLAG1, ctx->wflag, |
109 | MGA_TDUALSTAGE0, ctx->tdualstage0, | |
110 | MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol); | |
1da177e4 | 111 | |
b5e89ed5 DA |
112 | DMA_BLOCK(MGA_STENCIL, ctx->stencil, |
113 | MGA_STENCILCTL, ctx->stencilctl, | |
114 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | |
1da177e4 LT |
115 | |
116 | ADVANCE_DMA(); | |
117 | } | |
118 | ||
f2b2cb79 | 119 | static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv) |
1da177e4 LT |
120 | { |
121 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
122 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; | |
123 | DMA_LOCALS; | |
124 | ||
b5e89ed5 | 125 | BEGIN_DMA(4); |
1da177e4 | 126 | |
b5e89ed5 DA |
127 | DMA_BLOCK(MGA_TEXCTL2, tex->texctl2, |
128 | MGA_TEXCTL, tex->texctl, | |
129 | MGA_TEXFILTER, tex->texfilter, | |
130 | MGA_TEXBORDERCOL, tex->texbordercol); | |
1da177e4 | 131 | |
b5e89ed5 DA |
132 | DMA_BLOCK(MGA_TEXORG, tex->texorg, |
133 | MGA_TEXORG1, tex->texorg1, | |
134 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | |
1da177e4 | 135 | |
b5e89ed5 DA |
136 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, |
137 | MGA_TEXWIDTH, tex->texwidth, | |
138 | MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth); | |
1da177e4 | 139 | |
b5e89ed5 DA |
140 | DMA_BLOCK(MGA_WR34, tex->texheight, |
141 | MGA_TEXTRANS, 0x0000ffff, | |
142 | MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000); | |
1da177e4 LT |
143 | |
144 | ADVANCE_DMA(); | |
145 | } | |
146 | ||
f2b2cb79 | 147 | static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv) |
1da177e4 LT |
148 | { |
149 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
150 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; | |
151 | DMA_LOCALS; | |
152 | ||
bc5f4523 DA |
153 | /* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ |
154 | /* tex->texctl, tex->texctl2); */ | |
1da177e4 | 155 | |
b5e89ed5 | 156 | BEGIN_DMA(6); |
1da177e4 | 157 | |
b5e89ed5 DA |
158 | DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, |
159 | MGA_TEXCTL, tex->texctl, | |
160 | MGA_TEXFILTER, tex->texfilter, | |
161 | MGA_TEXBORDERCOL, tex->texbordercol); | |
1da177e4 | 162 | |
b5e89ed5 DA |
163 | DMA_BLOCK(MGA_TEXORG, tex->texorg, |
164 | MGA_TEXORG1, tex->texorg1, | |
165 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | |
1da177e4 | 166 | |
b5e89ed5 DA |
167 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, |
168 | MGA_TEXWIDTH, tex->texwidth, | |
169 | MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); | |
1da177e4 | 170 | |
b5e89ed5 DA |
171 | DMA_BLOCK(MGA_WR57, 0x00000000, |
172 | MGA_WR53, 0x00000000, | |
173 | MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC); | |
1da177e4 | 174 | |
b5e89ed5 DA |
175 | DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC, |
176 | MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, | |
177 | MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, | |
178 | MGA_DMAPAD, 0x00000000); | |
1da177e4 | 179 | |
b5e89ed5 DA |
180 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
181 | MGA_DMAPAD, 0x00000000, | |
182 | MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff); | |
1da177e4 LT |
183 | |
184 | ADVANCE_DMA(); | |
185 | } | |
186 | ||
f2b2cb79 | 187 | static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv) |
1da177e4 LT |
188 | { |
189 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
190 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; | |
191 | DMA_LOCALS; | |
192 | ||
bc5f4523 DA |
193 | /* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ |
194 | /* tex->texctl, tex->texctl2); */ | |
1da177e4 | 195 | |
b5e89ed5 | 196 | BEGIN_DMA(5); |
1da177e4 | 197 | |
b5e89ed5 DA |
198 | DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 | |
199 | MGA_MAP1_ENABLE | | |
200 | MGA_G400_TC2_MAGIC), | |
201 | MGA_TEXCTL, tex->texctl, | |
202 | MGA_TEXFILTER, tex->texfilter, | |
203 | MGA_TEXBORDERCOL, tex->texbordercol); | |
1da177e4 | 204 | |
b5e89ed5 DA |
205 | DMA_BLOCK(MGA_TEXORG, tex->texorg, |
206 | MGA_TEXORG1, tex->texorg1, | |
207 | MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); | |
1da177e4 | 208 | |
b5e89ed5 DA |
209 | DMA_BLOCK(MGA_TEXORG4, tex->texorg4, |
210 | MGA_TEXWIDTH, tex->texwidth, | |
211 | MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); | |
1da177e4 | 212 | |
b5e89ed5 DA |
213 | DMA_BLOCK(MGA_WR57, 0x00000000, |
214 | MGA_WR53, 0x00000000, | |
215 | MGA_WR61, 0x00000000, | |
216 | MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC); | |
1da177e4 | 217 | |
b5e89ed5 DA |
218 | DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, |
219 | MGA_TEXTRANS, 0x0000ffff, | |
220 | MGA_TEXTRANSHIGH, 0x0000ffff, | |
221 | MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC); | |
1da177e4 LT |
222 | |
223 | ADVANCE_DMA(); | |
224 | } | |
225 | ||
f2b2cb79 | 226 | static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv) |
1da177e4 LT |
227 | { |
228 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
229 | unsigned int pipe = sarea_priv->warp_pipe; | |
230 | DMA_LOCALS; | |
231 | ||
b5e89ed5 | 232 | BEGIN_DMA(3); |
1da177e4 | 233 | |
b5e89ed5 DA |
234 | DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND, |
235 | MGA_WVRTXSZ, 0x00000007, | |
236 | MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000); | |
1da177e4 | 237 | |
b5e89ed5 DA |
238 | DMA_BLOCK(MGA_WR25, 0x00000100, |
239 | MGA_WR34, 0x00000000, | |
240 | MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff); | |
1da177e4 | 241 | |
fd589a8f | 242 | /* Padding required due to hardware bug. |
1da177e4 | 243 | */ |
6795c985 DA |
244 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
245 | MGA_DMAPAD, 0xffffffff, | |
246 | MGA_DMAPAD, 0xffffffff, | |
247 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | | |
248 | MGA_WMODE_START | dev_priv->wagp_enable)); | |
1da177e4 LT |
249 | |
250 | ADVANCE_DMA(); | |
251 | } | |
252 | ||
f2b2cb79 | 253 | static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv) |
1da177e4 LT |
254 | { |
255 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
256 | unsigned int pipe = sarea_priv->warp_pipe; | |
257 | DMA_LOCALS; | |
258 | ||
bc5f4523 | 259 | /* printk("mga_g400_emit_pipe %x\n", pipe); */ |
1da177e4 | 260 | |
b5e89ed5 | 261 | BEGIN_DMA(10); |
1da177e4 | 262 | |
b5e89ed5 DA |
263 | DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND, |
264 | MGA_DMAPAD, 0x00000000, | |
265 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | |
1da177e4 | 266 | |
b5e89ed5 DA |
267 | if (pipe & MGA_T2) { |
268 | DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09, | |
269 | MGA_DMAPAD, 0x00000000, | |
270 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | |
1da177e4 | 271 | |
b5e89ed5 DA |
272 | DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, |
273 | MGA_WACCEPTSEQ, 0x00000000, | |
274 | MGA_WACCEPTSEQ, 0x00000000, | |
275 | MGA_WACCEPTSEQ, 0x1e000000); | |
1da177e4 | 276 | } else { |
b5e89ed5 | 277 | if (dev_priv->warp_pipe & MGA_T2) { |
1da177e4 | 278 | /* Flush the WARP pipe */ |
b5e89ed5 DA |
279 | DMA_BLOCK(MGA_YDST, 0x00000000, |
280 | MGA_FXLEFT, 0x00000000, | |
281 | MGA_FXRIGHT, 0x00000001, | |
282 | MGA_DWGCTL, MGA_DWGCTL_FLUSH); | |
283 | ||
284 | DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001, | |
285 | MGA_DWGSYNC, 0x00007000, | |
286 | MGA_TEXCTL2, MGA_G400_TC2_MAGIC, | |
287 | MGA_LEN + MGA_EXEC, 0x00000000); | |
288 | ||
289 | DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX | | |
290 | MGA_G400_TC2_MAGIC), | |
291 | MGA_LEN + MGA_EXEC, 0x00000000, | |
292 | MGA_TEXCTL2, MGA_G400_TC2_MAGIC, | |
293 | MGA_DMAPAD, 0x00000000); | |
1da177e4 LT |
294 | } |
295 | ||
b5e89ed5 DA |
296 | DMA_BLOCK(MGA_WVRTXSZ, 0x00001807, |
297 | MGA_DMAPAD, 0x00000000, | |
298 | MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); | |
1da177e4 | 299 | |
b5e89ed5 DA |
300 | DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, |
301 | MGA_WACCEPTSEQ, 0x00000000, | |
302 | MGA_WACCEPTSEQ, 0x00000000, | |
303 | MGA_WACCEPTSEQ, 0x18000000); | |
1da177e4 LT |
304 | } |
305 | ||
b5e89ed5 DA |
306 | DMA_BLOCK(MGA_WFLAG, 0x00000000, |
307 | MGA_WFLAG1, 0x00000000, | |
308 | MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000); | |
1da177e4 | 309 | |
b5e89ed5 DA |
310 | DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */ |
311 | MGA_WR57, 0x00000000, /* tex0 */ | |
312 | MGA_WR53, 0x00000000, /* tex1 */ | |
313 | MGA_WR61, 0x00000000); /* tex1 */ | |
1da177e4 | 314 | |
b5e89ed5 DA |
315 | DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ |
316 | MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ | |
317 | MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ | |
318 | MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */ | |
1da177e4 | 319 | |
fd589a8f | 320 | /* Padding required due to hardware bug */ |
6795c985 DA |
321 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
322 | MGA_DMAPAD, 0xffffffff, | |
323 | MGA_DMAPAD, 0xffffffff, | |
324 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | | |
325 | MGA_WMODE_START | dev_priv->wagp_enable)); | |
1da177e4 LT |
326 | |
327 | ADVANCE_DMA(); | |
328 | } | |
329 | ||
f2b2cb79 | 330 | static void mga_g200_emit_state(drm_mga_private_t *dev_priv) |
1da177e4 LT |
331 | { |
332 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
333 | unsigned int dirty = sarea_priv->dirty; | |
334 | ||
b5e89ed5 DA |
335 | if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { |
336 | mga_g200_emit_pipe(dev_priv); | |
1da177e4 LT |
337 | dev_priv->warp_pipe = sarea_priv->warp_pipe; |
338 | } | |
339 | ||
b5e89ed5 DA |
340 | if (dirty & MGA_UPLOAD_CONTEXT) { |
341 | mga_g200_emit_context(dev_priv); | |
1da177e4 LT |
342 | sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; |
343 | } | |
344 | ||
b5e89ed5 DA |
345 | if (dirty & MGA_UPLOAD_TEX0) { |
346 | mga_g200_emit_tex0(dev_priv); | |
1da177e4 LT |
347 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; |
348 | } | |
349 | } | |
350 | ||
f2b2cb79 | 351 | static void mga_g400_emit_state(drm_mga_private_t *dev_priv) |
1da177e4 LT |
352 | { |
353 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
354 | unsigned int dirty = sarea_priv->dirty; | |
355 | int multitex = sarea_priv->warp_pipe & MGA_T2; | |
356 | ||
b5e89ed5 DA |
357 | if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { |
358 | mga_g400_emit_pipe(dev_priv); | |
1da177e4 LT |
359 | dev_priv->warp_pipe = sarea_priv->warp_pipe; |
360 | } | |
361 | ||
b5e89ed5 DA |
362 | if (dirty & MGA_UPLOAD_CONTEXT) { |
363 | mga_g400_emit_context(dev_priv); | |
1da177e4 LT |
364 | sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; |
365 | } | |
366 | ||
b5e89ed5 DA |
367 | if (dirty & MGA_UPLOAD_TEX0) { |
368 | mga_g400_emit_tex0(dev_priv); | |
1da177e4 LT |
369 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; |
370 | } | |
371 | ||
b5e89ed5 DA |
372 | if ((dirty & MGA_UPLOAD_TEX1) && multitex) { |
373 | mga_g400_emit_tex1(dev_priv); | |
1da177e4 LT |
374 | sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; |
375 | } | |
376 | } | |
377 | ||
1da177e4 LT |
378 | /* ================================================================ |
379 | * SAREA state verification | |
380 | */ | |
381 | ||
382 | /* Disallow all write destinations except the front and backbuffer. | |
383 | */ | |
f2b2cb79 | 384 | static int mga_verify_context(drm_mga_private_t *dev_priv) |
1da177e4 LT |
385 | { |
386 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
387 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
388 | ||
b5e89ed5 DA |
389 | if (ctx->dstorg != dev_priv->front_offset && |
390 | ctx->dstorg != dev_priv->back_offset) { | |
391 | DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n", | |
392 | ctx->dstorg, dev_priv->front_offset, | |
393 | dev_priv->back_offset); | |
1da177e4 | 394 | ctx->dstorg = 0; |
20caafa6 | 395 | return -EINVAL; |
1da177e4 LT |
396 | } |
397 | ||
398 | return 0; | |
399 | } | |
400 | ||
401 | /* Disallow texture reads from PCI space. | |
402 | */ | |
f2b2cb79 | 403 | static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit) |
1da177e4 LT |
404 | { |
405 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
406 | drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; | |
407 | unsigned int org; | |
408 | ||
409 | org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); | |
410 | ||
b5e89ed5 DA |
411 | if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { |
412 | DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); | |
1da177e4 | 413 | tex->texorg = 0; |
20caafa6 | 414 | return -EINVAL; |
1da177e4 LT |
415 | } |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
f2b2cb79 | 420 | static int mga_verify_state(drm_mga_private_t *dev_priv) |
1da177e4 LT |
421 | { |
422 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
423 | unsigned int dirty = sarea_priv->dirty; | |
424 | int ret = 0; | |
425 | ||
b5e89ed5 | 426 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
427 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
428 | ||
b5e89ed5 DA |
429 | if (dirty & MGA_UPLOAD_CONTEXT) |
430 | ret |= mga_verify_context(dev_priv); | |
1da177e4 | 431 | |
b5e89ed5 DA |
432 | if (dirty & MGA_UPLOAD_TEX0) |
433 | ret |= mga_verify_tex(dev_priv, 0); | |
1da177e4 | 434 | |
6795c985 DA |
435 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { |
436 | if (dirty & MGA_UPLOAD_TEX1) | |
437 | ret |= mga_verify_tex(dev_priv, 1); | |
1da177e4 | 438 | |
b5e89ed5 DA |
439 | if (dirty & MGA_UPLOAD_PIPE) |
440 | ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES); | |
1da177e4 | 441 | } else { |
b5e89ed5 DA |
442 | if (dirty & MGA_UPLOAD_PIPE) |
443 | ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES); | |
1da177e4 LT |
444 | } |
445 | ||
b5e89ed5 | 446 | return (ret == 0); |
1da177e4 LT |
447 | } |
448 | ||
f2b2cb79 | 449 | static int mga_verify_iload(drm_mga_private_t *dev_priv, |
b5e89ed5 | 450 | unsigned int dstorg, unsigned int length) |
1da177e4 | 451 | { |
b5e89ed5 DA |
452 | if (dstorg < dev_priv->texture_offset || |
453 | dstorg + length > (dev_priv->texture_offset + | |
454 | dev_priv->texture_size)) { | |
455 | DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); | |
20caafa6 | 456 | return -EINVAL; |
1da177e4 LT |
457 | } |
458 | ||
b5e89ed5 DA |
459 | if (length & MGA_ILOAD_MASK) { |
460 | DRM_ERROR("*** bad iload length: 0x%x\n", | |
461 | length & MGA_ILOAD_MASK); | |
20caafa6 | 462 | return -EINVAL; |
1da177e4 LT |
463 | } |
464 | ||
465 | return 0; | |
466 | } | |
467 | ||
f2b2cb79 | 468 | static int mga_verify_blit(drm_mga_private_t *dev_priv, |
b5e89ed5 | 469 | unsigned int srcorg, unsigned int dstorg) |
1da177e4 | 470 | { |
b5e89ed5 DA |
471 | if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || |
472 | (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { | |
473 | DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); | |
20caafa6 | 474 | return -EINVAL; |
1da177e4 LT |
475 | } |
476 | return 0; | |
477 | } | |
478 | ||
1da177e4 LT |
479 | /* ================================================================ |
480 | * | |
481 | */ | |
482 | ||
f2b2cb79 | 483 | static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear) |
1da177e4 LT |
484 | { |
485 | drm_mga_private_t *dev_priv = dev->dev_private; | |
486 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
487 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
eddca551 | 488 | struct drm_clip_rect *pbox = sarea_priv->boxes; |
1da177e4 LT |
489 | int nbox = sarea_priv->nbox; |
490 | int i; | |
491 | DMA_LOCALS; | |
b5e89ed5 | 492 | DRM_DEBUG("\n"); |
1da177e4 | 493 | |
b5e89ed5 | 494 | BEGIN_DMA(1); |
1da177e4 | 495 | |
b5e89ed5 DA |
496 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
497 | MGA_DMAPAD, 0x00000000, | |
498 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | |
1da177e4 LT |
499 | |
500 | ADVANCE_DMA(); | |
501 | ||
b5e89ed5 | 502 | for (i = 0; i < nbox; i++) { |
eddca551 | 503 | struct drm_clip_rect *box = &pbox[i]; |
1da177e4 LT |
504 | u32 height = box->y2 - box->y1; |
505 | ||
b5e89ed5 DA |
506 | DRM_DEBUG(" from=%d,%d to=%d,%d\n", |
507 | box->x1, box->y1, box->x2, box->y2); | |
1da177e4 | 508 | |
b5e89ed5 DA |
509 | if (clear->flags & MGA_FRONT) { |
510 | BEGIN_DMA(2); | |
1da177e4 | 511 | |
b5e89ed5 DA |
512 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
513 | MGA_PLNWT, clear->color_mask, | |
514 | MGA_YDSTLEN, (box->y1 << 16) | height, | |
515 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | |
1da177e4 | 516 | |
b5e89ed5 DA |
517 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
518 | MGA_FCOL, clear->clear_color, | |
519 | MGA_DSTORG, dev_priv->front_offset, | |
520 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | |
1da177e4 LT |
521 | |
522 | ADVANCE_DMA(); | |
523 | } | |
524 | ||
b5e89ed5 DA |
525 | if (clear->flags & MGA_BACK) { |
526 | BEGIN_DMA(2); | |
1da177e4 | 527 | |
b5e89ed5 DA |
528 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
529 | MGA_PLNWT, clear->color_mask, | |
530 | MGA_YDSTLEN, (box->y1 << 16) | height, | |
531 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | |
1da177e4 | 532 | |
b5e89ed5 DA |
533 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
534 | MGA_FCOL, clear->clear_color, | |
535 | MGA_DSTORG, dev_priv->back_offset, | |
536 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | |
1da177e4 LT |
537 | |
538 | ADVANCE_DMA(); | |
539 | } | |
540 | ||
b5e89ed5 DA |
541 | if (clear->flags & MGA_DEPTH) { |
542 | BEGIN_DMA(2); | |
1da177e4 | 543 | |
b5e89ed5 DA |
544 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
545 | MGA_PLNWT, clear->depth_mask, | |
546 | MGA_YDSTLEN, (box->y1 << 16) | height, | |
547 | MGA_FXBNDRY, (box->x2 << 16) | box->x1); | |
1da177e4 | 548 | |
b5e89ed5 DA |
549 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
550 | MGA_FCOL, clear->clear_depth, | |
551 | MGA_DSTORG, dev_priv->depth_offset, | |
552 | MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); | |
1da177e4 LT |
553 | |
554 | ADVANCE_DMA(); | |
555 | } | |
556 | ||
557 | } | |
558 | ||
b5e89ed5 | 559 | BEGIN_DMA(1); |
1da177e4 LT |
560 | |
561 | /* Force reset of DWGCTL */ | |
b5e89ed5 DA |
562 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
563 | MGA_DMAPAD, 0x00000000, | |
564 | MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 LT |
565 | |
566 | ADVANCE_DMA(); | |
567 | ||
568 | FLUSH_DMA(); | |
569 | } | |
570 | ||
f2b2cb79 | 571 | static void mga_dma_dispatch_swap(struct drm_device *dev) |
1da177e4 LT |
572 | { |
573 | drm_mga_private_t *dev_priv = dev->dev_private; | |
574 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
575 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
eddca551 | 576 | struct drm_clip_rect *pbox = sarea_priv->boxes; |
1da177e4 LT |
577 | int nbox = sarea_priv->nbox; |
578 | int i; | |
579 | DMA_LOCALS; | |
b5e89ed5 | 580 | DRM_DEBUG("\n"); |
1da177e4 LT |
581 | |
582 | sarea_priv->last_frame.head = dev_priv->prim.tail; | |
583 | sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; | |
584 | ||
b5e89ed5 | 585 | BEGIN_DMA(4 + nbox); |
1da177e4 | 586 | |
b5e89ed5 DA |
587 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
588 | MGA_DMAPAD, 0x00000000, | |
589 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | |
1da177e4 | 590 | |
b5e89ed5 DA |
591 | DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset, |
592 | MGA_MACCESS, dev_priv->maccess, | |
593 | MGA_SRCORG, dev_priv->back_offset, | |
594 | MGA_AR5, dev_priv->front_pitch); | |
1da177e4 | 595 | |
b5e89ed5 DA |
596 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
597 | MGA_DMAPAD, 0x00000000, | |
598 | MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY); | |
1da177e4 | 599 | |
b5e89ed5 | 600 | for (i = 0; i < nbox; i++) { |
eddca551 | 601 | struct drm_clip_rect *box = &pbox[i]; |
1da177e4 LT |
602 | u32 height = box->y2 - box->y1; |
603 | u32 start = box->y1 * dev_priv->front_pitch; | |
604 | ||
b5e89ed5 DA |
605 | DRM_DEBUG(" from=%d,%d to=%d,%d\n", |
606 | box->x1, box->y1, box->x2, box->y2); | |
1da177e4 | 607 | |
b5e89ed5 DA |
608 | DMA_BLOCK(MGA_AR0, start + box->x2 - 1, |
609 | MGA_AR3, start + box->x1, | |
610 | MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, | |
611 | MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height); | |
1da177e4 LT |
612 | } |
613 | ||
b5e89ed5 DA |
614 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
615 | MGA_PLNWT, ctx->plnwt, | |
616 | MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 LT |
617 | |
618 | ADVANCE_DMA(); | |
619 | ||
620 | FLUSH_DMA(); | |
621 | ||
3e684eae | 622 | DRM_DEBUG("... done.\n"); |
1da177e4 LT |
623 | } |
624 | ||
f2b2cb79 | 625 | static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf) |
1da177e4 LT |
626 | { |
627 | drm_mga_private_t *dev_priv = dev->dev_private; | |
628 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | |
629 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
630 | u32 address = (u32) buf->bus_address; | |
631 | u32 length = (u32) buf->used; | |
632 | int i = 0; | |
633 | DMA_LOCALS; | |
3e684eae | 634 | DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); |
1da177e4 | 635 | |
b5e89ed5 | 636 | if (buf->used) { |
1da177e4 LT |
637 | buf_priv->dispatched = 1; |
638 | ||
b5e89ed5 | 639 | MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); |
1da177e4 LT |
640 | |
641 | do { | |
b5e89ed5 DA |
642 | if (i < sarea_priv->nbox) { |
643 | mga_emit_clip_rect(dev_priv, | |
644 | &sarea_priv->boxes[i]); | |
1da177e4 LT |
645 | } |
646 | ||
b5e89ed5 | 647 | BEGIN_DMA(1); |
1da177e4 | 648 | |
6795c985 DA |
649 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
650 | MGA_DMAPAD, 0x00000000, | |
651 | MGA_SECADDRESS, (address | | |
652 | MGA_DMA_VERTEX), | |
653 | MGA_SECEND, ((address + length) | | |
654 | dev_priv->dma_access)); | |
1da177e4 LT |
655 | |
656 | ADVANCE_DMA(); | |
b5e89ed5 | 657 | } while (++i < sarea_priv->nbox); |
1da177e4 LT |
658 | } |
659 | ||
b5e89ed5 DA |
660 | if (buf_priv->discard) { |
661 | AGE_BUFFER(buf_priv); | |
1da177e4 LT |
662 | buf->pending = 0; |
663 | buf->used = 0; | |
664 | buf_priv->dispatched = 0; | |
665 | ||
b5e89ed5 | 666 | mga_freelist_put(dev, buf); |
1da177e4 LT |
667 | } |
668 | ||
669 | FLUSH_DMA(); | |
670 | } | |
671 | ||
f2b2cb79 | 672 | static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf, |
b5e89ed5 | 673 | unsigned int start, unsigned int end) |
1da177e4 LT |
674 | { |
675 | drm_mga_private_t *dev_priv = dev->dev_private; | |
676 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | |
677 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
678 | u32 address = (u32) buf->bus_address; | |
679 | int i = 0; | |
680 | DMA_LOCALS; | |
3e684eae | 681 | DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end); |
1da177e4 | 682 | |
b5e89ed5 | 683 | if (start != end) { |
1da177e4 LT |
684 | buf_priv->dispatched = 1; |
685 | ||
b5e89ed5 | 686 | MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); |
1da177e4 LT |
687 | |
688 | do { | |
b5e89ed5 DA |
689 | if (i < sarea_priv->nbox) { |
690 | mga_emit_clip_rect(dev_priv, | |
691 | &sarea_priv->boxes[i]); | |
1da177e4 LT |
692 | } |
693 | ||
b5e89ed5 | 694 | BEGIN_DMA(1); |
1da177e4 | 695 | |
6795c985 DA |
696 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
697 | MGA_DMAPAD, 0x00000000, | |
698 | MGA_SETUPADDRESS, address + start, | |
699 | MGA_SETUPEND, ((address + end) | | |
700 | dev_priv->dma_access)); | |
1da177e4 LT |
701 | |
702 | ADVANCE_DMA(); | |
b5e89ed5 | 703 | } while (++i < sarea_priv->nbox); |
1da177e4 LT |
704 | } |
705 | ||
b5e89ed5 DA |
706 | if (buf_priv->discard) { |
707 | AGE_BUFFER(buf_priv); | |
1da177e4 LT |
708 | buf->pending = 0; |
709 | buf->used = 0; | |
710 | buf_priv->dispatched = 0; | |
711 | ||
b5e89ed5 | 712 | mga_freelist_put(dev, buf); |
1da177e4 LT |
713 | } |
714 | ||
715 | FLUSH_DMA(); | |
716 | } | |
717 | ||
718 | /* This copies a 64 byte aligned agp region to the frambuffer with a | |
719 | * standard blit, the ioctl needs to do checking. | |
720 | */ | |
f2b2cb79 | 721 | static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf, |
b5e89ed5 | 722 | unsigned int dstorg, unsigned int length) |
1da177e4 LT |
723 | { |
724 | drm_mga_private_t *dev_priv = dev->dev_private; | |
725 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | |
726 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; | |
b5e89ed5 DA |
727 | u32 srcorg = |
728 | buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; | |
1da177e4 LT |
729 | u32 y2; |
730 | DMA_LOCALS; | |
b5e89ed5 | 731 | DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); |
1da177e4 LT |
732 | |
733 | y2 = length / 64; | |
734 | ||
b5e89ed5 | 735 | BEGIN_DMA(5); |
1da177e4 | 736 | |
b5e89ed5 DA |
737 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
738 | MGA_DMAPAD, 0x00000000, | |
739 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | |
1da177e4 | 740 | |
b5e89ed5 DA |
741 | DMA_BLOCK(MGA_DSTORG, dstorg, |
742 | MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64); | |
1da177e4 | 743 | |
b5e89ed5 DA |
744 | DMA_BLOCK(MGA_PITCH, 64, |
745 | MGA_PLNWT, 0xffffffff, | |
746 | MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY); | |
1da177e4 | 747 | |
b5e89ed5 DA |
748 | DMA_BLOCK(MGA_AR0, 63, |
749 | MGA_AR3, 0, | |
750 | MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2); | |
1da177e4 | 751 | |
b5e89ed5 DA |
752 | DMA_BLOCK(MGA_PLNWT, ctx->plnwt, |
753 | MGA_SRCORG, dev_priv->front_offset, | |
754 | MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000); | |
1da177e4 LT |
755 | |
756 | ADVANCE_DMA(); | |
757 | ||
b5e89ed5 | 758 | AGE_BUFFER(buf_priv); |
1da177e4 LT |
759 | |
760 | buf->pending = 0; | |
761 | buf->used = 0; | |
762 | buf_priv->dispatched = 0; | |
763 | ||
b5e89ed5 | 764 | mga_freelist_put(dev, buf); |
1da177e4 LT |
765 | |
766 | FLUSH_DMA(); | |
767 | } | |
768 | ||
f2b2cb79 | 769 | static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit) |
1da177e4 LT |
770 | { |
771 | drm_mga_private_t *dev_priv = dev->dev_private; | |
772 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
773 | drm_mga_context_regs_t *ctx = &sarea_priv->context_state; | |
eddca551 | 774 | struct drm_clip_rect *pbox = sarea_priv->boxes; |
1da177e4 LT |
775 | int nbox = sarea_priv->nbox; |
776 | u32 scandir = 0, i; | |
777 | DMA_LOCALS; | |
b5e89ed5 | 778 | DRM_DEBUG("\n"); |
1da177e4 | 779 | |
b5e89ed5 | 780 | BEGIN_DMA(4 + nbox); |
1da177e4 | 781 | |
b5e89ed5 DA |
782 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
783 | MGA_DMAPAD, 0x00000000, | |
784 | MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); | |
1da177e4 | 785 | |
b5e89ed5 DA |
786 | DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY, |
787 | MGA_PLNWT, blit->planemask, | |
788 | MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg); | |
1da177e4 | 789 | |
b5e89ed5 DA |
790 | DMA_BLOCK(MGA_SGN, scandir, |
791 | MGA_MACCESS, dev_priv->maccess, | |
792 | MGA_AR5, blit->ydir * blit->src_pitch, | |
793 | MGA_PITCH, blit->dst_pitch); | |
1da177e4 | 794 | |
b5e89ed5 | 795 | for (i = 0; i < nbox; i++) { |
1da177e4 LT |
796 | int srcx = pbox[i].x1 + blit->delta_sx; |
797 | int srcy = pbox[i].y1 + blit->delta_sy; | |
798 | int dstx = pbox[i].x1 + blit->delta_dx; | |
799 | int dsty = pbox[i].y1 + blit->delta_dy; | |
800 | int h = pbox[i].y2 - pbox[i].y1; | |
801 | int w = pbox[i].x2 - pbox[i].x1 - 1; | |
802 | int start; | |
803 | ||
f2b2cb79 | 804 | if (blit->ydir == -1) |
1da177e4 | 805 | srcy = blit->height - srcy - 1; |
1da177e4 LT |
806 | |
807 | start = srcy * blit->src_pitch + srcx; | |
808 | ||
b5e89ed5 DA |
809 | DMA_BLOCK(MGA_AR0, start + w, |
810 | MGA_AR3, start, | |
811 | MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), | |
812 | MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); | |
1da177e4 LT |
813 | } |
814 | ||
815 | /* Do something to flush AGP? | |
816 | */ | |
817 | ||
818 | /* Force reset of DWGCTL */ | |
b5e89ed5 DA |
819 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
820 | MGA_PLNWT, ctx->plnwt, | |
821 | MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 LT |
822 | |
823 | ADVANCE_DMA(); | |
824 | } | |
825 | ||
1da177e4 LT |
826 | /* ================================================================ |
827 | * | |
828 | */ | |
829 | ||
c153f45f | 830 | static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 831 | { |
1da177e4 LT |
832 | drm_mga_private_t *dev_priv = dev->dev_private; |
833 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
c153f45f | 834 | drm_mga_clear_t *clear = data; |
1da177e4 | 835 | |
6c340eac | 836 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 837 | |
b5e89ed5 | 838 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
839 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
840 | ||
b5e89ed5 | 841 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 842 | |
c153f45f | 843 | mga_dma_dispatch_clear(dev, clear); |
1da177e4 LT |
844 | |
845 | /* Make sure we restore the 3D state next time. | |
846 | */ | |
847 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
848 | ||
849 | return 0; | |
850 | } | |
851 | ||
c153f45f | 852 | static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 853 | { |
1da177e4 LT |
854 | drm_mga_private_t *dev_priv = dev->dev_private; |
855 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
856 | ||
6c340eac | 857 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 858 | |
b5e89ed5 | 859 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
860 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
861 | ||
b5e89ed5 | 862 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 863 | |
b5e89ed5 | 864 | mga_dma_dispatch_swap(dev); |
1da177e4 LT |
865 | |
866 | /* Make sure we restore the 3D state next time. | |
867 | */ | |
868 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
869 | ||
870 | return 0; | |
871 | } | |
872 | ||
c153f45f | 873 | static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 874 | { |
1da177e4 | 875 | drm_mga_private_t *dev_priv = dev->dev_private; |
cdd55a29 | 876 | struct drm_device_dma *dma = dev->dma; |
056219e2 | 877 | struct drm_buf *buf; |
1da177e4 | 878 | drm_mga_buf_priv_t *buf_priv; |
c153f45f | 879 | drm_mga_vertex_t *vertex = data; |
1da177e4 | 880 | |
6c340eac | 881 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 882 | |
c153f45f | 883 | if (vertex->idx < 0 || vertex->idx > dma->buf_count) |
20caafa6 | 884 | return -EINVAL; |
c153f45f | 885 | buf = dma->buflist[vertex->idx]; |
1da177e4 LT |
886 | buf_priv = buf->dev_private; |
887 | ||
c153f45f EA |
888 | buf->used = vertex->used; |
889 | buf_priv->discard = vertex->discard; | |
1da177e4 | 890 | |
b5e89ed5 | 891 | if (!mga_verify_state(dev_priv)) { |
c153f45f | 892 | if (vertex->discard) { |
b5e89ed5 DA |
893 | if (buf_priv->dispatched == 1) |
894 | AGE_BUFFER(buf_priv); | |
1da177e4 | 895 | buf_priv->dispatched = 0; |
b5e89ed5 | 896 | mga_freelist_put(dev, buf); |
1da177e4 | 897 | } |
20caafa6 | 898 | return -EINVAL; |
1da177e4 LT |
899 | } |
900 | ||
b5e89ed5 | 901 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 902 | |
b5e89ed5 | 903 | mga_dma_dispatch_vertex(dev, buf); |
1da177e4 LT |
904 | |
905 | return 0; | |
906 | } | |
907 | ||
c153f45f | 908 | static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 909 | { |
1da177e4 | 910 | drm_mga_private_t *dev_priv = dev->dev_private; |
cdd55a29 | 911 | struct drm_device_dma *dma = dev->dma; |
056219e2 | 912 | struct drm_buf *buf; |
1da177e4 | 913 | drm_mga_buf_priv_t *buf_priv; |
c153f45f | 914 | drm_mga_indices_t *indices = data; |
1da177e4 | 915 | |
6c340eac | 916 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 917 | |
c153f45f | 918 | if (indices->idx < 0 || indices->idx > dma->buf_count) |
20caafa6 | 919 | return -EINVAL; |
1da177e4 | 920 | |
c153f45f | 921 | buf = dma->buflist[indices->idx]; |
1da177e4 LT |
922 | buf_priv = buf->dev_private; |
923 | ||
c153f45f | 924 | buf_priv->discard = indices->discard; |
1da177e4 | 925 | |
b5e89ed5 | 926 | if (!mga_verify_state(dev_priv)) { |
c153f45f | 927 | if (indices->discard) { |
b5e89ed5 DA |
928 | if (buf_priv->dispatched == 1) |
929 | AGE_BUFFER(buf_priv); | |
1da177e4 | 930 | buf_priv->dispatched = 0; |
b5e89ed5 | 931 | mga_freelist_put(dev, buf); |
1da177e4 | 932 | } |
20caafa6 | 933 | return -EINVAL; |
1da177e4 LT |
934 | } |
935 | ||
b5e89ed5 | 936 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 937 | |
c153f45f | 938 | mga_dma_dispatch_indices(dev, buf, indices->start, indices->end); |
1da177e4 LT |
939 | |
940 | return 0; | |
941 | } | |
942 | ||
c153f45f | 943 | static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 944 | { |
cdd55a29 | 945 | struct drm_device_dma *dma = dev->dma; |
1da177e4 | 946 | drm_mga_private_t *dev_priv = dev->dev_private; |
056219e2 | 947 | struct drm_buf *buf; |
1da177e4 | 948 | drm_mga_buf_priv_t *buf_priv; |
c153f45f | 949 | drm_mga_iload_t *iload = data; |
b5e89ed5 | 950 | DRM_DEBUG("\n"); |
1da177e4 | 951 | |
6c340eac | 952 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 953 | |
1da177e4 | 954 | #if 0 |
b5e89ed5 DA |
955 | if (mga_do_wait_for_idle(dev_priv) < 0) { |
956 | if (MGA_DMA_DEBUG) | |
3e684eae | 957 | DRM_INFO("-EBUSY\n"); |
20caafa6 | 958 | return -EBUSY; |
1da177e4 LT |
959 | } |
960 | #endif | |
c153f45f | 961 | if (iload->idx < 0 || iload->idx > dma->buf_count) |
20caafa6 | 962 | return -EINVAL; |
1da177e4 | 963 | |
c153f45f | 964 | buf = dma->buflist[iload->idx]; |
1da177e4 LT |
965 | buf_priv = buf->dev_private; |
966 | ||
c153f45f | 967 | if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) { |
b5e89ed5 | 968 | mga_freelist_put(dev, buf); |
20caafa6 | 969 | return -EINVAL; |
1da177e4 LT |
970 | } |
971 | ||
b5e89ed5 | 972 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 973 | |
c153f45f | 974 | mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length); |
1da177e4 LT |
975 | |
976 | /* Make sure we restore the 3D state next time. | |
977 | */ | |
978 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
979 | ||
980 | return 0; | |
981 | } | |
982 | ||
c153f45f | 983 | static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 984 | { |
1da177e4 LT |
985 | drm_mga_private_t *dev_priv = dev->dev_private; |
986 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
c153f45f | 987 | drm_mga_blit_t *blit = data; |
b5e89ed5 | 988 | DRM_DEBUG("\n"); |
1da177e4 | 989 | |
6c340eac | 990 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
1da177e4 | 991 | |
b5e89ed5 | 992 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
993 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
994 | ||
c153f45f | 995 | if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg)) |
20caafa6 | 996 | return -EINVAL; |
1da177e4 | 997 | |
b5e89ed5 | 998 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 999 | |
c153f45f | 1000 | mga_dma_dispatch_blit(dev, blit); |
1da177e4 LT |
1001 | |
1002 | /* Make sure we restore the 3D state next time. | |
1003 | */ | |
1004 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
1005 | ||
1006 | return 0; | |
1007 | } | |
1008 | ||
c153f45f | 1009 | static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1da177e4 | 1010 | { |
1da177e4 | 1011 | drm_mga_private_t *dev_priv = dev->dev_private; |
c153f45f | 1012 | drm_mga_getparam_t *param = data; |
1da177e4 LT |
1013 | int value; |
1014 | ||
b5e89ed5 | 1015 | if (!dev_priv) { |
3e684eae | 1016 | DRM_ERROR("called with no initialization\n"); |
20caafa6 | 1017 | return -EINVAL; |
1da177e4 LT |
1018 | } |
1019 | ||
b5e89ed5 | 1020 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); |
1da177e4 | 1021 | |
c153f45f | 1022 | switch (param->param) { |
1da177e4 | 1023 | case MGA_PARAM_IRQ_NR: |
9bfbd5cb | 1024 | value = drm_dev_to_irq(dev); |
1da177e4 | 1025 | break; |
6795c985 DA |
1026 | case MGA_PARAM_CARD_TYPE: |
1027 | value = dev_priv->chipset; | |
1028 | break; | |
1da177e4 | 1029 | default: |
20caafa6 | 1030 | return -EINVAL; |
1da177e4 LT |
1031 | } |
1032 | ||
c153f45f | 1033 | if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { |
b5e89ed5 | 1034 | DRM_ERROR("copy_to_user\n"); |
20caafa6 | 1035 | return -EFAULT; |
1da177e4 | 1036 | } |
b5e89ed5 | 1037 | |
1da177e4 LT |
1038 | return 0; |
1039 | } | |
1040 | ||
c153f45f | 1041 | static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) |
6795c985 | 1042 | { |
6795c985 | 1043 | drm_mga_private_t *dev_priv = dev->dev_private; |
c153f45f | 1044 | u32 *fence = data; |
6795c985 DA |
1045 | DMA_LOCALS; |
1046 | ||
1047 | if (!dev_priv) { | |
3e684eae | 1048 | DRM_ERROR("called with no initialization\n"); |
20caafa6 | 1049 | return -EINVAL; |
6795c985 DA |
1050 | } |
1051 | ||
1052 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | |
1053 | ||
c153f45f | 1054 | /* I would normal do this assignment in the declaration of fence, |
6795c985 DA |
1055 | * but dev_priv may be NULL. |
1056 | */ | |
1057 | ||
c153f45f | 1058 | *fence = dev_priv->next_fence_to_post; |
6795c985 DA |
1059 | dev_priv->next_fence_to_post++; |
1060 | ||
1061 | BEGIN_DMA(1); | |
1062 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | |
1063 | MGA_DMAPAD, 0x00000000, | |
b5e89ed5 | 1064 | MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); |
6795c985 DA |
1065 | ADVANCE_DMA(); |
1066 | ||
6795c985 DA |
1067 | return 0; |
1068 | } | |
1069 | ||
c153f45f EA |
1070 | static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file * |
1071 | file_priv) | |
6795c985 | 1072 | { |
6795c985 | 1073 | drm_mga_private_t *dev_priv = dev->dev_private; |
c153f45f | 1074 | u32 *fence = data; |
6795c985 DA |
1075 | |
1076 | if (!dev_priv) { | |
3e684eae | 1077 | DRM_ERROR("called with no initialization\n"); |
20caafa6 | 1078 | return -EINVAL; |
6795c985 DA |
1079 | } |
1080 | ||
6795c985 DA |
1081 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); |
1082 | ||
c153f45f | 1083 | mga_driver_fence_wait(dev, fence); |
6795c985 DA |
1084 | return 0; |
1085 | } | |
1086 | ||
c153f45f | 1087 | struct drm_ioctl_desc mga_ioctls[] = { |
1b2f1489 DA |
1088 | DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
1089 | DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH), | |
1090 | DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH), | |
1091 | DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH), | |
1092 | DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH), | |
1093 | DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH), | |
1094 | DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH), | |
1095 | DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH), | |
1096 | DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH), | |
1097 | DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH), | |
1098 | DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH), | |
1099 | DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), | |
1100 | DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | |
1da177e4 LT |
1101 | }; |
1102 | ||
1103 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); |