~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/intel/server/intel_dri.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * \file server/intel_dri.c
3
 
 * \brief File to perform the device-specific initialization tasks typically
4
 
 * done in the X server.
5
 
 *
6
 
 * Here they are converted to run in the client (or perhaps a standalone
7
 
 * process), and to work with the frame buffer device rather than the X
8
 
 * server infrastructure.
9
 
 * 
10
 
 * Copyright (C) 2006 Dave Airlie (airlied@linux.ie)
11
 
 
12
 
 Permission is hereby granted, free of charge, to any person obtaining a
13
 
 copy of this software and associated documentation files (the
14
 
 "Software"), to deal in the Software without restriction, including
15
 
 without limitation the rights to use, copy, modify, merge, publish,
16
 
 distribute, sub license, and/or sell copies of the Software, and to
17
 
 permit persons to whom the Software is furnished to do so, subject to
18
 
 the following conditions:
19
 
 
20
 
 The above copyright notice and this permission notice (including the
21
 
 next paragraph) shall be included in all copies or substantial portions
22
 
 of the Software.
23
 
 
24
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25
 
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
 
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
27
 
 IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR
28
 
 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29
 
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30
 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
 
*/
32
 
 
33
 
#include <stdio.h>
34
 
#include <stdlib.h>
35
 
#include <string.h>
36
 
#include <errno.h>
37
 
#include <unistd.h>
38
 
 
39
 
#include "driver.h"
40
 
#include "drm.h"
41
 
 
42
 
#include "intel.h"
43
 
#include "i830_dri.h"
44
 
 
45
 
#include "memops.h"
46
 
#include "pciaccess.h"
47
 
 
48
 
static size_t drm_page_size;
49
 
static int nextTile = 0;
50
 
#define xf86DrvMsg(...) do {} while(0)
51
 
 
52
 
static const int pitches[] = {
53
 
  128 * 8,
54
 
  128 * 16,
55
 
  128 * 32,
56
 
  128 * 64,
57
 
  0
58
 
};
59
 
 
60
 
static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
61
 
 
62
 
static unsigned long
63
 
GetBestTileAlignment(unsigned long size)
64
 
{
65
 
   unsigned long i;
66
 
 
67
 
   for (i = KB(512); i < size; i <<= 1)
68
 
      ;
69
 
 
70
 
   if (i > MB(64))
71
 
      i = MB(64);
72
 
 
73
 
   return i;
74
 
}
75
 
 
76
 
static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
77
 
{
78
 
  int i;
79
 
  unsigned char *MMIO = ctx->MMIOAddress;
80
 
 
81
 
  for (i = 0; i < 8; i++) {
82
 
    OUTREG(FENCE + i * 4, pI830->Fence[i]);
83
 
    //    if (I810_DEBUG & DEBUG_VERBOSE_VGA)
84
 
    fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]);
85
 
  }
86
 
}
87
 
 
88
 
/* Tiled memory is good... really, really good...
89
 
 *
90
 
 * Need to make it less likely that we miss out on this - probably
91
 
 * need to move the frontbuffer away from the 'guarenteed' alignment
92
 
 * of the first memory segment, or perhaps allocate a discontigous
93
 
 * framebuffer to get more alignment 'sweet spots'.
94
 
 */
95
 
static void
96
 
SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
97
 
         int nr, unsigned int start, unsigned int pitch,
98
 
         unsigned int size)
99
 
