OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm-4.0/] [mga_state.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* 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
 * PRECISION INSIGHT 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 OTHER
25
 * DEALINGS IN THE SOFTWARE.
26
 *
27
 * Authors: Jeff Hartmann <jhartmann@valinux.com>
28
 *          Keith Whitwell <keithw@valinux.com>
29
 *
30
 */
31
 
32
#define __NO_VERSION__
33
#include "drmP.h"
34
#include "mga_drv.h"
35
#include "drm.h"
36
 
37
/* If you change the functions to set state, PLEASE
38
 * change these values
39
 */
40
 
41
#define MGAEMITCLIP_SIZE        10
42
#define MGAEMITCTX_SIZE         20
43
#define MGAG200EMITTEX_SIZE     20
44
#define MGAG400EMITTEX0_SIZE    30
45
#define MGAG400EMITTEX1_SIZE    25
46
#define MGAG400EMITPIPE_SIZE    50
47
#define MGAG200EMITPIPE_SIZE    15
48
 
49
#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
50
                        MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \
51
                        MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)
52
 
53
static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
54
                            drm_clip_rect_t * box)
55
{
56
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
57
        unsigned int *regs = sarea_priv->ContextState;
58
        PRIMLOCALS;
59
 
60
        /* This takes 10 dwords */
61
        PRIMGETPTR(dev_priv);
62
 
63
        /* Force reset of dwgctl on G400 (eliminates clip disable bit) */
64
        if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
65
#if 0
66
                PRIMOUTREG(MGAREG_DMAPAD, 0);
67
                PRIMOUTREG(MGAREG_DWGSYNC, 0);
68
                PRIMOUTREG(MGAREG_DWGSYNC, 0);
69
                PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
70
#else
71
                PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
72
                PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
73
                PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
74
                PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
75
#endif
76
        }
77
        PRIMOUTREG(MGAREG_DMAPAD, 0);
78
        PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
79
        PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
80
        PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);
81
 
82
        PRIMADVANCE(dev_priv);
83
}
84
 
85
static void mgaEmitContext(drm_mga_private_t * dev_priv)
86
{
87
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
88
        unsigned int *regs = sarea_priv->ContextState;
89
        PRIMLOCALS;
90
 
91
        /* This takes a max of 20 dwords */
92
        PRIMGETPTR(dev_priv);
93
 
94
        PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]);
95
        PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]);
96
        PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]);
97
        PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
98
 
99
        PRIMOUTREG(MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL]);
100
        PRIMOUTREG(MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR]);
101
        PRIMOUTREG(MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG]);
102
        PRIMOUTREG(MGAREG_ZORG, dev_priv->depthOffset); /* invarient */
103
 
104
        if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
105
                PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]);
106
                PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]);
107
                PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]);
108
                PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
109
 
110
                PRIMOUTREG(MGAREG_STENCIL, regs[MGA_CTXREG_STENCIL]);
111
                PRIMOUTREG(MGAREG_STENCILCTL, regs[MGA_CTXREG_STENCILCTL]);
112
                PRIMOUTREG(MGAREG_DMAPAD, 0);
113
                PRIMOUTREG(MGAREG_DMAPAD, 0);
114
        } else {
115
                PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
116
                PRIMOUTREG(MGAREG_DMAPAD, 0);
117
                PRIMOUTREG(MGAREG_DMAPAD, 0);
118
                PRIMOUTREG(MGAREG_DMAPAD, 0);
119
        }
120
 
121
        PRIMADVANCE(dev_priv);
122
}
123
 
124
static void mgaG200EmitTex(drm_mga_private_t * dev_priv)
125
{
126
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
127
        unsigned int *regs = sarea_priv->TexState[0];
128
        PRIMLOCALS;
129
 
130
        PRIMGETPTR(dev_priv);
131
 
132
        /* This takes 20 dwords */
133
 
134
        PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]);
135
        PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
136
        PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
137
        PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
138
 
139
        PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
140
        PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
141
        PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
142
        PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
143
 
144
        PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
145
        PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
146
        PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
147
        PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);
148
 
149
        PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
150
        PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
151
        PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
152
        PRIMOUTREG(MGAREG_DMAPAD, 0);
153
 
154
        PRIMADVANCE(dev_priv);
155
}
156
 
157
#define TMC_dualtex_enable              0x80
158
 
