~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

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, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags)
 
487
{
 
488
  int ret;
 
489
 
 
490
  if (!result)
 
491
    return 0;
 
492
 
 
493
   /* Make sure these are initialised. */
 
494
   result->Size = 0;
 
495
   result->Key = -1;
 
496
 
 
497
   if (!size) {
 
498
      return 0;
 
499
   }
 
500
 
 
501
   if (pool->Free.Size < size)
 
502
     return AllocFromAGP(ctx, pI830, size, alignment, result);
 
503
   else
 
504
   {
 
505
     ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
 
506
 
 
507
     if (ret==0)
 
508
       return AllocFromAGP(ctx, pI830, size, alignment, result);
 
509
     return ret;
 
510
   }
 
511
}
 
512
 
 
513
static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
 
514
{
 
515
  if (!mem)
 
516
    return FALSE;
 
517
  
 
518
  if (mem->Key == -1)
 
519
    return TRUE;
 
520
 
 
521
  return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
 
522
}
 
523
 
 
524
/* simple memory allocation routines needed */
 
525
/* put ring buffer in low memory */
 
526
/* need to allocate front, back, depth buffers aligned correctly,
 
527
   allocate ring buffer, 
 
528
*/
 
529
 
 
530
/* */
 
531
static Bool
 
532
I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
 
533
{
 
534
  unsigned long size, ret;
 
535
  unsigned long lines, lineSize, align;
 
536
 
 
537
  /* allocate ring buffer */
 
538
  memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
 
539
  pI830->LpRing->mem.Key = -1;
 
540
 
 
541
  size = PRIMARY_RINGBUFFER_SIZE;
 
542
  
 
543
  ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
 
544
  
 
545
  if (ret != size)
 
546
  {
 
547
    fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
 
548
    return FALSE;
 
549
  }
 
550
 
 
551
  pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
 
552
 
 
553
  
 
554
  /* allocate front buffer */
 
555
  memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
 
556
  pI830->FrontBuffer.Key = -1;
 
557
  pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
 
558
 
 
559
  align = KB(512);  
 
560
 
 
561
  lineSize = ctx->shared.virtualWidth * ctx->cpp;
 
562
  lines = (ctx->shared.virtualHeight + 15) / 16 * 16;
 
563
  size = lineSize * lines;
 
564
  size = ROUND_TO_PAGE(size);
 
565
 
 
566
  align = GetBestTileAlignment(size);
 
567
 
 
568
  ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
 
569
  if (ret < size)
 
570
  {
 
571
    fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
 
572
    return FALSE;
 
573
  }
 
574
 
 
575
  memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
 
576
  pI830->BackBuffer.Key = -1;
 
577
  pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
 
578
 
 
579
  ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
 
580
  if (ret < size)
 
581
  {
 
582
    fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
 
583
    return FALSE;
 
584
  }
 
585
  
 
586
  memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
 
587
  pI830->DepthBuffer.Key = -1;
 
588
  pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
 
589
 
 
590
  ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
 
591
  if (ret < size)
 
592
  {
 
593
    fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
 
594
    return FALSE;
 
595
  }
 
596
 
 
597
  memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
 
598
  pI830->ContextMem.Key = -1;
 
599
  size = KB(32);
 
600
 
 
601
  ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
 
602
  if (ret < size)
 
603
  {
 
604
    fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
 
605
    return FALSE;
 
606
  }
 
607
 
 
608
#if 0  
 
609
  memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
 
610
  pI830->TexMem.Key = -1;
 
611
 
 
612
  size = 32768 * 1024;
 
613
  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
 
614
  if (ret < size)
 
615
  {
 
616
    fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
 
617
    return FALSE;
 
618
  }
 
619
#endif
 
620
 
 
621
  return TRUE;
 
622
}
 
623
 
 
624
static Bool
 
625
I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
 