{
100
 
   unsigned int val;
101
 
   unsigned int fence_mask = 0;
102
 
   unsigned int fence_pitch;
103
 
 
104
 
   if (nr < 0 || nr > 7) {
105
 
      fprintf(stderr,
106
 
                 "SetFence: fence %d out of range\n",nr);
107
 
      return;
108
 
   }
109
 
 
110
 
   pI830->Fence[nr] = 0;
111
 
 
112
 
   if (IS_I9XX(pI830))
113
 
        fence_mask = ~I915G_FENCE_START_MASK;
114
 
   else
115
 
        fence_mask = ~I830_FENCE_START_MASK;
116
 
 
117
 
   if (start & fence_mask) {
118
 
      fprintf(stderr,
119
 
                 "SetFence: %d: start (0x%08x) is not %s aligned\n",
120
 
                 nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
121
 
      return;
122
 
   }
123
 
 
124
 
   if (start % size) {
125
 
      fprintf(stderr,
126
 
                 "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
127
 
                 nr, start, size / 1024);
128
 
      return;
129
 
   }
130
 
 
131
 
   if (pitch & 127) {
132
 
      fprintf(stderr,
133
 
                 "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
134
 
                 nr, pitch);
135
 
      return;
136
 
   }
137
 
 
138
 
   val = (start | FENCE_X_MAJOR | FENCE_VALID);
139
 
 
140
 
   if (IS_I9XX(pI830)) {
141
 
        switch (size) {
142
 
           case MB(1):
143
 
                val |= I915G_FENCE_SIZE_1M;
144
 
                break;
145
 
           case MB(2):
146
 
                val |= I915G_FENCE_SIZE_2M;
147
 
                break;
148
 
           case MB(4):
149
 
                val |= I915G_FENCE_SIZE_4M;
150
 
                break;
151
 
           case MB(8):
152
 
                val |= I915G_FENCE_SIZE_8M;
153
 
                break;
154
 
           case MB(16):
155
 
                val |= I915G_FENCE_SIZE_16M;
156
 
                break;
157
 
           case MB(32):
158
 
                val |= I915G_FENCE_SIZE_32M;
159
 
                break;
160
 
           case MB(64):
161
 
                val |= I915G_FENCE_SIZE_64M;
162
 
                break;
163
 
           default:
164
 
                fprintf(stderr,
165
 
                 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
166
 
                return;
167
 
        }
168
 
    } else {
169
 
        switch (size) {
170
 
           case KB(512):
171
 
                val |= FENCE_SIZE_512K;
172
 
                break;
173
 
           case MB(1):
174
 
                val |= FENCE_SIZE_1M;
175
 
                break;
176
 
           case MB(2):
177
 
                val |= FENCE_SIZE_2M;
178
 
                break;
179
 
           case MB(4):
180
 
                val |= FENCE_SIZE_4M;
181
 
                break;
182
 
           case MB(8):
183
 
                val |= FENCE_SIZE_8M;
184
 
                break;
185
 
           case MB(16):
186
 
                val |= FENCE_SIZE_16M;
187
 
                break;
188
 
           case MB(32):
189
 
                val |= FENCE_SIZE_32M;
190
 
                break;
191
 
           case MB(64):
192
 
                val |= FENCE_SIZE_64M;
193
 
                break;
194
 
           default:
195
 
                fprintf(stderr,
196
 
                 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
197
 
                return;
198
 
        }
199
 
   }
200
 
 
201
 
   if (IS_I9XX(pI830))
202
 
        fence_pitch = pitch / 512;
203
 
   else
204
 
        fence_pitch = pitch / 128;
205
 
 
206
 
   switch (fence_pitch) {
207
 
   case 1:
208
 
      val |= FENCE_PITCH_1;
209
 
      break;
210
 
   case 2:
211
 
      val |= FENCE_PITCH_2;
212
 
      break;
213
 
   case 4:
214
 
      val |= FENCE_PITCH_4;
215
 
      break;
216
 
   case 8:
217
 
      val |= FENCE_PITCH_8;
218
 
      break;
219
 
   case 16:
220
 
      val |= FENCE_PITCH_16;
221
 
      break;
222
 
   case 32:
223
 
      val |= FENCE_PITCH_32;
224
 
      break;
225
 
   case 64:
226
 
      val |= FENCE_PITCH_64;
227
 
      break;
228
 
   default:
229
 
      fprintf(stderr,
230
 
                 "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
231
 
      return;
232
 
   }
233
 
 
234
 
   pI830->Fence[nr] = val;
235
 
}
236
 
 
237
 
static Bool
238
 
MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
239
 
{
240
 
   int pitch, ntiles, i;
241
 
 
242
 
   pitch = pMem->Pitch * ctx->cpp;
243
 
   /*
244
 
    * Simply try to break the region up into at most four pieces of size
245
 
    * equal to the alignment.
246
 
    */
247
 
   ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
248
 
   if (ntiles >= 4) {
249
 
      return FALSE;
250
 
   }
251
 
 
252
 
   for (i = 0; i < ntiles; i++, nextTile++) {
253
 
     SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
254
 
               pitch, pMem->Alignment);
255
 
   }
256
 
   return TRUE;
257
 
}
258
 
 
259
 
static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
260
 
{
261
 
  int i;
262
 
 
263
 
  /* Clear out */
264
 
  for (i = 0; i < 8; i++)
265
 
    pI830->Fence[i] = 0;
266
 
  
267
 
  nextTile = 0;
268
 
 
269
 
  if (pI830->BackBuffer.Alignment >= KB(512)) {
270
 
    if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
271
 
      fprintf(stderr,
272
 
                 "Activating tiled memory for the back buffer.\n");
273
 
    } else {
274
 
      fprintf(stderr,
275
 
                 "MakeTiles failed for the back buffer.\n");
276
 
      pI830->allowPageFlip = FALSE;
277
 
    }
278
 
  }
279
 
  
280
 
  if (pI830->DepthBuffer.Alignment >= KB(512)) {
281
 
    if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
282
 
      fprintf(stderr,
283
 
                 "Activating tiled memory for the depth buffer.\n");
284
 
    } else {
285
 
      fprintf(stderr,
286
 
                 "MakeTiles failed for the depth buffer.\n");
287
 
    }
288
 
  }
289
 
 
290
 
  return;
291
 
}
292
 
 
293
 
static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
294
 
{
295
 
  struct pci_device host_bridge, ig_dev;
296
 
  uint32_t gmch_ctrl;
297
 
  int memsize = 0;
298
 
  int range;
299
 
  uint32_t aper_size;
300
 
  uint32_t membase2 = 0;
301
 
      
302
 
  memset(&host_bridge, 0, sizeof(host_bridge));
303
 
  memset(&ig_dev, 0, sizeof(ig_dev));
304
 
 
305
 
  ig_dev.dev = 2;
306
 
 
307
 
  pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL);
308
 
 
309
 
  if (IS_I830(pI830) || IS_845G(pI830)) {
310
 
    if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
311
 
      aper_size = 0x80000000;
312
 
    } else {
313
 
      aper_size = 0x40000000;
314
 
    }
315
 
  } else {
316
 
    if (IS_I9XX(pI830)) {
317
 
      int ret;
318
 
      ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18);
319
 
      if (membase2 & 0x08000000)
320
 
        aper_size = 0x8000000;
321
 
      else
322
 
        aper_size = 0x10000000;
323
 
 
324
 
      fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret);
325
 
    } else
326
 
      aper_size = 0x8000000;
327
 
  }
328
 
 
329
 
  pI830->aper_size = aper_size;
330
 
 
331
 
 
332
 
  /* We need to reduce the stolen size, by the GTT and the popup.
333
 
   * The GTT varying according the the FbMapSize and the popup is 4KB */
334
 
  range = (ctx->shared.fbSize / (1024*1024)) + 4;
335
 
 
336
 
   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
337
 
      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
338
 
      case I855_GMCH_GMS_STOLEN_1M:
339
 
         memsize = MB(1) - KB(range);
340
 
         break;
341
 
      case I855_GMCH_GMS_STOLEN_4M:
342
 
         memsize = MB(4) - KB(range);
343
 
         break;
344
 
      case I855_GMCH_GMS_STOLEN_8M:
345
 
         memsize = MB(8) - KB(range);
346
 
         break;
347
 
      case I855_GMCH_GMS_STOLEN_16M:
348
 
         memsize = MB(16) - KB(range);
349
 
         break;