159
static void mgaG400EmitTex0(drm_mga_private_t * dev_priv)
160
{
161
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
162
        unsigned int *regs = sarea_priv->TexState[0];
163
        PRIMLOCALS;
164
 
165
        PRIMGETPTR(dev_priv);
166
 
167
        /* This takes 30 dwords */
168
 
169
        PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
170
        PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
171
        PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
172
        PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
173
 
174
        PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
175
        PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
176
        PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
177
        PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
178
 
179
        PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
180
        PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
181
        PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
182
        PRIMOUTREG(MGAREG_WR49, 0);
183
 
184
        PRIMOUTREG(MGAREG_WR57, 0);
185
        PRIMOUTREG(MGAREG_WR53, 0);
186
        PRIMOUTREG(MGAREG_WR61, 0);
187
        PRIMOUTREG(MGAREG_WR52, 0x40);
188
 
189
        PRIMOUTREG(MGAREG_WR60, 0x40);
190
        PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
191
        PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
192
        PRIMOUTREG(MGAREG_DMAPAD, 0);
193
 
194
        PRIMOUTREG(MGAREG_DMAPAD, 0);
195
        PRIMOUTREG(MGAREG_DMAPAD, 0);
196
        PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
197
        PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
198
 
199
        PRIMADVANCE(dev_priv);
200
}
201
 
202
#define TMC_map1_enable                 0x80000000
203
 
204
static void mgaG400EmitTex1(drm_mga_private_t * dev_priv)
205
{
206
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
207
        unsigned int *regs = sarea_priv->TexState[1];
208
        PRIMLOCALS;
209
 
210
        PRIMGETPTR(dev_priv);
211
 
212
        /* This takes 25 dwords */
213
 
214
        PRIMOUTREG(MGAREG_TEXCTL2,
215
                   regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
216
        PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
217
        PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
218
        PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
219
 
220
        PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
221
        PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
222
        PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
223
        PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
224
 
225
        PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
226
        PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
227
        PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
228
        PRIMOUTREG(MGAREG_WR49, 0);
229
 
230
        PRIMOUTREG(MGAREG_WR57, 0);
231
        PRIMOUTREG(MGAREG_WR53, 0);
232
        PRIMOUTREG(MGAREG_WR61, 0);
233
        PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);
234
 
235
        PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);
236
        PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
237
        PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
238
        PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
239
 
240
        PRIMADVANCE(dev_priv);
241
}
242
 
243
#define MAGIC_FPARAM_HEX_VALUE 0x46480000
244
/* This is the hex value of 12800.0f which is a magic value we must
245
 * set in wr56.
246
 */
247
 
248
static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
249
{
250
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
251
        unsigned int pipe = sarea_priv->WarpPipe;
252
        PRIMLOCALS;
253
 
254
        PRIMGETPTR(dev_priv);
255
 
256
        /* This takes 50 dwords */
257
 
258
        /* Establish vertex size.
259
         */
260
        PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
261
        PRIMOUTREG(MGAREG_DMAPAD, 0);
262
        PRIMOUTREG(MGAREG_DMAPAD, 0);
263
        PRIMOUTREG(MGAREG_DMAPAD, 0);
264
 
265
        if (pipe & MGA_T2) {
266
                PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
267
                PRIMOUTREG(MGAREG_DMAPAD, 0);
268
                PRIMOUTREG(MGAREG_DMAPAD, 0);
269
                PRIMOUTREG(MGAREG_DMAPAD, 0);
270
 
271
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
272
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
273
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
274
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
275
        } else {
276
                if (dev_priv->WarpPipe & MGA_T2) {
277
                        /* Flush the WARP pipe */
278
                        PRIMOUTREG(MGAREG_YDST, 0);
279
                        PRIMOUTREG(MGAREG_FXLEFT, 0);
280
                        PRIMOUTREG(MGAREG_FXRIGHT, 1);
281
                        PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
282
 
283
                        PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
284
                        PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
285
                        PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
286
                        PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
287
 
288
                        PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
289
                        PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
290
                        PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
291
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
292
                }
293
 
294
                PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
295
                PRIMOUTREG(MGAREG_DMAPAD, 0);
296
                PRIMOUTREG(MGAREG_DMAPAD, 0);
297
                PRIMOUTREG(MGAREG_DMAPAD, 0);
298
 
299
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
300
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
301
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
302
                PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
303
        }
304
 
305
        PRIMOUTREG(MGAREG_WFLAG, 0);
306
        PRIMOUTREG(MGAREG_WFLAG1, 0);
307
        PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
308
        PRIMOUTREG(MGAREG_DMAPAD, 0);
309
 
310
        PRIMOUTREG(MGAREG_WR49, 0);      /* Tex stage 0 */
311
        PRIMOUTREG(MGAREG_WR57, 0);      /* Tex stage 0 */
312
        PRIMOUTREG(MGAREG_WR53, 0);      /* Tex stage 1 */
313
        PRIMOUTREG(MGAREG_WR61, 0);      /* Tex stage 1 */
314
 
315
        PRIMOUTREG(MGAREG_WR54, 0x40);  /* Tex stage 0 : w */
316
        PRIMOUTREG(MGAREG_WR62, 0x40);  /* Tex stage 0 : h */
317
        PRIMOUTREG(MGAREG_WR52, 0x40);  /* Tex stage 1 : w */
318
        PRIMOUTREG(MGAREG_WR60, 0x40);  /* Tex stage 1 : h */
319
 
320
        /* Dma pading required due to hw bug */
321
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
322
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
323
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
324
        PRIMOUTREG(MGAREG_WIADDR2,
325
                   (u32) (dev_priv->WarpIndex[pipe].
326
                          phys_addr | WIA_wmode_start | WIA_wagp_agp));
327
        PRIMADVANCE(dev_priv);
328
}
329
 
