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