350
 
      case I855_GMCH_GMS_STOLEN_32M:
351
 
         memsize = MB(32) - KB(range);
352
 
         break;
353
 
      case I915G_GMCH_GMS_STOLEN_48M:
354
 
         if (IS_I9XX(pI830))
355
 
            memsize = MB(48) - KB(range);
356
 
         break;
357
 
      case I915G_GMCH_GMS_STOLEN_64M:
358
 
         if (IS_I9XX(pI830))
359
 
            memsize = MB(64) - KB(range);
360
 
         break;
361
 
      }
362
 
   } else {
363
 
      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
364
 
      case I830_GMCH_GMS_STOLEN_512:
365
 
         memsize = KB(512) - KB(range);
366
 
         break;
367
 
      case I830_GMCH_GMS_STOLEN_1024:
368
 
         memsize = MB(1) - KB(range);
369
 
         break;
370
 
      case I830_GMCH_GMS_STOLEN_8192:
371
 
         memsize = MB(8) - KB(range);
372
 
         break;
373
 
      case I830_GMCH_GMS_LOCAL:
374
 
         memsize = 0;
375
 
         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
376
 
                    "Local memory found, but won't be used.\n");
377
 
         break;
378
 
      }
379
 
   }
380
 
   if (memsize > 0) {
381
 
     fprintf(stderr,
382
 
                 "detected %d kB stolen memory.\n", memsize / 1024);
383
 
   } else {
384
 
     fprintf(stderr,
385
 
                 "no video memory detected.\n");
386
 
   }
387
 
   return memsize;
388
 
}
389
 
 
390
 
static int AgpInit(const DRIDriverContext *ctx, I830Rec *info)
391
 
{
392
 
  unsigned long mode = 0x4;
393
 
 
394
 
  if (drmAgpAcquire(ctx->drmFD) < 0) {
395
 
    fprintf(stderr, "[gart] AGP not available\n");
396
 
    return 0;
397
 
  }
398
 
  
399
 
  if (drmAgpEnable(ctx->drmFD, mode) < 0) {
400
 
    fprintf(stderr, "[gart] AGP not enabled\n");
401
 
    drmAgpRelease(ctx->drmFD);
402
 
    return 0;
403
 
  }
404
 
  else
405
 
    fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);
406
 
 
407
 
  return 1;
408
 
}
409
 
 
410
 
/*
411
 
 * Allocate memory from the given pool.  Grow the pool if needed and if
412
 
 * possible.
413
 
 */
414
 
static unsigned long
415
 
AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, 
416
 
              I830MemRange *result, I830MemPool *pool,
417
 
              long size, unsigned long alignment, int flags)
418
 
{
419
 
   long needed, start, end;
420
 
 
421
 
   if (!result || !pool || !size)
422
 
      return 0;
423
 
 
424
 
   /* Calculate how much space is needed. */
425
 
   if (alignment <= GTT_PAGE_SIZE)
426
 
      needed = size;
427
 
   else {
428
 
         start = ROUND_TO(pool->Free.Start, alignment);
429
 
         end = ROUND_TO(start + size, alignment);
430
 
         needed = end - pool->Free.Start;
431
 
   }
432
 
   if (needed > pool->Free.Size) {
433
 
     return 0;
434
 
   }
435
 
 
436
 
   result->Start = ROUND_TO(pool->Free.Start, alignment);
437
 
   pool->Free.Start += needed;
438
 
   result->End = pool->Free.Start;
439
 
 
440
 
   pool->Free.Size = pool->Free.End - pool->Free.Start;
441
 
   result->Size = result->End - result->Start;
442
 
   result->Pool = pool;
443
 
   result->Alignment = alignment;
444
 
   return needed;
445
 
}
446
 
 
447
 
static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange  *result)
448
 
{
449
 
   unsigned long start, end;
450
 
   unsigned long newApStart, newApEnd;
451
 
   int ret;
452
 
   if (!result || !size)
453
 
      return 0;
454
 
   
455
 
   if (!alignment)
456
 
     alignment = 4;
457
 
 
458
 
   start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
459
 
   end = ROUND_TO(start + size, alignment);
460
 
   newApStart = end;
461
 
   newApEnd = pI830->MemoryAperture.End;
462
 
 
463
 
   ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key));
464
 
   
465
 
   if (ret)
466
 
   {
467
 
     fprintf(stderr,"drmAgpAlloc failed %d\n", ret);
468
 
     return 0;
469
 
   }
470
 
   pI830->allocatedMemory += size;
471
 
   pI830->MemoryAperture.Start = newApStart;
472
 
   pI830->MemoryAperture.End = newApEnd;
473
 
   pI830->MemoryAperture.Size = newApEnd - newApStart;
474
 
   //   pI830->FreeMemory -= size;
475
 
   result->Start = start;
476
 
   result->End = start + size;
477
 
   result->Size = size;
478
 
   result->Offset = start;
479
 
   result->Alignment = alignment;
480
 
   result->Pool = NULL;
481
 
  
482
 
   return size;
483
 
}
484
 
 
485
 
unsigned long
486
 
I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830,
487
 
                I830MemRange *result, I830MemPool *pool, long size,
488
 
                unsigned long alignment, int flags)
489
 
{
490
 
   unsigned long ret;
491
 
 
492
 
   if (!result)
493
 
      return 0;
494
 
 
495
 
   /* Make sure these are initialised. */
496
 
   result->Size = 0;
497
 
   result->Key = -1;
498
 
 
499
 
   if (!size) {
500
 
      return 0;
501
 
   }
502
 
 
503
 
   if (pool->Free.Size < size) {
504
 
      ret = AllocFromAGP(ctx, pI830, size, alignment, result);
505
 
   }
506
 
   else {
507
 
      ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
508
 
      if (ret == 0)
509
 
         ret = AllocFromAGP(ctx, pI830, size, alignment, result);
510
 
   }
511
 
   return ret;
512
 
}
513
 
 
514
 
static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
515
 