330
static void mgaG200EmitPipe(drm_mga_private_t * dev_priv)
331
{
332
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
333
        unsigned int pipe = sarea_priv->WarpPipe;
334
        PRIMLOCALS;
335
 
336
        PRIMGETPTR(dev_priv);
337
 
338
        /* This takes 15 dwords */
339
 
340
        PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
341
        PRIMOUTREG(MGAREG_WVRTXSZ, 7);
342
        PRIMOUTREG(MGAREG_WFLAG, 0);
343
        PRIMOUTREG(MGAREG_WR24, 0);      /* tex w/h */
344
 
345
        PRIMOUTREG(MGAREG_WR25, 0x100);
346
        PRIMOUTREG(MGAREG_WR34, 0);      /* tex w/h */
347
        PRIMOUTREG(MGAREG_WR42, 0xFFFF);
348
        PRIMOUTREG(MGAREG_WR60, 0xFFFF);
349
 
350
        /* Dma pading required due to hw bug */
351
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
352
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
353
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
354
        PRIMOUTREG(MGAREG_WIADDR,
355
                   (u32) (dev_priv->WarpIndex[pipe].
356
                          phys_addr | WIA_wmode_start | WIA_wagp_agp));
357
 
358
        PRIMADVANCE( dev_priv );
359
}
360
 
361
static void mgaEmitState(drm_mga_private_t * dev_priv)
362
{
363
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
364
        unsigned int dirty = sarea_priv->dirty;
365
 
366
        if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
367
                int multitex = sarea_priv->WarpPipe & MGA_T2;
368
 
369
                if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
370
                        mgaG400EmitPipe(dev_priv);
371
                        dev_priv->WarpPipe = sarea_priv->WarpPipe;
372
                }
373
 
374
                if (dirty & MGA_UPLOAD_CTX) {
375
                        mgaEmitContext(dev_priv);
376
                        sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
377
                }
378
 
379
                if (dirty & MGA_UPLOAD_TEX0) {
380
                        mgaG400EmitTex0(dev_priv);
381
                        sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
382
                }
383
 
384
                if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
385
                        mgaG400EmitTex1(dev_priv);
386
                        sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
387
                }
388
        } else {
389
                if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
390
                        mgaG200EmitPipe(dev_priv);
391
                        dev_priv->WarpPipe = sarea_priv->WarpPipe;
392
                }
393
 
394
                if (dirty & MGA_UPLOAD_CTX) {
395
                        mgaEmitContext(dev_priv);
396
                        sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
397
                }
398
 
399
                if (dirty & MGA_UPLOAD_TEX0) {
400
                        mgaG200EmitTex(dev_priv);
401
                        sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
402
                }
403
        }
404
}
405
 