626
{
 
627
  if (!BindAgpRange(ctx, &pI830->LpRing->mem))
 
628
    return FALSE;
 
629
  if (!BindAgpRange(ctx, &pI830->FrontBuffer))
 
630
    return FALSE;
 
631
  if (!BindAgpRange(ctx, &pI830->BackBuffer))
 
632
    return FALSE;
 
633
  if (!BindAgpRange(ctx, &pI830->DepthBuffer))
 
634
    return FALSE;
 
635
  if (!BindAgpRange(ctx, &pI830->ContextMem))
 
636
    return FALSE;
 
637
#if 0
 
638
  if (!BindAgpRange(ctx, &pI830->TexMem))
 
639
    return FALSE;
 
640
#endif
 
641
  return TRUE;
 
642
}
 
643
 
 
644
static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830)
 
645
{
 
646
  unsigned long aperEnd = ROUND_DOWN_TO(pI830->aper_size, GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
 
647
  unsigned long aperStart = ROUND_TO(pI830->aper_size - KB(32768), GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
 
648
 
 
649
  fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize);
 
650
  if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) {
 
651
      fprintf(stderr,
 
652
              "DRM MM Initialization Failed\n");
 
653
  } else {
 
654
    fprintf(stderr,
 
655
            "DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart);
 
656
  }
 
657
 
 
658
}
 
659
 
 
660
static Bool
 
661
I830CleanupDma(const DRIDriverContext *ctx)
 
662
{
 
663
   drmI830Init info;
 
664
 
 
665
   memset(&info, 0, sizeof(drmI830Init));
 
666
   info.func = I830_CLEANUP_DMA;
 
667
 
 
668
   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
 
669
                       &info, sizeof(drmI830Init))) {
 
670
     fprintf(stderr, "I830 Dma Cleanup Failed\n");
 
671
      return FALSE;
 
672
   }
 
673
 
 
674
   return TRUE;
 
675
}
 
676
 
 
677
static Bool
 
678
I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
 
679
{
 
680
   I830RingBuffer *ring = pI830->LpRing;
 
681
   drmI830Init info;
 
682
 
 
683
   memset(&info, 0, sizeof(drmI830Init));
 
684
   info.func = I830_INIT_DMA;
 
685
 
 
686
   info.ring_start = ring->mem.Start + pI830->LinearAddr;
 
687
   info.ring_end = ring->mem.End + pI830->LinearAddr;
 
688
   info.ring_size = ring->mem.Size;
 
689
 
 
690
   info.mmio_offset = (unsigned int)ctx->MMIOStart;
 
691
 
 
692
   info.sarea_priv_offset = sizeof(drm_sarea_t);
 
693
 
 
694
   info.front_offset = pI830->FrontBuffer.Start;
 
695
   info.back_offset = pI830->BackBuffer.Start;
 
696
   info.depth_offset = pI830->DepthBuffer.Start;
 
697
   info.w = ctx->shared.virtualWidth;
 
698
   info.h = ctx->shared.virtualHeight;
 
699
   info.pitch = ctx->shared.virtualWidth;
 
700
   info.back_pitch = pI830->BackBuffer.Pitch;
 
701
   info.depth_pitch = pI830->DepthBuffer.Pitch;
 
702
   info.cpp = ctx->cpp;
 
703
 
 
704
   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
 
705
                       &info, sizeof(drmI830Init))) {
 
706
      fprintf(stderr,
 
707
                 "I830 Dma Initialization Failed\n");
 
708
      return FALSE;
 
709
   }
 
710
 
 
711
   return TRUE;
 
712
}
 
713
 
 
714
static int I830CheckDRMVersion( const DRIDriverContext *ctx,
 
715
                                  I830Rec *pI830 )
 