{
516
 
  if (!mem)
517
 
    return FALSE;
518
 
  
519
 
  if (mem->Key == -1)
520
 
    return TRUE;
521
 
 
522
 
  return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
523
 
}
524
 
 
525
 
/* simple memory allocation routines needed */
526
 
/* put ring buffer in low memory */
527
 
/* need to allocate front, back, depth buffers aligned correctly,
528
 
   allocate ring buffer, 
529
 
*/
530
 
 
531
 
/* */
532
 
static Bool
533
 
I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
534
 
{
535
 
  unsigned long size, ret;
536
 
  unsigned long lines, lineSize, align;
537
 
 
538
 
  /* allocate ring buffer */
539
 
  memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
540
 
  pI830->LpRing->mem.Key = -1;
541
 
 
542
 
  size = PRIMARY_RINGBUFFER_SIZE;
543
 
  
544
 
  ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
545
 
  
546
 
  if (ret != size)
547
 
  {
548
 
    fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
549
 
    return FALSE;
550
 
  }
551
 
 
552
 
  pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
553
 
 
554
 
  
555
 
  /* allocate front buffer */
556
 
  memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
557
 
  pI830->FrontBuffer.Key = -1;
558
 
  pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
559
 
 
560
 
  align = KB(512);  
561
 
 
562
 
  lineSize = ctx->shared.virtualWidth * ctx->cpp;
563
 
  lines = (ctx->shared.virtualHeight + 15) / 16 * 16;
564
 
  size = lineSize * lines;
565
 
  size = ROUND_TO_PAGE(size);
566
 
 
567
 
  align = GetBestTileAlignment(size);
568
 
 
569
 
  ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
570
 
  if (ret < size)
571
 
  {
572
 
    fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
573
 
    return FALSE;
574
 
  }
575
 
 
576
 
  memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
577
 
  pI830->BackBuffer.Key = -1;
578
 
  pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
579
 
 
580
 
  ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
581
 
  if (ret < size)
582
 
  {
583
 
    fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
584
 
    return FALSE;
585
 
  }
586
 
  
587
 
  memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
588
 
  pI830->DepthBuffer.Key = -1;
589
 
  pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
590
 
 
591
 
  ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
592
 
  if (ret < size)
593
 
  {
594
 
    fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
595
 
    return FALSE;
596
 
  }
597
 
 
598
 
  memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
599
 
  pI830->ContextMem.Key = -1;
600
 
  size = KB(32);
601
 
 
602
 
  ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
603
 
  if (ret < size)
604
 
  {
605
 
    fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
606
 
    return FALSE;
607
 
  }
608
 
 
609
 
#if 0  
610
 
  memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
611
 
  pI830->TexMem.Key = -1;
612
 
 
613
 
  size = 32768 * 1024;
614
 
  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
615
 
  if (ret < size)
616
 
  {
617
 
    fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
618
 
    return FALSE;
619
 
  }
620
 
#endif
621
 
 
622
 
  return TRUE;
623
 
}
624
 
 
625
 
static Bool
626
 
I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
627
 
{
628
 
  if (!BindAgpRange(ctx, &pI830->LpRing->mem))
629
 
    return FALSE;
630
 
  if (!BindAgpRange(ctx, &pI830->FrontBuffer))
631
 
    return FALSE;
632
 
  if (!BindAgpRange(ctx, &pI830->BackBuffer))
633
 
    return FALSE;
634
 
  if (!BindAgpRange(ctx, &pI830->DepthBuffer))
635
 
    return FALSE;
636
 
  if (!BindAgpRange(ctx, &pI830->ContextMem))
637
 
    return FALSE;
638
 
#if 0
639
 
  if (!BindAgpRange(ctx, &pI830->TexMem))
640
 
    return FALSE;
641
 
#endif
642
 
  return TRUE;
643
 
}
644
 
 
645
 
static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830)
646
 
{
647
 
  unsigned long aperEnd = ROUND_DOWN_TO(pI830->aper_size, GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
648
 
  unsigned long aperStart = ROUND_TO(pI830->aper_size - KB(32768), GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
649
 
 
650
 
  fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize);
651
 
  if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) {
652
 
      fprintf(stderr,
653
 
              "DRM MM Initialization Failed\n");
654
 
  } else {
655
 
    fprintf(stderr,
656
 
            "DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart);
657
 
  }
658
 
 
659
 
}
660
 
 
661
 
static Bool
662
 
I830CleanupDma(const DRIDriverContext *ctx)
663
 
{
664
 
   drmI830Init info;
665
 
 
666
 
   memset(&info, 0, sizeof(drmI830Init));
667
 
   info.func = I830_CLEANUP_DMA;
668
 
 
669
 
   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
670
 
                       &info, sizeof(drmI830Init))) {
671
 
     fprintf(stderr, "I830 Dma Cleanup Failed\n");
672
 
      return FALSE;
673
 
   }
674
 
 
675
 
   return TRUE;
676
 
}
677
 
 
678
 
static Bool
679
 
I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
680
 
{
681
 
   I830RingBuffer *ring = pI830->LpRing;
682
 
   drmI830Init info;
683
 
 
684
 
   memset(&info, 0, sizeof(drmI830Init));
685
 
   info.func = I830_INIT_DMA;
686
 
 
687
 
   info.ring_start = ring->mem.Start + pI830->LinearAddr;
688
 
   info.ring_end = ring->mem.End + pI830->LinearAddr;
689
 
   info.ring_size = ring->mem.Size;
690
 
 
691
 
   info.mmio_offset = (unsigned int)ctx->MMIOStart;
692
 
 
693
 
   info.sarea_priv_offset = sizeof(drm_sarea_t);
694
 
 
695
 
   info.front_offset = pI830->FrontBuffer.Start;
696
 
   info.back_offset = pI830->BackBuffer.Start;
697
 
   info.depth_offset = pI830->DepthBuffer.Start;
698
 
   info.w = ctx->shared.virtualWidth;
699
 
   info.h = ctx->shared.virtualHeight;
700
 
   info.pitch = ctx->shared.virtualWidth;
701
 
   info.back_pitch = pI830->BackBuffer.Pitch;
702
 
   info.depth_pitch = pI830->DepthBuffer.Pitch;
703
 
   info.cpp = ctx->cpp;
704
 
 
705
 
   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
706
 
                       &info, sizeof(drmI830Init))) {
707
 
      fprintf(stderr,
708
 
                 "I830 Dma Initialization Failed\n");
709
 
      return FALSE;
710
 
   }