406
/* Disallow all write destinations except the front and backbuffer.
407
 */
408
static int mgaVerifyContext(drm_mga_private_t * dev_priv)
409
{
410
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
411
        unsigned int *regs = sarea_priv->ContextState;
412
 
413
        if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
414
            regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
415
                DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
416
                          regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
417
                          dev_priv->backOffset);
418
                regs[MGA_CTXREG_DSTORG] = 0;
419
                return -1;
420
        }
421
 
422
        return 0;
423
}
424
 
425
/* Disallow texture reads from PCI space.
426
 */
427
static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit)
428
{
429
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
430
 
431
        if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
432
                DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
433
                          sarea_priv->TexState[unit][MGA_TEXREG_ORG],
434
                          unit);
435
                sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
436
                return -1;
437
        }
438
 
439
        return 0;
440
}
441
 
442
static int mgaVerifyState(drm_mga_private_t * dev_priv)
443
{
444
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
445
        unsigned int dirty = sarea_priv->dirty;
446
        int rv = 0;
447
 
448
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
449
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
450
 
451
        if (dirty & MGA_UPLOAD_CTX)
452
                rv |= mgaVerifyContext(dev_priv);
453
 
454
        if (dirty & MGA_UPLOAD_TEX0)
455
                rv |= mgaVerifyTex(dev_priv, 0);
456
 
457
        if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
458
                if (dirty & MGA_UPLOAD_TEX1)
459
                        rv |= mgaVerifyTex(dev_priv, 1);
460
 
461
                if (dirty & MGA_UPLOAD_PIPE)
462
                        rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
463
        } else {
464
                if (dirty & MGA_UPLOAD_PIPE)
465
                        rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
466
        }
467
 
468
        return rv == 0;
469
}
470
 
471
static int mgaVerifyIload(drm_mga_private_t * dev_priv,
472
                          unsigned long bus_address,
473
                          unsigned int dstOrg, int length)
474
{
475
        if (dstOrg < dev_priv->textureOffset ||
476
            dstOrg + length >
477
            (dev_priv->textureOffset + dev_priv->textureSize)) {
478
                return -EINVAL;
479
        }
480
        if (length % 64) {
481
                return -EINVAL;
482
        }
483
        return 0;
484
}
485
 
486
/* This copies a 64 byte aligned agp region to the frambuffer
487
 * with a standard blit, the ioctl needs to do checking */
488
 
489
static void mga_dma_dispatch_tex_blit(drm_device_t * dev,
490
                                      unsigned long bus_address,
491
                                      int length, unsigned int destOrg)
492
{
493
        drm_mga_private_t *dev_priv = dev->dev_private;
494
        int use_agp = PDEA_pagpxfer_enable | 0x00000001;
495
        u16 y2;
496
        PRIMLOCALS;
497
 
498
        y2 = length / 64;
499
 
500
        PRIM_OVERFLOW(dev, dev_priv, 30);
501
 
502
        PRIMOUTREG(MGAREG_DSTORG, destOrg);
503
        PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
504
        PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
505
        PRIMOUTREG(MGAREG_AR5, 64);
506
 
507
        PRIMOUTREG(MGAREG_PITCH, 64);
508
        PRIMOUTREG(MGAREG_DMAPAD, 0);
509
        PRIMOUTREG(MGAREG_DMAPAD, 0);
510
        PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
511
 
512
        PRIMOUTREG(MGAREG_AR0, 63);
513
        PRIMOUTREG(MGAREG_AR3, 0);
514
        PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
515
        PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2);
516
 
517
        PRIMOUTREG(MGAREG_DMAPAD, 0);
518
        PRIMOUTREG(MGAREG_SRCORG, 0);
519
        PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
520
        PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
521
        PRIMADVANCE(dev_priv);
522
}
523
 