716
{
 
717
   drmVersionPtr  version;
 
718
 
 
719
   version = drmGetVersion(ctx->drmFD);
 
720
 
 
721
   if (version) {
 
722
     int req_minor, req_patch;
 
723
 
 
724
     req_minor = 4;
 
725
     req_patch = 0;     
 
726
 
 
727
     if (version->version_major != 1 ||
 
728
         version->version_minor < req_minor ||
 
729
         (version->version_minor == req_minor && 
 
730
          version->version_patchlevel < req_patch)) {
 
731
       /* Incompatible drm version */
 
732
       fprintf(stderr,
 
733
               "[dri] I830DRIScreenInit failed because of a version "
 
734
               "mismatch.\n"
 
735
               "[dri] i915.o kernel module version is %d.%d.%d "
 
736
               "but version 1.%d.%d or newer is needed.\n"
 
737
               "[dri] Disabling DRI.\n",
 
738
               version->version_major,
 
739
               version->version_minor,
 
740
               version->version_patchlevel,
 
741
               req_minor,
 
742
               req_patch);
 
743
       drmFreeVersion(version);
 
744
       return 0;
 
745
     }
 
746
     
 
747
     pI830->drmMinor = version->version_minor;
 
748
     drmFreeVersion(version);
 
749
   }
 
750
   return 1;
 
751
}
 
752
 
 
753
static void
 
754
I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
 
755
{
 
756
  unsigned int itemp;
 
757
  unsigned char *MMIO = ctx->MMIOAddress;
 
758
 
 
759
   OUTREG(LP_RING + RING_LEN, 0);
 
760
   OUTREG(LP_RING + RING_TAIL, 0);
 
761
   OUTREG(LP_RING + RING_HEAD, 0);
 
762
 
 
763
   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
 
764
       pI830->LpRing->mem.Start) {
 
765
      fprintf(stderr,
 
766
                 "I830SetRingRegs: Ring buffer start (%lx) violates its "
 
767
                 "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
 
768
   }
 
769
   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 
770
   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
 
771
   OUTREG(LP_RING + RING_START, itemp);
 
772
 
 
773
   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
 
774
       pI830->LpRing->mem.Size - 4096) {
 
775
      fprintf(stderr,
 
776
                 "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
 
777
                 "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
 
778
                 I830_RING_NR_PAGES);
 
779
   }
 
780
   /* Don't care about the old value.  Reserved bits must be zero anyway. */
 
781
   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
 
782
   itemp |= (RING_NO_REPORT | RING_VALID);
 
783
   OUTREG(LP_RING + RING_LEN, itemp);
 
784
 
 
785
   pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
 
786
   pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
 
787
   pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
 
788
   if (pI830->LpRing->space < 0)
 
789
      pI830->LpRing->space += pI830->LpRing->mem.Size;
 
790
 
 
791
   SetFenceRegs(ctx, pI830);
 
792
   
 
793
   /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
 
794
      hacky hacky */
 
795
   OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
 
796
 
 
797
}
 
798
 
 
799
static Bool
 
800
I830SetParam(const DRIDriverContext *ctx, int param, int value)
 
801
{
 
802
   drmI830SetParam sp;
 
803
 
 
804
   memset(&sp, 0, sizeof(sp));
 
805
   sp.param = param;
 
806
   sp.value = value;
 
807
 
 
808
   if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
 
809
      fprintf(stderr, "I830 SetParam Failed\n");
 
810
      return FALSE;
 
811
   }
 
812
 
 
813
   return TRUE;
 
814
}
 
815
 
 
816
static Bool
 
817
I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
 
