2
* \file server/intel_dri.c
3
* \brief File to perform the device-specific initialization tasks typically
4
* done in the X server.
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.
10
* Copyright (C) 2006 Dave Airlie (airlied@linux.ie)
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:
20
The above copyright notice and this permission notice (including the
21
next paragraph) shall be included in all copies or substantial portions
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.
46
#include "pciaccess.h"
48
static size_t drm_page_size;
49
static int nextTile = 0;
50
#define xf86DrvMsg(...) do {} while(0)
52
static const int pitches[] = {
60
static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
63
GetBestTileAlignment(unsigned long size)
67
for (i = KB(512); i < size; i <<= 1)
76
static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
79
unsigned char *MMIO = ctx->MMIOAddress;
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]);
88
/* Tiled memory is good... really, really good...
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'.
96
SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
97
int nr, unsigned int start, unsigned int pitch,
101
unsigned int fence_mask = 0;
102
unsigned int fence_pitch;
104
if (nr < 0 || nr > 7) {
106
"SetFence: fence %d out of range\n",nr);
110
pI830->Fence[nr] = 0;
113
fence_mask = ~I915G_FENCE_START_MASK;
115
fence_mask = ~I830_FENCE_START_MASK;
117
if (start & fence_mask) {
119
"SetFence: %d: start (0x%08x) is not %s aligned\n",
120
nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
126
"SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
127
nr, start, size / 1024);
133
"SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
138
val = (start | FENCE_X_MAJOR | FENCE_VALID);
140
if (IS_I9XX(pI830)) {
143
val |= I915G_FENCE_SIZE_1M;
146
val |= I915G_FENCE_SIZE_2M;
149
val |= I915G_FENCE_SIZE_4M;
152
val |= I915G_FENCE_SIZE_8M;
155
val |= I915G_FENCE_SIZE_16M;
158
val |= I915G_FENCE_SIZE_32M;
161
val |= I915G_FENCE_SIZE_64M;
165
"SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
171
val |= FENCE_SIZE_512K;
174
val |= FENCE_SIZE_1M;
177
val |= FENCE_SIZE_2M;
180
val |= FENCE_SIZE_4M;
183
val |= FENCE_SIZE_8M;
186
val |= FENCE_SIZE_16M;
189
val |= FENCE_SIZE_32M;
192
val |= FENCE_SIZE_64M;
196
"SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
202
fence_pitch = pitch / 512;
204
fence_pitch = pitch / 128;
206
switch (fence_pitch) {
208
val |= FENCE_PITCH_1;
211
val |= FENCE_PITCH_2;
214
val |= FENCE_PITCH_4;
217
val |= FENCE_PITCH_8;
220
val |= FENCE_PITCH_16;
223
val |= FENCE_PITCH_32;
226
val |= FENCE_PITCH_64;
230
"SetFence: %d: illegal pitch (%d)\n", nr, pitch);
234
pI830->Fence[nr] = val;
238
MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
240
int pitch, ntiles, i;
242
pitch = pMem->Pitch * ctx->cpp;
244
* Simply try to break the region up into at most four pieces of size
245
* equal to the alignment.
247
ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
252
for (i = 0; i < ntiles; i++, nextTile++) {
253
SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
254
pitch, pMem->Alignment);
259
static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
264
for (i = 0; i < 8; i++)
269
if (pI830->BackBuffer.Alignment >= KB(512)) {
270
if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
272
"Activating tiled memory for the back buffer.\n");
275
"MakeTiles failed for the back buffer.\n");
276
pI830->allowPageFlip = FALSE;
280
if (pI830->DepthBuffer.Alignment >= KB(512)) {
281
if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
283
"Activating tiled memory for the depth buffer.\n");
286
"MakeTiles failed for the depth buffer.\n");
293
static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
295
struct pci_device host_bridge, ig_dev;
300
uint32_t membase2 = 0;
302
memset(&host_bridge, 0, sizeof(host_bridge));
303
memset(&ig_dev, 0, sizeof(ig_dev));
307
pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL);
309
if (IS_I830(pI830) || IS_845G(pI830)) {
310
if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
311
aper_size = 0x80000000;
313
aper_size = 0x40000000;
316
if (IS_I9XX(pI830)) {
318
ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18);
319
if (membase2 & 0x08000000)
320
aper_size = 0x8000000;
322
aper_size = 0x10000000;
324
fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret);
326
aper_size = 0x8000000;
329
pI830->aper_size = aper_size;
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;
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);
341
case I855_GMCH_GMS_STOLEN_4M:
342
memsize = MB(4) - KB(range);
344
case I855_GMCH_GMS_STOLEN_8M:
345
memsize = MB(8) - KB(range);
347
case I855_GMCH_GMS_STOLEN_16M:
348
memsize = MB(16) - KB(range);
350
case I855_GMCH_GMS_STOLEN_32M:
351
memsize = MB(32) - KB(range);
353
case I915G_GMCH_GMS_STOLEN_48M:
355
memsize = MB(48) - KB(range);
357
case I915G_GMCH_GMS_STOLEN_64M:
359
memsize = MB(64) - KB(range);
363
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
364
case I830_GMCH_GMS_STOLEN_512:
365
memsize = KB(512) - KB(range);
367
case I830_GMCH_GMS_STOLEN_1024:
368
memsize = MB(1) - KB(range);
370
case I830_GMCH_GMS_STOLEN_8192:
371
memsize = MB(8) - KB(range);
373
case I830_GMCH_GMS_LOCAL:
375
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
376
"Local memory found, but won't be used.\n");
382
"detected %d kB stolen memory.\n", memsize / 1024);
385
"no video memory detected.\n");
390
static int AgpInit(const DRIDriverContext *ctx, I830Rec *info)
392
unsigned long mode = 0x4;
394
if (drmAgpAcquire(ctx->drmFD) < 0) {
395
fprintf(stderr, "[gart] AGP not available\n");
399
if (drmAgpEnable(ctx->drmFD, mode) < 0) {
400
fprintf(stderr, "[gart] AGP not enabled\n");
401
drmAgpRelease(ctx->drmFD);
405
fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);
411
* Allocate memory from the given pool. Grow the pool if needed and if
415
AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830,
416
I830MemRange *result, I830MemPool *pool,
417
long size, unsigned long alignment, int flags)
419
long needed, start, end;
421
if (!result || !pool || !size)
424
/* Calculate how much space is needed. */
425
if (alignment <= GTT_PAGE_SIZE)
428
start = ROUND_TO(pool->Free.Start, alignment);
429
end = ROUND_TO(start + size, alignment);
430
needed = end - pool->Free.Start;
432
if (needed > pool->Free.Size) {
436
result->Start = ROUND_TO(pool->Free.Start, alignment);
437
pool->Free.Start += needed;
438
result->End = pool->Free.Start;
440
pool->Free.Size = pool->Free.End - pool->Free.Start;
441
result->Size = result->End - result->Start;
443
result->Alignment = alignment;
447
static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result)
449
unsigned long start, end;
450
unsigned long newApStart, newApEnd;
452
if (!result || !size)
458
start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
459
end = ROUND_TO(start + size, alignment);
461
newApEnd = pI830->MemoryAperture.End;
463
ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key));
467
fprintf(stderr,"drmAgpAlloc failed %d\n", ret);
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;
478
result->Offset = start;
479
result->Alignment = alignment;
486
I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags)
493
/* Make sure these are initialised. */
501
if (pool->Free.Size < size)
502
return AllocFromAGP(ctx, pI830, size, alignment, result);
505
ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
508
return AllocFromAGP(ctx, pI830, size, alignment, result);
513
static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
521
return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
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,
532
I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
534
unsigned long size, ret;
535
unsigned long lines, lineSize, align;
537
/* allocate ring buffer */
538
memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
539
pI830->LpRing->mem.Key = -1;
541
size = PRIMARY_RINGBUFFER_SIZE;
543
ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
547
fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
551
pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
554
/* allocate front buffer */
555
memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
556
pI830->FrontBuffer.Key = -1;
557
pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
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);
566
align = GetBestTileAlignment(size);
568
ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
571
fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
575
memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
576
pI830->BackBuffer.Key = -1;
577
pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
579
ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
582
fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
586
memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
587
pI830->DepthBuffer.Key = -1;
588
pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
590
ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
593
fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
597
memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
598
pI830->ContextMem.Key = -1;
601
ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
604
fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
609
memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
610
pI830->TexMem.Key = -1;
613
ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
616
fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
625
I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
627
if (!BindAgpRange(ctx, &pI830->LpRing->mem))
629
if (!BindAgpRange(ctx, &pI830->FrontBuffer))
631
if (!BindAgpRange(ctx, &pI830->BackBuffer))
633
if (!BindAgpRange(ctx, &pI830->DepthBuffer))
635
if (!BindAgpRange(ctx, &pI830->ContextMem))
638
if (!BindAgpRange(ctx, &pI830->TexMem))
644
static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830)
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;
649
fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize);
650
if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) {
652
"DRM MM Initialization Failed\n");
655
"DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart);
661
I830CleanupDma(const DRIDriverContext *ctx)
665
memset(&info, 0, sizeof(drmI830Init));
666
info.func = I830_CLEANUP_DMA;
668
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
669
&info, sizeof(drmI830Init))) {
670
fprintf(stderr, "I830 Dma Cleanup Failed\n");
678
I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
680
I830RingBuffer *ring = pI830->LpRing;
683
memset(&info, 0, sizeof(drmI830Init));
684
info.func = I830_INIT_DMA;
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;
690
info.mmio_offset = (unsigned int)ctx->MMIOStart;
692
info.sarea_priv_offset = sizeof(drm_sarea_t);
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;
704
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
705
&info, sizeof(drmI830Init))) {
707
"I830 Dma Initialization Failed\n");
714
static int I830CheckDRMVersion( const DRIDriverContext *ctx,
717
drmVersionPtr version;
719
version = drmGetVersion(ctx->drmFD);
722
int req_minor, req_patch;
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 */
733
"[dri] I830DRIScreenInit failed because of a version "
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,
743
drmFreeVersion(version);
747
pI830->drmMinor = version->version_minor;
748
drmFreeVersion(version);
754
I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
757
unsigned char *MMIO = ctx->MMIOAddress;
759
OUTREG(LP_RING + RING_LEN, 0);
760
OUTREG(LP_RING + RING_TAIL, 0);
761
OUTREG(LP_RING + RING_HEAD, 0);
763
if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
764
pI830->LpRing->mem.Start) {
766
"I830SetRingRegs: Ring buffer start (%lx) violates its "
767
"mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
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);
773
if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
774
pI830->LpRing->mem.Size - 4096) {
776
"I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
777
"mask (%x)\n", pI830->LpRing->mem.Size - 4096,
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);
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;
791
SetFenceRegs(ctx, pI830);
793
/* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
795
OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
800
I830SetParam(const DRIDriverContext *ctx, int param, int value)
804
memset(&sp, 0, sizeof(sp));
808
if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
809
fprintf(stderr, "I830 SetParam Failed\n");
817
I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
820
"[drm] Mapping front buffer\n");
822
if (drmAddMap(ctx->drmFD,
823
(drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
825
DRM_FRAME_BUFFER, /*DRM_AGP,*/
827
&sarea->front_handle) < 0) {
829
"[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
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);
837
if (drmAddMap(ctx->drmFD,
838
(drm_handle_t)(sarea->back_offset),
839
sarea->back_size, DRM_AGP, 0,
840
&sarea->back_handle) < 0) {
842
"[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
845
fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
848
if (drmAddMap(ctx->drmFD,
849
(drm_handle_t)sarea->depth_offset,
850
sarea->depth_size, DRM_AGP, 0,
851
&sarea->depth_handle) < 0) {
853
"[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
856
fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
857
sarea->depth_handle);
860
if (drmAddMap(ctx->drmFD,
861
(drm_handle_t)sarea->tex_offset,
862
sarea->tex_size, DRM_AGP, 0,
863
&sarea->tex_handle) < 0) {
865
"[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
868
fprintf(stderr, "[drm] textures = 0x%08x\n",
876
I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
879
if (sarea->front_handle) {
880
drmRmMap(ctx->drmFD, sarea->front_handle);
881
sarea->front_handle = 0;
884
if (sarea->back_handle) {
885
drmRmMap(ctx->drmFD, sarea->back_handle);
886
sarea->back_handle = 0;
888
if (sarea->depth_handle) {
889
drmRmMap(ctx->drmFD, sarea->depth_handle);
890
sarea->depth_handle = 0;
892
if (sarea->tex_handle) {
893
drmRmMap(ctx->drmFD, sarea->tex_handle);
894
sarea->tex_handle = 0;
900
I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
902
/* Start up the simple memory manager for agp space */
903
drmI830MemInitHeap drmHeap;
904
drmHeap.region = I830_MEM_REGION_AGP;
906
drmHeap.size = sarea->tex_size;
908
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
909
&drmHeap, sizeof(drmHeap))) {
911
"[drm] Failed to initialized agp heap manager\n");
914
"[drm] Initialized kernel agp heap manager, %d\n",
917
I830SetParam(ctx, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY,
918
sarea->log_tex_granularity);
924
I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
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) {
931
"[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
934
fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
937
if (I830InitDma(ctx, pI830) == FALSE) {
941
/* init to zero to be safe */
943
I830DRIMapScreenRegions(ctx, pI830, sarea);
944
SetupDRIMM(ctx, pI830);
947
I830InitTextureHeap(ctx, pI830, sarea);
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 );
954
/* Okay now initialize the dma engine */
956
pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
961
if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
963
"[drm] failure adding irq handler\n");
969
"[drm] dma control initialized, using IRQ %d\n",
973
fprintf(stderr, "[dri] visual configs initialized\n");
979
I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
981
/* need to drmMap front and back buffers and zero them */
985
ret = drmMap(ctx->drmFD,
992
fprintf(stderr, "Unable to map front buffer\n");
996
drimemsetio((char *)map_addr,
999
drmUnmap(map_addr, sarea->front_size);
1002
ret = drmMap(ctx->drmFD,
1009
fprintf(stderr, "Unable to map back buffer\n");
1013
drimemsetio((char *)map_addr,
1016
drmUnmap(map_addr, sarea->back_size);
1022
I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
1025
I830DRIPtr pI830DRI;
1026
drmI830Sarea *pSAREAPriv;
1029
drm_page_size = getpagesize();
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.
1037
ctx->shared.SAREASize = SAREA_MAX;
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");
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));
1052
if (drmAddMap( ctx->drmFD,
1054
ctx->shared.SAREASize,
1057
&ctx->shared.hSAREA) < 0)
1059
fprintf(stderr, "[drm] drmAddMap failed\n");
1063
fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
1064
ctx->shared.SAREASize, ctx->shared.hSAREA);
1066
if (drmMap( ctx->drmFD,
1068
ctx->shared.SAREASize,
1069
(drmAddressPtr)(&ctx->pSAREA)) < 0)
1071
fprintf(stderr, "[drm] drmMap failed\n");
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);
1081
if (drmAddMap(ctx->drmFD,
1086
&pI830->registerHandle) < 0) {
1087
fprintf(stderr, "[drm] drmAddMap mmio failed\n");
1091
"[drm] register handle = 0x%08x\n", pI830->registerHandle);
1094
if (!I830CheckDRMVersion(ctx, pI830)) {
1098
/* Create a 'server' context so we can grab the lock for
1099
* initialization ioctls.
1101
if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
1102
fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
1106
DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
1108
/* Initialize the SAREA private data structure */
1109
pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
1110
sizeof(drm_sarea_t));
1111
memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
1113
pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
1114
pI830->StolenMemory.Start = 0;
1115
pI830->StolenMemory.End = pI830->StolenMemory.Size;
1117
pI830->MemoryAperture.Start = pI830->StolenMemory.End;
1118
pI830->MemoryAperture.End = KB(40000);
1119
pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
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;
1126
if (!AgpInit(ctx, pI830))
1129
if (I830AllocateMemory(ctx, pI830) == FALSE)
1134
if (I830BindMemory(ctx, pI830) == FALSE)
1139
pSAREAPriv->rotated_offset = -1;
1140
pSAREAPriv->rotated_size = 0;
1141
pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth;
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;
1155
pSAREAPriv->tex_offset = pI830->TexMem.Start;
1156
pSAREAPriv->tex_size = pI830->TexMem.Size;
1158
pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
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;
1170
pI830DRI->bitsPerPixel = ctx->bpp;
1171
pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
1173
err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
1177
I830SetupMemoryTiling(ctx, pI830);
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
1183
I830ClearScreen(ctx, pI830, pSAREAPriv);
1185
I830SetRingRegs(ctx, pI830);
1192
* \brief Validate the fbdev mode.
1194
* \param ctx display handle.
1196
* \return one on success, or zero on failure.
1198
* Saves some registers and returns 1.
1200
* \sa radeonValidateMode().
1202
static int i830ValidateMode( const DRIDriverContext *ctx )
1208
* \brief Examine mode returned by fbdev.
1210
* \param ctx display handle.
1212
* \return one on success, or zero on failure.
1214
* Restores registers that fbdev has clobbered and returns 1.
1216
* \sa i810ValidateMode().
1218
static int i830PostValidateMode( const DRIDriverContext *ctx )
1220
I830Rec *pI830 = ctx->driverPrivate;
1222
I830SetRingRegs(ctx, pI830);
1228
* \brief Initialize the framebuffer device mode
1230
* \param ctx display handle.
1232
* \return one on success, or zero on failure.
1234
* Fills in \p info with some default values and some information from \p ctx
1235
* and then calls I810ScreenInit() for the screen initialization.
1237
* Before exiting clears the framebuffer memory accessing it directly.
1239
static int i830InitFBDev( DRIDriverContext *ctx )
1241
I830Rec *pI830 = calloc(1, sizeof(I830Rec));
1245
int dummy = ctx->shared.virtualWidth;
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;
1251
case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
1254
ctx->shared.virtualWidth = dummy;
1255
ctx->shared.Width = ctx->shared.virtualWidth;
1259
for (i = 0; pitches[i] != 0; i++) {
1260
if (pitches[i] >= ctx->shared.virtualWidth) {
1261
ctx->shared.virtualWidth = pitches[i];
1266
ctx->driverPrivate = (void *)pI830;
1268
pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
1269
pI830->Chipset = ctx->chipset;
1270
pI830->LinearAddr = ctx->FBStart;
1272
if (!I830ScreenInit( ctx, pI830 ))
1281
* \brief The screen is being closed, so clean up any state and free any
1282
* resources used by the DRI.
1284
* \param ctx display handle.
1286
* Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1289
static void i830HaltFBDev( DRIDriverContext *ctx )
1291
drmI830Sarea *pSAREAPriv;
1292
I830Rec *pI830 = ctx->driverPrivate;
1295
drmCtlUninstHandler(ctx->drmFD);
1298
I830CleanupDma(ctx);
1300
pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
1301
sizeof(drm_sarea_t));
1303
I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
1304
drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
1305
drmClose(ctx->drmFD);
1307
if (ctx->driverPrivate) {
1308
free(ctx->driverPrivate);
1309
ctx->driverPrivate = 0;
1314
extern void i810NotifyFocus( int );
1317
* \brief Exported driver interface for Mini GLX.
1321
const struct DRIDriverRec __driDriver = {
1323
i830PostValidateMode,
1326
NULL,//I830EngineShutdown,
1327
NULL, //I830EngineRestore,