524
static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
525
{
526
        drm_mga_private_t *dev_priv = dev->dev_private;
527
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
528
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
529
        unsigned long address = (unsigned long) buf->bus_address;
530
        int length = buf->used;
531
        int use_agp = PDEA_pagpxfer_enable;
532
        int i = 0;
533
        PRIMLOCALS;
534
 
535
        if (buf->used) {
536
                /* WARNING: if you change any of the state functions verify
537
                 * these numbers (Overestimating this doesn't hurt).
538
                 */
539
                buf_priv->dispatched = 1;
540
                PRIM_OVERFLOW(dev, dev_priv,
541
                              (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
542
                mgaEmitState(dev_priv);
543
 
544
#if 0
545
                length = dev_priv->vertexsize * 3 * 4;
546
#endif
547
 
548
                do {
549
                        if (i < sarea_priv->nbox) {
550
                                mgaEmitClipRect(dev_priv,
551
                                                &sarea_priv->boxes[i]);
552
                        }
553
 
554
                        PRIMGETPTR(dev_priv);
555
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
556
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
557
                        PRIMOUTREG(MGAREG_SECADDRESS,
558
                                   ((u32) address) | TT_VERTEX);
559
                        PRIMOUTREG(MGAREG_SECEND,
560
                                   (((u32) (address + length)) | use_agp));
561
                        PRIMADVANCE(dev_priv);
562
                } while (++i < sarea_priv->nbox);
563
        }
564
        if (buf_priv->discard) {
565
                if (buf_priv->dispatched == 1)
566
                        AGEBUF(dev_priv, buf_priv);
567
                buf_priv->dispatched = 0;
568
                mga_freelist_put(dev, buf);
569
        }
570
 
571
 
572
}
573
 
574
 
575
static void mga_dma_dispatch_indices(drm_device_t * dev,
576
                                     drm_buf_t * buf,
577
                                     unsigned int start, unsigned int end)
578
{
579
        drm_mga_private_t *dev_priv = dev->dev_private;
580
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
581
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
582
        unsigned int address = (unsigned int) buf->bus_address;
583
        int use_agp = PDEA_pagpxfer_enable;
584
        int i = 0;
585
        PRIMLOCALS;
586
 
587
        if (start != end) {
588
                /* WARNING: if you change any of the state functions verify
589
                 * these numbers (Overestimating this doesn't hurt).
590
                 */
591
                buf_priv->dispatched = 1;
592
                PRIM_OVERFLOW(dev, dev_priv,
593
                              (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
594
                mgaEmitState(dev_priv);
595
 
596
                do {
597
                        if (i < sarea_priv->nbox) {
598
                                mgaEmitClipRect(dev_priv,
599
                                                &sarea_priv->boxes[i]);
600
                        }
601
 
602
                        PRIMGETPTR(dev_priv);
603
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
604
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
605
                        PRIMOUTREG(MGAREG_SETUPADDRESS,
606
                                   ((address + start) |
607
                                    SETADD_mode_vertlist));
608
                        PRIMOUTREG(MGAREG_SETUPEND,
609
                                   ((address + end) | use_agp));
610
/*                                 ((address + start + 12) | use_agp)); */
611
                        PRIMADVANCE(dev_priv);
612
                } while (++i < sarea_priv->nbox);
613
        }
614
        if (buf_priv->discard) {
615
                if (buf_priv->dispatched == 1)
616
                        AGEBUF(dev_priv, buf_priv);
617
                buf_priv->dispatched = 0;
618
                mga_freelist_put(dev, buf);
619
        }
620
}
621
 
622
 
623
static void mga_dma_dispatch_clear(drm_device_t * dev, int flags,
624
                                   unsigned int clear_color,
625
                                   unsigned int clear_zval,
626
                                   unsigned int clear_colormask,
627
                                   unsigned int clear_depthmask)
628
{
629
        drm_mga_private_t *dev_priv = dev->dev_private;
630
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
631
        unsigned int *regs = sarea_priv->ContextState;
632
        int nbox = sarea_priv->nbox;
633
        drm_clip_rect_t *pbox = sarea_priv->boxes;
634
        unsigned int cmd;
635
        int i;
636
        PRIMLOCALS;
637
 
638
        if (dev_priv->sgram)
639
                cmd = MGA_CLEAR_CMD | DC_atype_blk;
640
        else
641
                cmd = MGA_CLEAR_CMD | DC_atype_rstr;
642
 
643
        PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS);
644
 
645
        for (i = 0; i < nbox; i++) {
646
                unsigned int height = pbox[i].y2 - pbox[i].y1;
647
 
648
                if (flags & MGA_FRONT) {
649
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
650
                        PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
651
                        PRIMOUTREG(MGAREG_YDSTLEN,
652
                                   (pbox[i].y1 << 16) | height);
653
                        PRIMOUTREG(MGAREG_FXBNDRY,
654
                                   (pbox[i].x2 << 16) | pbox[i].x1);
655
 
656
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
657
                        PRIMOUTREG(MGAREG_FCOL, clear_color);
658
                        PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
659
                        PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
660
                }
661
 
662
                if (flags & MGA_BACK) {
663
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
664
                        PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
665
                        PRIMOUTREG(MGAREG_YDSTLEN,
666
                                   (pbox[i].y1 << 16) | height);
667
                        PRIMOUTREG(MGAREG_FXBNDRY,
668
                                   (pbox[i].x2 << 16) | pbox[i].x1);
669
 
670
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
671
                        PRIMOUTREG(MGAREG_FCOL, clear_color);
672
                        PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
673
                        PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
674
                }
675
 
676
                if (flags & MGA_DEPTH) {
677
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
678
                        PRIMOUTREG(MGAREG_PLNWT, clear_depthmask);
679
                        PRIMOUTREG(MGAREG_YDSTLEN,
680
                                   (pbox[i].y1 << 16) | height);
681
                        PRIMOUTREG(MGAREG_FXBNDRY,
682
                                   (pbox[i].x2 << 16) | pbox[i].x1);
683
 
684
                        PRIMOUTREG(MGAREG_DMAPAD, 0);
685
                        PRIMOUTREG(MGAREG_FCOL, clear_zval);
686
                        PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
687
                        PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
688
                }
689
        }
690
 
691
        /* Force reset of DWGCTL */
692
        PRIMOUTREG(MGAREG_DMAPAD, 0);
693
        PRIMOUTREG(MGAREG_DMAPAD, 0);
694
        PRIMOUTREG(MGAREG_DMAPAD, 0);
695
        PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
696
        PRIMADVANCE(dev_priv);
697
}
698
 
699
static void mga_dma_dispatch_swap(drm_device_t * dev)
700
{
701
        drm_mga_private_t *dev_priv = dev->dev_private;
702
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
703
        unsigned int *regs = sarea_priv->ContextState;
704
        int nbox = sarea_priv->nbox;
705
        drm_clip_rect_t *pbox = sarea_priv->boxes;
706
        int i;
707
        int pixel_stride = dev_priv->stride / dev_priv->cpp;
708
 
709
        PRIMLOCALS;
710
 
711
        PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
712
 
713
        PRIMOUTREG(MGAREG_DMAPAD, 0);
714
        PRIMOUTREG(MGAREG_DMAPAD, 0);
715
        PRIMOUTREG(MGAREG_DWGSYNC, 0x7100);
716
        PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
717
 
718
        PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
719
        PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
720
        PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
721
        PRIMOUTREG(MGAREG_AR5, pixel_stride);
722
 
723
        PRIMOUTREG(MGAREG_DMAPAD, 0);
724
        PRIMOUTREG(MGAREG_DMAPAD, 0);
725
        PRIMOUTREG(MGAREG_DMAPAD, 0);
726
        PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
727
 
728
        for (i = 0; i < nbox; i++) {
729
                unsigned int h = pbox[i].y2 - pbox[i].y1;
730
                unsigned int start = pbox[i].y1 * pixel_stride;
731
 
732
                PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
733
                PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
734
                PRIMOUTREG(MGAREG_FXBNDRY,
735
                           pbox[i].x1 | ((pbox[i].x2 - 1) << 16));
736
                PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC,
737
                           (pbox[i].y1 << 16) | h);
738
        }
739
 
740
        /* Force reset of DWGCTL */
741
        PRIMOUTREG(MGAREG_DMAPAD, 0);
742
        PRIMOUTREG(MGAREG_DMAPAD, 0);
743
        PRIMOUTREG(MGAREG_SRCORG, 0);
744
        PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
745
 
746
        PRIMADVANCE(dev_priv);
747
}
748
 
749
int mga_clear_bufs(struct inode *inode, struct file *filp,
750
                   unsigned int cmd, unsigned long arg)
751
{
752
        drm_file_t *priv = filp->private_data;
753
        drm_device_t *dev = priv->dev;
754
        drm_mga_private_t *dev_priv =
755
            (drm_mga_private_t *) dev->dev_private;
756
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
757
        drm_mga_clear_t clear;
758
 
759
        if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
760
                return -EFAULT;
761
 
762
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
763
                DRM_ERROR("mga_clear_bufs called without lock held\n");
764
                return -EINVAL;
765
        }
766
 
767
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
768
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
769
 
770
        /* Make sure we restore the 3D state next time.
771
         */
772
        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
773
        mga_dma_dispatch_clear(dev, clear.flags,
774
                               clear.clear_color,
775
                               clear.clear_depth,
776
                               clear.clear_color_mask,
777
                               clear.clear_depth_mask);
778
        PRIMUPDATE(dev_priv);
779
        mga_flush_write_combine();
780
        mga_dma_schedule(dev, 1);
781
        return 0;
782
}
783
 
784
int mga_swap_bufs(struct inode *inode, struct file *filp,
785
                  unsigned int cmd, unsigned long arg)
786
{
787
        drm_file_t *priv = filp->private_data;
788
        drm_device_t *dev = priv->dev;
789
        drm_mga_private_t *dev_priv =
790
            (drm_mga_private_t *) dev->dev_private;
791
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
792
 
793
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
794
                DRM_ERROR("mga_swap_bufs called without lock held\n");
795
                return -EINVAL;
796
        }
797
 
798
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
799
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
800
 
801
        /* Make sure we restore the 3D state next time.
802
         */
803
        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
804
        mga_dma_dispatch_swap(dev);
805
        PRIMUPDATE(dev_priv);
806
        set_bit(MGA_BUF_SWAP_PENDING,
807
                &dev_priv->current_prim->buffer_status);
808
        mga_flush_write_combine();
809
        mga_dma_schedule(dev, 1);
810
        return 0;
811
}
812
 