818
{
 
819
   fprintf(stderr,
 
820
              "[drm] Mapping front buffer\n");
 
821
 
 
822
   if (drmAddMap(ctx->drmFD,
 
823
                 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
 
824
                 sarea->front_size,
 
825
                 DRM_FRAME_BUFFER,  /*DRM_AGP,*/
 
826
                 0,
 
827
                 &sarea->front_handle) < 0) {
 
828
     fprintf(stderr,
 
829
             "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
 
830
      return FALSE;
 
831
   }
 
832
   ctx->shared.hFrameBuffer = sarea->front_handle;
 
833
   ctx->shared.fbSize = sarea->front_size;
 
834
   fprintf(stderr, "[drm] Front Buffer = 0x%08x\n",
 
835
           sarea->front_handle);
 
836
 
 
837
   if (drmAddMap(ctx->drmFD,
 
838
                 (drm_handle_t)(sarea->back_offset),
 
839
                 sarea->back_size, DRM_AGP, 0,
 
840
                 &sarea->back_handle) < 0) {
 
841
      fprintf(stderr,
 
842
                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
 
843
      return FALSE;
 
844
   }
 
845
   fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
 
846
              sarea->back_handle);
 
847
 
 
848
   if (drmAddMap(ctx->drmFD,
 
849
                 (drm_handle_t)sarea->depth_offset,
 
850
                 sarea->depth_size, DRM_AGP, 0,
 
851
                 &sarea->depth_handle) < 0) {
 
852
      fprintf(stderr,
 
853
                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
 
854
      return FALSE;
 
855
   }
 
856
   fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
 
857
              sarea->depth_handle);
 
858
 
 
859
#if 0
 
860
   if (drmAddMap(ctx->drmFD,
 
861
                 (drm_handle_t)sarea->tex_offset,
 
862
                 sarea->tex_size, DRM_AGP, 0,
 
863
                 &sarea->tex_handle) < 0) {
 
864
      fprintf(stderr,
 
865
                 "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
 
866
      return FALSE;
 
867
   }
 
868
   fprintf(stderr, "[drm] textures = 0x%08x\n",
 
869
              sarea->tex_handle);
 
870
#endif
 
871
   return TRUE;
 
872
}
 
873
 
 
874
 
 
875
static void
 
876
I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
 
877
{
 
878
#if 1
 
879
   if (sarea->front_handle) {
 
880
      drmRmMap(ctx->drmFD, sarea->front_handle);
 
881
      sarea->front_handle = 0;
 
882
   }
 
883
#endif
 
884
   if (sarea->back_handle) {
 
885
      drmRmMap(ctx->drmFD, sarea->back_handle);
 
886
      sarea->back_handle = 0;
 
887
   }
 
888
   if (sarea->depth_handle) {
 
889
      drmRmMap(ctx->drmFD, sarea->depth_handle);
 
890
      sarea->depth_handle = 0;
 
891
   }
 
892
   if (sarea->tex_handle) {
 
893
      drmRmMap(ctx->drmFD, sarea->tex_handle);
 
894
      sarea->tex_handle = 0;
 
895
   }
 
896
}
 
897
 
 
898
#if 0
 
899
static void
 
900
I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
 
901
{
 
902
   /* Start up the simple memory manager for agp space */
 
903
   drmI830MemInitHeap drmHeap;
 
904
   drmHeap.region = I830_MEM_REGION_AGP;
 
905
   drmHeap.start  = 0;
 
906
   drmHeap.size   = sarea->tex_size;
 
907
      
 
908
   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
 
909
                          &drmHeap, sizeof(drmHeap))) {
 
910
      fprintf(stderr,
 
911
                    "[drm] Failed to initialized agp heap manager\n");
 
912
   } else {
 
913
      fprintf(stderr,
 
914
                    "[drm] Initialized kernel agp heap manager, %d\n",
 
915
                    sarea->tex_size);
 
916
 
 
917
      I830SetParam(ctx, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
 
918
                      sarea->log_tex_granularity);
 
919
   }
 
920
}
 
921
#endif
 
922
 
 
923
static Bool
 
924
I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
 