711
 
 
712
 
   return TRUE;
713
 
}
714
 
 
715
 
static int I830CheckDRMVersion( const DRIDriverContext *ctx,
716
 
                                  I830Rec *pI830 )
717
 
{
718
 
   drmVersionPtr  version;
719
 
 
720
 
   version = drmGetVersion(ctx->drmFD);
721
 
 
722
 
   if (version) {
723
 
     int req_minor, req_patch;
724
 
 
725
 
     req_minor = 4;
726
 
     req_patch = 0;     
727
 
 
728
 
     if (version->version_major != 1 ||
729
 
         version->version_minor < req_minor ||
730
 
         (version->version_minor == req_minor && 
731
 
          version->version_patchlevel < req_patch)) {
732
 
       /* Incompatible drm version */
733
 
       fprintf(stderr,
734
 
               "[dri] I830DRIScreenInit failed because of a version "
735
 
               "mismatch.\n"
736
 
               "[dri] i915.o kernel module version is %d.%d.%d "
737
 
               "but version 1.%d.%d or newer is needed.\n"
738
 
               "[dri] Disabling DRI.\n",
739
 
               version->version_major,
740
 
               version->version_minor,
741
 
               version->version_patchlevel,
742
 
               req_minor,
743
 
               req_patch);
744
 
       drmFreeVersion(version);
745
 
       return 0;
746
 
     }
747
 
     
748
 
     pI830->drmMinor = version->version_minor;
749
 
     drmFreeVersion(version);
750
 
   }
751
 
   return 1;
752
 
}
753
 
 
754
 
static void
755
 
I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
756
 
{
757
 
  unsigned int itemp;
758
 
  unsigned char *MMIO = ctx->MMIOAddress;
759
 
 
760
 
   OUTREG(LP_RING + RING_LEN, 0);
761
 
   OUTREG(LP_RING + RING_TAIL, 0);
762
 
   OUTREG(LP_RING + RING_HEAD, 0);
763
 
 
764
 
   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
765
 
       pI830->LpRing->mem.Start) {
766
 
      fprintf(stderr,
767
 
                 "I830SetRingRegs: Ring buffer start (%lx) violates its "
768
 
                 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
769
 
   }
770
 
   /* Don't care about the old value.  Reserved bits must be zero anyway. */
771
 
   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
772
 
   OUTREG(LP_RING + RING_START, itemp);
773
 
 
774
 
   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
775
 
       pI830->LpRing->mem.Size - 4096) {
776
 
      fprintf(stderr,
777
 
                 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
778
 
                 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
779
 
                 I830_RING_NR_PAGES);
780
 
   }
781
 
   /* Don't care about the old value.  Reserved bits must be zero anyway. */
782
 
   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
783
 
   itemp |= (RING_NO_REPORT | RING_VALID);
784
 
   OUTREG(LP_RING + RING_LEN, itemp);
785
 
 
786
 
   pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
787
 
   pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
788
 
   pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
789
 
   if (pI830->LpRing->space < 0)
790
 
      pI830->LpRing->space += pI830->LpRing->mem.Size;
791
 
 
792
 
   SetFenceRegs(ctx, pI830);
793
 
   
794
 
   /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
795
 
      hacky hacky */
796
 
   OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
797
 
 
798
 
}
799
 
 
800
 
static Bool
801
 
I830SetParam(const DRIDriverContext *ctx, int param, int value)
802
 
{
803
 
   drmI830SetParam sp;
804
 
 
805
 
   memset(&sp, 0, sizeof(sp));
806
 
   sp.param = param;
807
 
   sp.value = value;
808
 
 
809
 
   if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
810
 
      fprintf(stderr, "I830 SetParam Failed\n");
811
 
      return FALSE;
812
 
   }
813
 
 
814
 
   return TRUE;
815
 
}
816
 
 
817
 
static Bool
818
 
I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
819
 