813
int mga_iload(struct inode *inode, struct file *filp,
814
              unsigned int cmd, unsigned long arg)
815
{
816
        drm_file_t *priv = filp->private_data;
817
        drm_device_t *dev = priv->dev;
818
        drm_device_dma_t *dma = dev->dma;
819
        drm_mga_private_t *dev_priv =
820
            (drm_mga_private_t *) dev->dev_private;
821
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
822
        drm_buf_t *buf;
823
        drm_mga_buf_priv_t *buf_priv;
824
        drm_mga_iload_t iload;
825
        unsigned long bus_address;
826
 
827
        if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
828
                return -EFAULT;
829
 
830
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
831
                DRM_ERROR("mga_iload called without lock held\n");
832
                return -EINVAL;
833
        }
834
 
835
        if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
836
        buf = dma->buflist[iload.idx];
837
        buf_priv = buf->dev_private;
838
        bus_address = buf->bus_address;
839
 
840
        if (mgaVerifyIload(dev_priv,
841
                           bus_address, iload.destOrg, iload.length)) {
842
                mga_freelist_put(dev, buf);
843
                return -EINVAL;
844
        }
845
 
846
        sarea_priv->dirty |= MGA_UPLOAD_CTX;
847
 
848
        mga_dma_dispatch_tex_blit(dev, bus_address, iload.length,
849
                                  iload.destOrg);