925
{
 
926
  if (drmAddMap(ctx->drmFD,
 
927
                (drm_handle_t)pI830->LpRing->mem.Start,
 
928
                pI830->LpRing->mem.Size, DRM_AGP, 0,
 
929
                &pI830->ring_map) < 0) {
 
930
    fprintf(stderr,
 
931
            "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
 
932
    return FALSE;
 
933
  }
 
934
  fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
 
935
          pI830->ring_map);
 
936
 
 
937
  if (I830InitDma(ctx, pI830) == FALSE) {
 
938
    return FALSE;
 
939
  }
 
940
  
 
941
   /* init to zero to be safe */
 
942
 
 
943
  I830DRIMapScreenRegions(ctx, pI830, sarea);
 
944
  SetupDRIMM(ctx, pI830);
 
945
 
 
946
#if 0
 
947
  I830InitTextureHeap(ctx, pI830, sarea);
 
948
#endif
 
949
   if (ctx->pciDevice != PCI_CHIP_845_G &&
 
950
       ctx->pciDevice != PCI_CHIP_I830_M) {
 
951
      I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
 
952
   }
 
953
 
 
954
   /* Okay now initialize the dma engine */
 
955
   {
 
956
      pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
 
957
                                            ctx->pciBus,
 
958
                                            ctx->pciDevice,
 
959
                                            ctx->pciFunc);
 
960
 
 
961
      if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
 
962
         fprintf(stderr,
 
963
                    "[drm] failure adding irq handler\n");
 
964
         pI830->irq = 0;
 
965
         return FALSE;
 
966
      }
 
967
      else
 
968
         fprintf(stderr,
 
969
                    "[drm] dma control initialized, using IRQ %d\n",
 
970
                    pI830->irq);
 
971
   }
 
972
 
 
973
   fprintf(stderr, "[dri] visual configs initialized\n");
 
974
 
 
975
   return TRUE;
 
976
}
 
977
 
 
978
static Bool
 
979
I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
 
980
{
 
981
  /* need to drmMap front and back buffers and zero them */
 
982
  drmAddress map_addr;
 
983
  int ret;
 
984
 
 
985
  ret = drmMap(ctx->drmFD,
 
986
               sarea->front_handle,
 
987
               sarea->front_size,
 
988
               &map_addr);
 
989
 
 
990
  if (ret)
 
991
  {
 
992
    fprintf(stderr, "Unable to map front buffer\n");
 
993
    return FALSE;
 
994
  }
 
995
 
 
996
  drimemsetio((char *)map_addr,
 
997
              0,
 
998
              sarea->front_size);
 
999
  drmUnmap(map_addr, sarea->front_size);
 
1000
 
 
1001
 
 
1002
  ret = drmMap(ctx->drmFD,
 
1003
               sarea->back_handle,
 
1004
               sarea->back_size,
 
1005
               &map_addr);
 
1006
 
 
1007
  if (ret)
 
1008
  {
 
1009
    fprintf(stderr, "Unable to map back buffer\n");
 
1010
    return FALSE;
 
1011
  }
 
1012
 
 
1013
  drimemsetio((char *)map_addr,
 
1014
              0,
 
1015
              sarea->back_size);
 
1016
  drmUnmap(map_addr, sarea->back_size);
 
1017
 
 
1018
  return TRUE;
 
1019
}
 
1020
 
 
1021
static Bool
 
1022
I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
 
1023
                  
 
1024
{
 
1025
   I830DRIPtr pI830DRI;
 
1026
   drmI830Sarea *pSAREAPriv;
 
1027
   int err;
 
1028
      
 
1029
   drm_page_size = getpagesize();   
 
1030
 
 
1031
   pI830->registerSize = ctx->MMIOSize;
 
1032
   /* This is a hack for now.  We have to have more than a 4k page here
 
1033
    * because of the size of the state.  However, the state should be
 
1034
    * in a per-context mapping.  This will be added in the Mesa 3.5 port
 
1035
    * of the I830 driver.
 
1036
    */
 
1037
   ctx->shared.SAREASize = SAREA_MAX;
 
1038
 
 
1039
   /* Note that drmOpen will try to load the kernel module, if needed. */
 
1040
   ctx->drmFD = drmOpen("i915", NULL );
 
1041
   if (ctx->drmFD < 0) {
 
1042
      fprintf(stderr, "[drm] drmOpen failed\n");
 
1043
      return 0;
 
1044
   }
 
1045
 
 
1046
   if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
 
1047
      fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
 
1048
              ctx->drmFD, ctx->pciBusID, strerror(-err));
 