{
820
 
   fprintf(stderr,
821
 
              "[drm] Mapping front buffer\n");
822
 
 
823
 
   if (drmAddMap(ctx->drmFD,
824
 
                 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
825
 
                 sarea->front_size,
826
 
                 DRM_FRAME_BUFFER,  /*DRM_AGP,*/
827
 
                 0,
828
 
                 &sarea->front_handle) < 0) {
829
 
     fprintf(stderr,
830
 
             "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
831
 
      return FALSE;
832
 
   }
833
 
   ctx->shared.hFrameBuffer = sarea->front_handle;
834
 
   ctx->shared.fbSize = sarea->front_size;
835
 
   fprintf(stderr, "[drm] Front Buffer = 0x%08x\n",
836
 
           sarea->front_handle);
837
 
 
838
 
   if (drmAddMap(ctx->drmFD,
839
 
                 (drm_handle_t)(sarea->back_offset),
840
 
                 sarea->back_size, DRM_AGP, 0,
841
 
                 &sarea->back_handle) < 0) {
842
 
      fprintf(stderr,
843
 
                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
844
 
      return FALSE;
845
 
   }
846
 
   fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
847
 
              sarea->back_handle);
848
 
 
849
 
   if (drmAddMap(ctx->drmFD,
850
 
                 (drm_handle_t)sarea->depth_offset,
851
 
                 sarea->depth_size, DRM_AGP, 0,
852
 
                 &sarea->depth_handle) < 0) {
853
 
      fprintf(stderr,
854
 
                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
855
 
      return FALSE;
856
 
   }
857
 
   fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
858
 
              sarea->depth_handle);
859
 
 
860
 
#if 0
861
 
   if (drmAddMap(ctx->drmFD,
862
 
                 (drm_handle_t)sarea->tex_offset,
863
 
                 sarea->tex_size, DRM_AGP, 0,
864
 
                 &sarea->tex_handle) < 0) {
865
 
      fprintf(stderr,
866
 
                 "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
867
 
      return FALSE;
868
 
   }
869
 
   fprintf(stderr, "[drm] textures = 0x%08x\n",
870
 
              sarea->tex_handle);
871
 
#endif
872
 
   return TRUE;
873
 
}
874
 
 
875
 
 
876
 
static void
877
 
I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
878
 
{
879
 
#if 1
880
 
   if (sarea->front_handle) {
881
 
      drmRmMap(ctx->drmFD, sarea->front_handle);
882
 
      sarea->front_handle = 0;
883
 
   }
884
 
#endif
885
 
   if (sarea->back_handle) {
886
 
      drmRmMap(ctx->drmFD, sarea->back_handle);
887
 
      sarea->back_handle = 0;
888
 
   }
889
 
   if (sarea->depth_handle) {
890
 
      drmRmMap(ctx->drmFD, sarea->depth_handle);
891
 
      sarea->depth_handle = 0;
892
 
   }
893
 
   if (sarea->tex_handle) {
894
 
      drmRmMap(ctx->drmFD, sarea->tex_handle);
895
 
      sarea->tex_handle = 0;
896
 
   }
897
 
}
898
 
 
899
 
static Bool
900
 
I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
901
 
{
902
 
  if (drmAddMap(ctx->drmFD,
903
 
                (drm_handle_t)pI830->LpRing->mem.Start,
904
 
                pI830->LpRing->mem.Size, DRM_AGP, 0,
905
 
                &pI830->ring_map) < 0) {
906
 
    fprintf(stderr,
907
 
            "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
908
 
    return FALSE;
909
 
  }
910
 
  fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
911
 
          pI830->ring_map);
912
 
 
913
 
  if (I830InitDma(ctx, pI830) == FALSE) {
914
 
    return FALSE;
915
 
  }
916
 
  
917
 
   /* init to zero to be safe */
918
 
 
919
 
  I830DRIMapScreenRegions(ctx, pI830, sarea);
920
 
  SetupDRIMM(ctx, pI830);
921
 
 
922
 
   if (ctx->pciDevice != PCI_CHIP_845_G &&
923
 
       ctx->pciDevice != PCI_CHIP_I830_M) {
924
 
      I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
925
 
   }
926
 
 
927
 
   /* Okay now initialize the dma engine */
928
 
   {
929
 
      pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
930
 
                                            ctx->pciBus,
931
 
                                            ctx->pciDevice,
932
 
                                            ctx->pciFunc);
933
 
 
934
 
      if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
935
 
         fprintf(stderr,
936
 
                    "[drm] failure adding irq handler\n");
937
 
         pI830->irq = 0;
938
 
         return FALSE;
939
 
      }
940
 
      else
941
 
         fprintf(stderr,
942
 
                    "[drm] dma control initialized, using IRQ %d\n",
943
 
                    pI830->irq);
944
 
   }
945
 
 
946
 
   fprintf(stderr, "[dri] visual configs initialized\n");
947
 
 
948
 
   return TRUE;
949
 
}
950
 
 
951
 
static Bool
952
 
I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
953
 
{
954
 
  /* need to drmMap front and back buffers and zero them */
955
 
  drmAddress map_addr;
956
 
  int ret;
957
 
 
958
 
  ret = drmMap(ctx->drmFD,
959
 
               sarea->front_handle,
960
 
               sarea->front_size,
961
 
               &map_addr);
962
 
 
963
 
  if (ret)
964
 
  {
965
 
    fprintf(stderr, "Unable to map front buffer\n");
966
 
    return FALSE;
967
 
  }
968
 
 
969
 
  drimemsetio((char *)map_addr,
970
 
              0,
971
 
              sarea->front_size);
972
 
  drmUnmap(map_addr, sarea->front_size);
973
 
 
974
 
 
975
 
  ret = drmMap(ctx->drmFD,
976
 
               sarea->back_handle,
977
 
               sarea->back_size,
978
 
               &map_addr);
979
 
 
980
 
  if (ret)
981
 
  {
982
 
    fprintf(stderr, "Unable to map back buffer\n");
983
 
    return FALSE;
984
 
  }
985
 
 
986
 
  drimemsetio((char *)map_addr,
987
 
              0,
988
 
              sarea->back_size);
989
 
  drmUnmap(map_addr, sarea->back_size);
990
 
 
991
 
  return TRUE;
992
 
}
993
 
 
994
 
static Bool
995
 
I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
996
 
                  
997
 
{
998
 
   I830DRIPtr pI830DRI;
999
 
   drmI830Sarea *pSAREAPriv;
1000
 
   int err;
1001
 
      
1002
 
   drm_page_size = getpagesize();   
1003
 
 
1004
 
   pI830->registerSize = ctx->MMIOSize;
1005
 
   /* This is a hack for now.  We have to have more than a 4k page here
1006
 
    * because of the size of the state.  However, the state should be
1007
 
    * in a per-context mapping.  This will be added in the Mesa 3.5 port
1008
 
    * of the I830 driver.
1009
 
    */
1010
 
   ctx->shared.SAREASize = SAREA_MAX;
1011
 
 
1012
 
   /* Note that drmOpen will try to load the kernel module, if needed. */
1013
 
   ctx->drmFD = drmOpen("i915", NULL );
1014
 
   if (ctx->drmFD < 0) {
1015
 
      fprintf(stderr, "[drm] drmOpen failed\n");
1016
 
      return 0;
1017
 
   }
1018
 
 
1019
 
   if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
1020
 
      fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
1021
 
              ctx->drmFD, ctx->pciBusID, strerror(-err));