850
        AGEBUF(dev_priv, buf_priv);
851
        buf_priv->discard = 1;
852
        mga_freelist_put(dev, buf);
853
        mga_flush_write_combine();
854
        mga_dma_schedule(dev, 1);
855
        return 0;
856
}
857
 
858
int mga_vertex(struct inode *inode, struct file *filp,
859
               unsigned int cmd, unsigned long arg)
860
{
861
        drm_file_t *priv = filp->private_data;
862
        drm_device_t *dev = priv->dev;
863
        drm_mga_private_t *dev_priv =
864
            (drm_mga_private_t *) dev->dev_private;
865
        drm_device_dma_t *dma = dev->dma;
866
        drm_buf_t *buf;
867
        drm_mga_buf_priv_t *buf_priv;
868
        drm_mga_vertex_t vertex;
869
 
870
        if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
871
                return -EFAULT;
872
 
873
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
874
                DRM_ERROR("mga_vertex called without lock held\n");
875
                return -EINVAL;
876
        }
877
 
878
        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
879
 
880
        buf = dma->buflist[vertex.idx];
881
        buf_priv = buf->dev_private;
882
 
883
        buf->used = vertex.used;
884
        buf_priv->discard = vertex.discard;
885
 
886
        if (!mgaVerifyState(dev_priv)) {
887
                if (vertex.discard) {
888
                        if (buf_priv->dispatched == 1)
889
                                AGEBUF(dev_priv, buf_priv);
890
                        buf_priv->dispatched = 0;
891
                        mga_freelist_put(dev, buf);
892
                }
893
                return -EINVAL;
894
        }