1049
      return 0;
 
1050
   }
 
1051
 
 
1052
   if (drmAddMap( ctx->drmFD,
 
1053
                  0,
 
1054
                  ctx->shared.SAREASize,
 
1055
                  DRM_SHM,
 
1056
                  DRM_CONTAINS_LOCK,
 
1057
                  &ctx->shared.hSAREA) < 0)
 
1058
   {
 
1059
     fprintf(stderr, "[drm] drmAddMap failed\n");
 
1060
     return 0;
 
1061
   }
 
1062
 
 
1063
   fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
 
1064
           ctx->shared.SAREASize, ctx->shared.hSAREA);
 
1065
   
 
1066
   if (drmMap( ctx->drmFD,
 
1067
               ctx->shared.hSAREA,
 
1068
               ctx->shared.SAREASize,
 
1069
               (drmAddressPtr)(&ctx->pSAREA)) < 0)
 
1070
   {
 
1071
      fprintf(stderr, "[drm] drmMap failed\n");
 
1072
      return 0;
 
1073
   
 
1074
   }
 
1075
   
 
1076
   memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
 
1077
   fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n",
 
1078
           ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
 
1079
   
 
1080
 
 
1081
   if (drmAddMap(ctx->drmFD, 
 
1082
                 ctx->MMIOStart,
 
1083
                 ctx->MMIOSize,
 
1084
                 DRM_REGISTERS, 
 
1085
                 DRM_READ_ONLY, 
 
1086
                 &pI830->registerHandle) < 0) {
 
1087
      fprintf(stderr, "[drm] drmAddMap mmio failed\n"); 
 
1088
      return 0;
 
1089
   }
 
1090
   fprintf(stderr,
 
1091
           "[drm] register handle = 0x%08x\n", pI830->registerHandle);
 
1092
 
 
1093
 
 
1094
   if (!I830CheckDRMVersion(ctx, pI830)) {
 
1095
     return FALSE;
 
1096
   }
 
1097
 
 
1098
   /* Create a 'server' context so we can grab the lock for
 
1099
    * initialization ioctls.
 
1100
    */
 
1101
   if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
 
1102
      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
 
1103
      return 0;
 
1104
   }
 
1105
 
 
1106
   DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); 
 
1107
 
 
1108
   /* Initialize the SAREA private data structure */
 
1109
   pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
 
1110
                                 sizeof(drm_sarea_t));
 
1111
   memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
 
1112
 
 
1113
   pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
 
1114
   pI830->StolenMemory.Start = 0;
 
1115
   pI830->StolenMemory.End = pI830->StolenMemory.Size;
 
1116
 
 
1117
   pI830->MemoryAperture.Start = pI830->StolenMemory.End;
 
1118
   pI830->MemoryAperture.End = KB(40000);
 
1119
   pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
 
1120
 
 
1121
   pI830->StolenPool.Fixed = pI830->StolenMemory;
 
1122
   pI830->StolenPool.Total = pI830->StolenMemory;
 
1123
   pI830->StolenPool.Free = pI830->StolenPool.Total;
 
1124
   pI830->FreeMemory = pI830->StolenPool.Total.Size;
 
1125
 
 
1126
   if (!AgpInit(ctx, pI830))
 
1127
     return FALSE;
 
1128
 
 
1129
   if (I830AllocateMemory(ctx, pI830) == FALSE)
 
1130
   {
 
1131
     return FALSE;
 
1132
   }
 
1133
 
 
1134
   if (I830BindMemory(ctx, pI830) == FALSE)
 
1135
   {
 
1136
     return FALSE;
 
1137
   }
 
1138
 
 
1139
   pSAREAPriv->rotated_offset = -1;
 
1140
   pSAREAPriv->rotated_size = 0;
 
1141
   pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth;
 
1142
 
 
1143
   pSAREAPriv->front_offset = pI830->FrontBuffer.Start;
 
1144
   pSAREAPriv->front_size = pI830->FrontBuffer.Size;
 