1022
 
      return 0;
1023
 
   }
1024
 
 
1025
 
   if (drmAddMap( ctx->drmFD,
1026
 
                  0,
1027
 
                  ctx->shared.SAREASize,
1028
 
                  DRM_SHM,
1029
 
                  DRM_CONTAINS_LOCK,
1030
 
                  &ctx->shared.hSAREA) < 0)
1031
 
   {
1032
 
     fprintf(stderr, "[drm] drmAddMap failed\n");
1033
 
     return 0;
1034
 
   }
1035
 
 
1036
 
   fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
1037
 
           ctx->shared.SAREASize, ctx->shared.hSAREA);
1038
 
   
1039
 
   if (drmMap( ctx->drmFD,
1040
 
               ctx->shared.hSAREA,
1041
 
               ctx->shared.SAREASize,
1042
 
               (drmAddressPtr)(&ctx->pSAREA)) < 0)
1043
 
   {
1044
 
      fprintf(stderr, "[drm] drmMap failed\n");
1045
 
      return 0;
1046
 
   
1047
 
   }
1048
 
   
1049
 
   memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
1050
 
   fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n",
1051
 
           ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
1052
 
   
1053
 
 
1054
 
   if (drmAddMap(ctx->drmFD, 
1055
 
                 ctx->MMIOStart,
1056
 
                 ctx->MMIOSize,
1057
 
                 DRM_REGISTERS, 
1058
 
                 DRM_READ_ONLY, 
1059
 
                 &pI830->registerHandle) < 0) {
1060
 
      fprintf(stderr, "[drm] drmAddMap mmio failed\n"); 
1061
 
      return 0;
1062
 
   }
1063
 
   fprintf(stderr,
1064
 
           "[drm] register handle = 0x%08x\n", pI830->registerHandle);
1065
 
 
1066
 
 
1067
 
   if (!I830CheckDRMVersion(ctx, pI830)) {
1068
 
     return FALSE;
1069
 
   }
1070
 
 
1071
 
   /* Create a 'server' context so we can grab the lock for
1072
 
    * initialization ioctls.
1073
 
    */
1074
 
   if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
1075
 
      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
1076
 
      return 0;
1077
 
   }
1078
 
 
1079
 
   DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); 
1080
 
 
1081
 
   /* Initialize the SAREA private data structure */
1082
 
   pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
1083
 
                                 sizeof(drm_sarea_t));
1084
 
   memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
1085
 
 
1086
 
   pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
1087
 
   pI830->StolenMemory.Start = 0;
1088
 
   pI830->StolenMemory.End = pI830->StolenMemory.Size;
1089
 
 
1090
 
   pI830->MemoryAperture.Start = pI830->StolenMemory.End;
1091
 
   pI830->MemoryAperture.End = KB(40000);
1092
 
   pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
1093
 
 
1094
 
   pI830->StolenPool.Fixed = pI830->StolenMemory;
1095
 
   pI830->StolenPool.Total = pI830->StolenMemory;
1096
 
   pI830->StolenPool.Free = pI830->StolenPool.Total;
1097
 
   pI830->FreeMemory = pI830->StolenPool.Total.Size;
1098
 
 
1099
 
   if (!AgpInit(ctx, pI830))
1100
 
     return FALSE;
1101
 
 
1102
 
   if (I830AllocateMemory(ctx, pI830) == FALSE)
1103
 
   {
1104
 
     return FALSE;
1105
 
   }
1106
 
 
1107
 
   if (I830BindMemory(ctx, pI830) == FALSE)
1108
 
   {
1109
 
     return FALSE;
1110
 
   }
1111
 
 
1112
 
   pSAREAPriv->rotated_offset = -1;
1113
 
   pSAREAPriv->rotated_size = 0;
1114
 
   pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth;
1115
 
 
1116
 
   pSAREAPriv->front_offset = pI830->FrontBuffer.Start;
1117
 
   pSAREAPriv->front_size = pI830->FrontBuffer.Size;
1118
 
   pSAREAPriv->width = ctx->shared.virtualWidth;
1119
 
   pSAREAPriv->height = ctx->shared.virtualHeight;
1120
 
   pSAREAPriv->pitch = ctx->shared.virtualWidth;
1121
 
   pSAREAPriv->virtualX = ctx->shared.virtualWidth;
1122
 
   pSAREAPriv->virtualY = ctx->shared.virtualHeight;
1123
 
   pSAREAPriv->back_offset = pI830->BackBuffer.Start;
1124
 
   pSAREAPriv->back_size = pI830->BackBuffer.Size;
1125
 
   pSAREAPriv->depth_offset = pI830->DepthBuffer.Start;
1126
 
   pSAREAPriv->depth_size = pI830->DepthBuffer.Size;
1127
 
#if 0
1128
 
   pSAREAPriv->tex_offset = pI830->TexMem.Start;
1129
 
   pSAREAPriv->tex_size = pI830->TexMem.Size;
1130
 
#endif
1131
 
   pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
1132
 
 
1133
 
   ctx->driverClientMsg = malloc(sizeof(I830DRIRec));
1134
 
   ctx->driverClientMsgSize = sizeof(I830DRIRec);
1135
 
   pI830DRI = (I830DRIPtr)ctx->driverClientMsg;
1136
 
   pI830DRI->deviceID = pI830->Chipset;
1137
 
   pI830DRI->regsSize = I830_REG_SIZE;
1138
 
   pI830DRI->width = ctx->shared.virtualWidth;
1139
 
   pI830DRI->height = ctx->shared.virtualHeight;
1140
 
   pI830DRI->mem = ctx->shared.fbSize;
1141
 
   pI830DRI->cpp = ctx->cpp;
1142
 
 
1143
 
   pI830DRI->bitsPerPixel = ctx->bpp;
1144
 
   pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
1145
 
   
1146
 
   err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
1147
 
   if (err == FALSE)