895
 
896
        mga_dma_dispatch_vertex(dev, buf);
897
 
898
        PRIMUPDATE(dev_priv);
899
        mga_flush_write_combine();
900
        mga_dma_schedule(dev, 1);
901
        return 0;
902
}
903
 
904
 
905
int mga_indices(struct inode *inode, struct file *filp,
906
                unsigned int cmd, unsigned long arg)
907
{
908
        drm_file_t *priv = filp->private_data;
909
        drm_device_t *dev = priv->dev;
910
        drm_mga_private_t *dev_priv =
911
            (drm_mga_private_t *) dev->dev_private;
912
        drm_device_dma_t *dma = dev->dma;
913
        drm_buf_t *buf;
914
        drm_mga_buf_priv_t *buf_priv;
915
        drm_mga_indices_t indices;
916
 
917
        if (copy_from_user(&indices,
918
                           (drm_mga_indices_t *)arg, sizeof(indices)))
919
                return -EFAULT;
920
 
921
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
922
                DRM_ERROR("mga_indices called without lock held\n");
923
                return -EINVAL;
924
        }
925
 
926
        if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
927
        buf = dma->buflist[indices.idx];
928
        buf_priv = buf->dev_private;
929
 
930
        buf_priv->discard = indices.discard;
931
 
932
        if (!mgaVerifyState(dev_priv)) {
933
                if (indices.discard) {
934
                        if (buf_priv->dispatched == 1)
935
                                AGEBUF(dev_priv, buf_priv);
936
                        buf_priv->dispatched = 0;
937
                        mga_freelist_put(dev, buf);
938
                }
939
                return -EINVAL;
940
        }
941
 
942
        mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
943
 
944
        PRIMUPDATE(dev_priv);
945
        mga_flush_write_combine();
946
        mga_dma_schedule(dev, 1);
947
        return 0;
948
}
949
 
950
 
951
 
952
static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d)
953
{
954
        int i;
955
        drm_buf_t *buf;
956
 
957
        for (i = d->granted_count; i < d->request_count; i++) {
958
                buf = mga_freelist_get(dev);
959
                if (!buf)
960
                        break;
961
                buf->pid = current->pid;
962
                if (copy_to_user(&d->request_indices[i],
963
                                 &buf->idx, sizeof(buf->idx)))
964
                        return -EFAULT;
965
                if (copy_to_user(&d->request_sizes[i],
966
                                 &buf->total, sizeof(buf->total)))
967
                        return -EFAULT;
968
                ++d->granted_count;
969
        }
970
        return 0;
971
}
972
 
973
int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
974
            unsigned long arg)
975
{
976
        drm_file_t *priv = filp->private_data;
977
        drm_device_t *dev = priv->dev;
978
        drm_device_dma_t *dma = dev->dma;
979
        int retcode = 0;
980
        drm_dma_t d;
981
 
982
        if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
983
                return -EFAULT;
984
 
985
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
986
                DRM_ERROR("mga_dma called without lock held\n");
987
                return -EINVAL;
988
        }
989
 
990
        /* Please don't send us buffers.
991
         */
992
        if (d.send_count != 0) {
993
                DRM_ERROR
994
                    ("Process %d trying to send %d buffers via drmDMA\n",
995
                     current->pid, d.send_count);
996
                return -EINVAL;
997
        }
998
 
999
        /* We'll send you buffers.
1000
         */
1001
        if (d.request_count < 0 || d.request_count > dma->buf_count) {
1002
                DRM_ERROR
1003
                    ("Process %d trying to get %d buffers (of %d max)\n",
1004
                     current->pid, d.request_count, dma->buf_count);
1005
                return -EINVAL;
1006
        }
1007
 
1008
        d.granted_count = 0;
1009
 
1010
        if (d.request_count) {
1011
                retcode = mga_dma_get_buffers(dev, &d);
1012
        }
1013
 
1014
        if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
1015
                return -EFAULT;
1016
        return retcode;
1017
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.