1145
   pSAREAPriv->width = ctx->shared.virtualWidth;
 
1146
   pSAREAPriv->height = ctx->shared.virtualHeight;
 
1147
   pSAREAPriv->pitch = ctx->shared.virtualWidth;
 
1148
   pSAREAPriv->virtualX = ctx->shared.virtualWidth;
 
1149
   pSAREAPriv->virtualY = ctx->shared.virtualHeight;
 
1150
   pSAREAPriv->back_offset = pI830->BackBuffer.Start;
 
1151
   pSAREAPriv->back_size = pI830->BackBuffer.Size;
 
1152
   pSAREAPriv->depth_offset = pI830->DepthBuffer.Start;
 
1153
   pSAREAPriv->depth_size = pI830->DepthBuffer.Size;
 
1154
#if 0
 
1155
   pSAREAPriv->tex_offset = pI830->TexMem.Start;
 
1156
   pSAREAPriv->tex_size = pI830->TexMem.Size;
 
1157
#endif
 
1158
   pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
 
1159
 
 
1160
   ctx->driverClientMsg = malloc(sizeof(I830DRIRec));
 
1161
   ctx->driverClientMsgSize = sizeof(I830DRIRec);
 
1162
   pI830DRI = (I830DRIPtr)ctx->driverClientMsg;
 
1163
   pI830DRI->deviceID = pI830->Chipset;
 
1164
   pI830DRI->regsSize = I830_REG_SIZE;
 
1165
   pI830DRI->width = ctx->shared.virtualWidth;
 
1166
   pI830DRI->height = ctx->shared.virtualHeight;
 
1167
   pI830DRI->mem = ctx->shared.fbSize;
 
1168
   pI830DRI->cpp = ctx->cpp;
 
1169
 
 
1170
   pI830DRI->bitsPerPixel = ctx->bpp;
 
1171
   pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
 
1172
   
 
1173
   err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
 
1174
   if (err == FALSE)
 
1175
       return FALSE;
 
1176
 
 
1177
   I830SetupMemoryTiling(ctx, pI830);
 
1178
 
 
1179
   /* Quick hack to clear the front & back buffers.  Could also use
 
1180
    * the clear ioctl to do this, but would need to setup hw state
 
1181
    * first.
 
1182
    */
 
1183
   I830ClearScreen(ctx, pI830, pSAREAPriv);
 
1184
 
 
1185
   I830SetRingRegs(ctx, pI830);
 
1186
 
 
1187
   return TRUE;
 
1188
}
 
1189
 
 
1190
 
 
1191
/**
 
1192
 * \brief Validate the fbdev mode.
 
1193
 * 
 
1194
 * \param ctx display handle.
 
1195
 *
 
1196
 * \return one on success, or zero on failure.
 
1197
 *
 
1198
 * Saves some registers and returns 1.
 
1199
 *
 
1200
 * \sa radeonValidateMode().
 
1201
 */
 
1202
static int i830ValidateMode( const DRIDriverContext *ctx )
 
1203
{
 
1204
  return 1;
 
1205
}
 
1206
 
 
1207
/**
 
1208
 * \brief Examine mode returned by fbdev.
 
1209
 * 
 
1210
 * \param ctx display handle.
 
1211
 *
 
1212
 * \return one on success, or zero on failure.
 
1213
 *
 
1214
 * Restores registers that fbdev has clobbered and returns 1.
 
1215
 *
 
1216
 * \sa i810ValidateMode().
 
1217
 */
 
1218
static int i830PostValidateMode( const DRIDriverContext *ctx )
 
1219
{
 
1220
  I830Rec *pI830 = ctx->driverPrivate;
 
1221
 
 
1222
  I830SetRingRegs(ctx, pI830);
 
1223
  return 1;
 
1224
}
 
