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 | ||
b5e89ed5 | 44 | static void mga_emit_clip_rect(drm_mga_private_t * dev_priv, |
eddca551 | 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 | ||
b5e89ed5 | 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 | ||
b5e89ed5 | 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 | ||
b5e89ed5 | 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 | ||
b5e89ed5 | 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 | ||
153 | /* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ | |
154 | /* tex->texctl, tex->texctl2); */ | |
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 | ||
b5e89ed5 | 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 | ||
193 | /* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ | |
194 | /* tex->texctl, tex->texctl2); */ | |
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 | ||
b5e89ed5 | 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 LT |
241 | |
242 | /* Padding required to to hardware bug. | |
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 | ||
b5e89ed5 | 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 | ||
259 | /* printk("mga_g400_emit_pipe %x\n", pipe); */ | |
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 LT |
319 | |
320 | /* Padding required to 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 | ||
b5e89ed5 | 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 | ||
b5e89ed5 | 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 | */ | |
b5e89ed5 | 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 LT |
394 | ctx->dstorg = 0; |
395 | return DRM_ERR(EINVAL); | |
396 | } | |
397 | ||
398 | return 0; | |
399 | } | |
400 | ||
401 | /* Disallow texture reads from PCI space. | |
402 | */ | |
b5e89ed5 | 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 LT |
413 | tex->texorg = 0; |
414 | return DRM_ERR(EINVAL); | |
415 | } | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
b5e89ed5 | 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 | ||
b5e89ed5 DA |
449 | static int mga_verify_iload(drm_mga_private_t * dev_priv, |
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); | |
1da177e4 LT |
456 | return DRM_ERR(EINVAL); |
457 | } | |
458 | ||
b5e89ed5 DA |
459 | if (length & MGA_ILOAD_MASK) { |
460 | DRM_ERROR("*** bad iload length: 0x%x\n", | |
461 | length & MGA_ILOAD_MASK); | |
1da177e4 LT |
462 | return DRM_ERR(EINVAL); |
463 | } | |
464 | ||
465 | return 0; | |
466 | } | |
467 | ||
b5e89ed5 DA |
468 | static int mga_verify_blit(drm_mga_private_t * dev_priv, |
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); | |
1da177e4 LT |
474 | return DRM_ERR(EINVAL); |
475 | } | |
476 | return 0; | |
477 | } | |
478 | ||
1da177e4 LT |
479 | /* ================================================================ |
480 | * | |
481 | */ | |
482 | ||
eddca551 | 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 | ||
eddca551 | 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 | ||
b5e89ed5 | 622 | DRM_DEBUG("%s... done.\n", __FUNCTION__); |
1da177e4 LT |
623 | } |
624 | ||
056219e2 | 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; | |
b5e89ed5 | 634 | DRM_DEBUG("vertex: 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 | ||
056219e2 | 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; | |
b5e89ed5 | 681 | DRM_DEBUG("indices: 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 | */ | |
056219e2 | 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 | ||
eddca551 | 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 | ||
b5e89ed5 | 804 | if (blit->ydir == -1) { |
1da177e4 LT |
805 | srcy = blit->height - srcy - 1; |
806 | } | |
807 | ||
808 | start = srcy * blit->src_pitch + srcx; | |
809 | ||
b5e89ed5 DA |
810 | DMA_BLOCK(MGA_AR0, start + w, |
811 | MGA_AR3, start, | |
812 | MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), | |
813 | MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); | |
1da177e4 LT |
814 | } |
815 | ||
816 | /* Do something to flush AGP? | |
817 | */ | |
818 | ||
819 | /* Force reset of DWGCTL */ | |
b5e89ed5 DA |
820 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
821 | MGA_PLNWT, ctx->plnwt, | |
822 | MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl); | |
1da177e4 LT |
823 | |
824 | ADVANCE_DMA(); | |
825 | } | |
826 | ||
1da177e4 LT |
827 | /* ================================================================ |
828 | * | |
829 | */ | |
830 | ||
b5e89ed5 | 831 | static int mga_dma_clear(DRM_IOCTL_ARGS) |
1da177e4 LT |
832 | { |
833 | DRM_DEVICE; | |
834 | drm_mga_private_t *dev_priv = dev->dev_private; | |
835 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
836 | drm_mga_clear_t clear; | |
837 | ||
b5e89ed5 | 838 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 839 | |
b5e89ed5 DA |
840 | DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data, |
841 | sizeof(clear)); | |
1da177e4 | 842 | |
b5e89ed5 | 843 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
844 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
845 | ||
b5e89ed5 | 846 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 847 | |
b5e89ed5 | 848 | mga_dma_dispatch_clear(dev, &clear); |
1da177e4 LT |
849 | |
850 | /* Make sure we restore the 3D state next time. | |
851 | */ | |
852 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
853 | ||
854 | return 0; | |
855 | } | |
856 | ||
b5e89ed5 | 857 | static int mga_dma_swap(DRM_IOCTL_ARGS) |
1da177e4 LT |
858 | { |
859 | DRM_DEVICE; | |
860 | drm_mga_private_t *dev_priv = dev->dev_private; | |
861 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
862 | ||
b5e89ed5 | 863 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 864 | |
b5e89ed5 | 865 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
866 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
867 | ||
b5e89ed5 | 868 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 869 | |
b5e89ed5 | 870 | mga_dma_dispatch_swap(dev); |
1da177e4 LT |
871 | |
872 | /* Make sure we restore the 3D state next time. | |
873 | */ | |
874 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
875 | ||
876 | return 0; | |
877 | } | |
878 | ||
b5e89ed5 | 879 | static int mga_dma_vertex(DRM_IOCTL_ARGS) |
1da177e4 LT |
880 | { |
881 | DRM_DEVICE; | |
882 | drm_mga_private_t *dev_priv = dev->dev_private; | |
883 | drm_device_dma_t *dma = dev->dma; | |
056219e2 | 884 | struct drm_buf *buf; |
1da177e4 LT |
885 | drm_mga_buf_priv_t *buf_priv; |
886 | drm_mga_vertex_t vertex; | |
887 | ||
b5e89ed5 | 888 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 889 | |
b5e89ed5 DA |
890 | DRM_COPY_FROM_USER_IOCTL(vertex, |
891 | (drm_mga_vertex_t __user *) data, | |
892 | sizeof(vertex)); | |
1da177e4 | 893 | |
b5e89ed5 DA |
894 | if (vertex.idx < 0 || vertex.idx > dma->buf_count) |
895 | return DRM_ERR(EINVAL); | |
1da177e4 LT |
896 | buf = dma->buflist[vertex.idx]; |
897 | buf_priv = buf->dev_private; | |
898 | ||
899 | buf->used = vertex.used; | |
900 | buf_priv->discard = vertex.discard; | |
901 | ||
b5e89ed5 DA |
902 | if (!mga_verify_state(dev_priv)) { |
903 | if (vertex.discard) { | |
904 | if (buf_priv->dispatched == 1) | |
905 | AGE_BUFFER(buf_priv); | |
1da177e4 | 906 | buf_priv->dispatched = 0; |
b5e89ed5 | 907 | mga_freelist_put(dev, buf); |
1da177e4 LT |
908 | } |
909 | return DRM_ERR(EINVAL); | |
910 | } | |
911 | ||
b5e89ed5 | 912 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 913 | |
b5e89ed5 | 914 | mga_dma_dispatch_vertex(dev, buf); |
1da177e4 LT |
915 | |
916 | return 0; | |
917 | } | |
918 | ||
b5e89ed5 | 919 | static int mga_dma_indices(DRM_IOCTL_ARGS) |
1da177e4 LT |
920 | { |
921 | DRM_DEVICE; | |
922 | drm_mga_private_t *dev_priv = dev->dev_private; | |
923 | drm_device_dma_t *dma = dev->dma; | |
056219e2 | 924 | struct drm_buf *buf; |
1da177e4 LT |
925 | drm_mga_buf_priv_t *buf_priv; |
926 | drm_mga_indices_t indices; | |
927 | ||
b5e89ed5 | 928 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 929 | |
b5e89ed5 DA |
930 | DRM_COPY_FROM_USER_IOCTL(indices, |
931 | (drm_mga_indices_t __user *) data, | |
932 | sizeof(indices)); | |
1da177e4 | 933 | |
b5e89ed5 DA |
934 | if (indices.idx < 0 || indices.idx > dma->buf_count) |
935 | return DRM_ERR(EINVAL); | |
1da177e4 LT |
936 | |
937 | buf = dma->buflist[indices.idx]; | |
938 | buf_priv = buf->dev_private; | |
939 | ||
940 | buf_priv->discard = indices.discard; | |
941 | ||
b5e89ed5 DA |
942 | if (!mga_verify_state(dev_priv)) { |
943 | if (indices.discard) { | |
944 | if (buf_priv->dispatched == 1) | |
945 | AGE_BUFFER(buf_priv); | |
1da177e4 | 946 | buf_priv->dispatched = 0; |
b5e89ed5 | 947 | mga_freelist_put(dev, buf); |
1da177e4 LT |
948 | } |
949 | return DRM_ERR(EINVAL); | |
950 | } | |
951 | ||
b5e89ed5 | 952 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 953 | |
b5e89ed5 | 954 | mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); |
1da177e4 LT |
955 | |
956 | return 0; | |
957 | } | |
958 | ||
b5e89ed5 | 959 | static int mga_dma_iload(DRM_IOCTL_ARGS) |
1da177e4 LT |
960 | { |
961 | DRM_DEVICE; | |
962 | drm_device_dma_t *dma = dev->dma; | |
963 | drm_mga_private_t *dev_priv = dev->dev_private; | |
056219e2 | 964 | struct drm_buf *buf; |
1da177e4 LT |
965 | drm_mga_buf_priv_t *buf_priv; |
966 | drm_mga_iload_t iload; | |
b5e89ed5 | 967 | DRM_DEBUG("\n"); |
1da177e4 | 968 | |
b5e89ed5 | 969 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 970 | |
b5e89ed5 DA |
971 | DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data, |
972 | sizeof(iload)); | |
1da177e4 LT |
973 | |
974 | #if 0 | |
b5e89ed5 DA |
975 | if (mga_do_wait_for_idle(dev_priv) < 0) { |
976 | if (MGA_DMA_DEBUG) | |
977 | DRM_INFO("%s: -EBUSY\n", __FUNCTION__); | |
1da177e4 LT |
978 | return DRM_ERR(EBUSY); |
979 | } | |
980 | #endif | |
b5e89ed5 DA |
981 | if (iload.idx < 0 || iload.idx > dma->buf_count) |
982 | return DRM_ERR(EINVAL); | |
1da177e4 LT |
983 | |
984 | buf = dma->buflist[iload.idx]; | |
985 | buf_priv = buf->dev_private; | |
986 | ||
b5e89ed5 DA |
987 | if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) { |
988 | mga_freelist_put(dev, buf); | |
1da177e4 LT |
989 | return DRM_ERR(EINVAL); |
990 | } | |
991 | ||
b5e89ed5 | 992 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 993 | |
b5e89ed5 | 994 | mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length); |
1da177e4 LT |
995 | |
996 | /* Make sure we restore the 3D state next time. | |
997 | */ | |
998 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
999 | ||
1000 | return 0; | |
1001 | } | |
1002 | ||
b5e89ed5 | 1003 | static int mga_dma_blit(DRM_IOCTL_ARGS) |
1da177e4 LT |
1004 | { |
1005 | DRM_DEVICE; | |
1006 | drm_mga_private_t *dev_priv = dev->dev_private; | |
1007 | drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
1008 | drm_mga_blit_t blit; | |
b5e89ed5 | 1009 | DRM_DEBUG("\n"); |
1da177e4 | 1010 | |
b5e89ed5 | 1011 | LOCK_TEST_WITH_RETURN(dev, filp); |
1da177e4 | 1012 | |
b5e89ed5 DA |
1013 | DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data, |
1014 | sizeof(blit)); | |
1da177e4 | 1015 | |
b5e89ed5 | 1016 | if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) |
1da177e4 LT |
1017 | sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; |
1018 | ||
b5e89ed5 | 1019 | if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg)) |
1da177e4 LT |
1020 | return DRM_ERR(EINVAL); |
1021 | ||
b5e89ed5 | 1022 | WRAP_TEST_WITH_RETURN(dev_priv); |
1da177e4 | 1023 | |
b5e89ed5 | 1024 | mga_dma_dispatch_blit(dev, &blit); |
1da177e4 LT |
1025 | |
1026 | /* Make sure we restore the 3D state next time. | |
1027 | */ | |
1028 | dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; | |
1029 | ||
1030 | return 0; | |
1031 | } | |
1032 | ||
b5e89ed5 | 1033 | static int mga_getparam(DRM_IOCTL_ARGS) |
1da177e4 LT |
1034 | { |
1035 | DRM_DEVICE; | |
1036 | drm_mga_private_t *dev_priv = dev->dev_private; | |
1037 | drm_mga_getparam_t param; | |
1038 | int value; | |
1039 | ||
b5e89ed5 DA |
1040 | if (!dev_priv) { |
1041 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | |
1da177e4 LT |
1042 | return DRM_ERR(EINVAL); |
1043 | } | |
1044 | ||
b5e89ed5 DA |
1045 | DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data, |
1046 | sizeof(param)); | |
1da177e4 | 1047 | |
b5e89ed5 | 1048 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); |
1da177e4 | 1049 | |
b5e89ed5 | 1050 | switch (param.param) { |
1da177e4 LT |
1051 | case MGA_PARAM_IRQ_NR: |
1052 | value = dev->irq; | |
1053 | break; | |
6795c985 DA |
1054 | case MGA_PARAM_CARD_TYPE: |
1055 | value = dev_priv->chipset; | |
1056 | break; | |
1da177e4 LT |
1057 | default: |
1058 | return DRM_ERR(EINVAL); | |
1059 | } | |
1060 | ||
b5e89ed5 DA |
1061 | if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { |
1062 | DRM_ERROR("copy_to_user\n"); | |
1da177e4 LT |
1063 | return DRM_ERR(EFAULT); |
1064 | } | |
b5e89ed5 | 1065 | |
1da177e4 LT |
1066 | return 0; |
1067 | } | |
1068 | ||
6795c985 DA |
1069 | static int mga_set_fence(DRM_IOCTL_ARGS) |
1070 | { | |
1071 | DRM_DEVICE; | |
1072 | drm_mga_private_t *dev_priv = dev->dev_private; | |
1073 | u32 temp; | |
1074 | DMA_LOCALS; | |
1075 | ||
1076 | if (!dev_priv) { | |
1077 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | |
1078 | return DRM_ERR(EINVAL); | |
1079 | } | |
1080 | ||
1081 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | |
1082 | ||
1083 | /* I would normal do this assignment in the declaration of temp, | |
1084 | * but dev_priv may be NULL. | |
1085 | */ | |
1086 | ||
1087 | temp = dev_priv->next_fence_to_post; | |
1088 | dev_priv->next_fence_to_post++; | |
1089 | ||
1090 | BEGIN_DMA(1); | |
1091 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | |
1092 | MGA_DMAPAD, 0x00000000, | |
b5e89ed5 | 1093 | MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); |
6795c985 DA |
1094 | ADVANCE_DMA(); |
1095 | ||
b5e89ed5 | 1096 | if (DRM_COPY_TO_USER((u32 __user *) data, &temp, sizeof(u32))) { |
6795c985 DA |
1097 | DRM_ERROR("copy_to_user\n"); |
1098 | return DRM_ERR(EFAULT); | |
1099 | } | |
1100 | ||
1101 | return 0; | |
1102 | } | |
1103 | ||
1104 | static int mga_wait_fence(DRM_IOCTL_ARGS) | |
1105 | { | |
1106 | DRM_DEVICE; | |
1107 | drm_mga_private_t *dev_priv = dev->dev_private; | |
1108 | u32 fence; | |
1109 | ||
1110 | if (!dev_priv) { | |
1111 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | |
1112 | return DRM_ERR(EINVAL); | |
1113 | } | |
1114 | ||
1115 | DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); | |
1116 | ||
1117 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | |
1118 | ||
b5e89ed5 | 1119 | mga_driver_fence_wait(dev, &fence); |
6795c985 | 1120 | |
b5e89ed5 | 1121 | if (DRM_COPY_TO_USER((u32 __user *) data, &fence, sizeof(u32))) { |
6795c985 DA |
1122 | DRM_ERROR("copy_to_user\n"); |
1123 | return DRM_ERR(EFAULT); | |
1124 | } | |
1125 | ||
1126 | return 0; | |
1127 | } | |
1128 | ||
1da177e4 | 1129 | drm_ioctl_desc_t mga_ioctls[] = { |
a7a2cc31 DA |
1130 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1131 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH}, | |
1132 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH}, | |
1133 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH}, | |
1134 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH}, | |
1135 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH}, | |
1136 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH}, | |
1137 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH}, | |
1138 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH}, | |
1139 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH}, | |
1140 | [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH}, | |
1141 | [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH}, | |
1142 | [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
1da177e4 LT |
1143 | }; |
1144 | ||
1145 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); |