1148
 
       return FALSE;
1149
 
 
1150
 
   I830SetupMemoryTiling(ctx, pI830);
1151
 
 
1152
 
   /* Quick hack to clear the front & back buffers.  Could also use
1153
 
    * the clear ioctl to do this, but would need to setup hw state
1154
 
    * first.
1155
 
    */
1156
 
   I830ClearScreen(ctx, pI830, pSAREAPriv);
1157
 
 
1158
 
   I830SetRingRegs(ctx, pI830);
1159
 
 
1160
 
   return TRUE;
1161
 
}
1162
 
 
1163
 
 
1164
 
/**
1165
 
 * \brief Validate the fbdev mode.
1166
 
 * 
1167
 
 * \param ctx display handle.
1168
 
 *
1169
 
 * \return one on success, or zero on failure.
1170
 
 *
1171
 
 * Saves some registers and returns 1.
1172
 
 *
1173
 
 * \sa radeonValidateMode().
1174
 
 */
1175
 
static int i830ValidateMode( const DRIDriverContext *ctx )
1176
 
{
1177
 
  return 1;
1178
 
}
1179
 
 
1180
 
/**
1181
 
 * \brief Examine mode returned by fbdev.
1182
 
 * 
1183
 
 * \param ctx display handle.
1184
 
 *
1185
 
 * \return one on success, or zero on failure.
1186
 
 *
1187
 
 * Restores registers that fbdev has clobbered and returns 1.
1188
 
 *
1189
 
 * \sa i810ValidateMode().
1190
 
 */
1191
 
static int i830PostValidateMode( const DRIDriverContext *ctx )
1192
 
{
1193
 
  I830Rec *pI830 = ctx->driverPrivate;
1194
 
 
1195
 
  I830SetRingRegs(ctx, pI830);
1196
 
  return 1;
1197
 
}
1198
 
 
1199
 
 
1200
 
/**
1201
 
 * \brief Initialize the framebuffer device mode
1202
 
 *
1203
 
 * \param ctx display handle.
1204
 
 *
1205
 
 * \return one on success, or zero on failure.
1206
 
 *
1207
 
 * Fills in \p info with some default values and some information from \p ctx
1208
 
 * and then calls I810ScreenInit() for the screen initialization.
1209
 
 * 
1210
 
 * Before exiting clears the framebuffer memory accessing it directly.
1211
 
 */
1212
 
static int i830InitFBDev( DRIDriverContext *ctx )
1213
 
{
1214
 
  I830Rec *pI830 = calloc(1, sizeof(I830Rec));
1215
 
  int i;
1216
 
 
1217
 
   {
1218
 
      int  dummy = ctx->shared.virtualWidth;
1219
 
 
1220
 
      switch (ctx->bpp / 8) {
1221
 
      case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
1222
 
      case 2: dummy = (ctx->shared.virtualWidth +  31) &  ~31; break;
1223
 
      case 3:
1224
 
      case 4: dummy = (ctx->shared.virtualWidth +  15) &  ~15; break;
1225
 
      }
1226
 
 
1227
 
      ctx->shared.virtualWidth = dummy;
1228
 
      ctx->shared.Width = ctx->shared.virtualWidth;
1229
 
   }
1230
 
 
1231
 
 
1232
 
   for (i = 0; pitches[i] != 0; i++) {
1233
 
     if (pitches[i] >= ctx->shared.virtualWidth) {
1234
 
       ctx->shared.virtualWidth = pitches[i];
1235
 
       break;
1236
 
     }
1237
 
   }
1238
 
 
1239
 
   ctx->driverPrivate = (void *)pI830;
1240
 
   
1241
 
   pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
1242
 
   pI830->Chipset = ctx->chipset;
1243
 
   pI830->LinearAddr = ctx->FBStart;
1244
 
 
1245
 
   if (!I830ScreenInit( ctx, pI830 ))
1246
 
      return 0;
1247
 
 
1248
 
   
1249
 
   return 1;
1250
 
}
1251
 
 
1252
 
 
1253
 
/**
1254
 
 * \brief The screen is being closed, so clean up any state and free any
1255
 
 * resources used by the DRI.
1256
 
 *
1257
 
 * \param ctx display handle.
1258
 
 *
1259
 
 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1260
 
 * private data.
1261
 
 */
1262
 
static void i830HaltFBDev( DRIDriverContext *ctx )
1263
 
{
1264
 
  drmI830Sarea *pSAREAPriv;
1265
 
  I830Rec *pI830 = ctx->driverPrivate;
1266
 
 
1267
 
   if (pI830->irq) {
1268
 
       drmCtlUninstHandler(ctx->drmFD);
1269
 
       pI830->irq = 0;   }
1270
 
 
1271
 
   I830CleanupDma(ctx);
1272
 
 
1273
 
  pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
1274
 
                                sizeof(drm_sarea_t));
1275
 
 
1276
 
  I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
1277
 
  drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
1278
 
  drmClose(ctx->drmFD);
1279
 
  
1280
 
  if (ctx->driverPrivate) {
1281
 
    free(ctx->driverPrivate);
1282
 
    ctx->driverPrivate = 0;
1283
 
  }
1284
 
}
1285
 
 
1286
 
 
1287
 
extern void i810NotifyFocus( int );
1288
 
 
1289
 
/**
1290
 
 * \brief Exported driver interface for Mini GLX.
1291
 
 *
1292
 
 * \sa DRIDriverRec.
1293
 
 */
1294
 
const struct DRIDriverRec __driDriver = {
1295
 
   i830ValidateMode,
1296
 
   i830PostValidateMode,
1297
 
   i830InitFBDev,
1298
 
   i830HaltFBDev,
1299
 
   NULL,//I830EngineShutdown,
1300
 
   NULL, //I830EngineRestore,  
1301
 
#ifndef _EMBEDDED
1302
 
   0,
1303
 
#else
1304
 
   i810NotifyFocus, 
1305
 
#endif
1306
 
};