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