1225
 
 
1226
 
 
1227
/**
 
1228
 * \brief Initialize the framebuffer device mode
 
1229
 *
 
1230
 * \param ctx display handle.
 
1231
 *
 
1232
 * \return one on success, or zero on failure.
 
1233
 *
 
1234
 * Fills in \p info with some default values and some information from \p ctx
 
1235
 * and then calls I810ScreenInit() for the screen initialization.
 
1236
 * 
 
1237
 * Before exiting clears the framebuffer memory accessing it directly.
 
1238
 */
 
1239
static int i830InitFBDev( DRIDriverContext *ctx )
 
1240
{
 
1241
  I830Rec *pI830 = calloc(1, sizeof(I830Rec));
 
1242
  int i;
 
1243
 
 
1244
   {
 
1245
      int  dummy = ctx->shared.virtualWidth;
 
1246
 
 
1247
      switch (ctx->bpp / 8) {
 
1248
      case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
 
1249
      case 2: dummy = (ctx->shared.virtualWidth +  31) &  ~31; break;
 
1250
      case 3:
 
1251
      case 4: dummy = (ctx->shared.virtualWidth +  15) &  ~15; break;
 
1252
      }
 
1253
 
 
1254
      ctx->shared.virtualWidth = dummy;
 
1255
      ctx->shared.Width = ctx->shared.virtualWidth;
 
1256
   }
 
1257
 
 
1258
 
 
1259
   for (i = 0; pitches[i] != 0; i++) {
 
1260
     if (pitches[i] >= ctx->shared.virtualWidth) {
 
1261
       ctx->shared.virtualWidth = pitches[i];
 
1262
       break;
 
1263
     }
 
1264
   }
 
1265
 
 
1266
   ctx->driverPrivate = (void *)pI830;
 
1267
   
 
1268
   pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
 
1269
   pI830->Chipset = ctx->chipset;
 
1270
   pI830->LinearAddr = ctx->FBStart;
 
1271
 
 
1272
   if (!I830ScreenInit( ctx, pI830 ))
 
1273
      return 0;
 
1274
 
 
1275
   
 
1276
   return 1;
 
1277
}
 
1278
 
 
1279
 
 
1280
/**
 
1281
 * \brief The screen is being closed, so clean up any state and free any
 
1282
 * resources used by the DRI.
 
1283
 *
 
1284
 * \param ctx display handle.
 
1285
 *
 
1286
 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
 
1287
 * private data.
 
1288
 */
 
1289
static void i830HaltFBDev( DRIDriverContext *ctx )
 
1290
{
 
1291
  drmI830Sarea *pSAREAPriv;
 
1292
  I830Rec *pI830 = ctx->driverPrivate;
 
1293
 
 
1294
   if (pI830->irq) {
 
1295
       drmCtlUninstHandler(ctx->drmFD);
 
1296
       pI830->irq = 0;   }
 
1297
 
 
1298
   I830CleanupDma(ctx);
 
1299
 
 
1300
  pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
 
1301
                                sizeof(drm_sarea_t));
 
1302
 
 
1303
  I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
 
1304
  drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
 
1305
  drmClose(ctx->drmFD);
 
1306
  
 
1307
  if (ctx->driverPrivate) {
 
1308
    free(ctx->driverPrivate);
 
1309
    ctx->driverPrivate = 0;
 
1310
  }
 
1311
}
 
1312
 
 
1313
 
 
1314
extern void i810NotifyFocus( int );
 
1315
 
 
1316
/**
 
1317
 * \brief Exported driver interface for Mini GLX.
 
1318
 *
 
1319
 * \sa DRIDriverRec.
 
1320
 */
 
1321
const struct DRIDriverRec __driDriver = {
 
1322
   i830ValidateMode,
 
1323
   i830PostValidateMode,
 
1324
   i830InitFBDev,
 
1325
   i830HaltFBDev,
 
1326
   NULL,//I830EngineShutdown,
 
1327
   NULL, //I830EngineRestore,  
 
1328
#ifndef _EMBEDDED
 
1329
   0,
 
1330
#else
 
1331
   i810NotifyFocus, 
 
1332
#endif
 
1333
};