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,
487
I830MemRange *result, I830MemPool *pool, long size,
488
unsigned long alignment, int flags)
495
/* Make sure these are initialised. */
503
if (pool->Free.Size < size) {
504
ret = AllocFromAGP(ctx, pI830, size, alignment, result);
507
ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
509
ret = AllocFromAGP(ctx, pI830, size, alignment, result);
514
static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
522
return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
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,
533
I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
535
unsigned long size, ret;
536
unsigned long lines, lineSize, align;
538
/* allocate ring buffer */
539
memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
540
pI830->LpRing->mem.Key = -1;
542
size = PRIMARY_RINGBUFFER_SIZE;
544
ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
548
fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
552
pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
555
/* allocate front buffer */
556
memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
557
pI830->FrontBuffer.Key = -1;
558
pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
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);
567
align = GetBestTileAlignment(size);
569
ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
572
fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
576
memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
577
pI830->BackBuffer.Key = -1;
578
pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
580
ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
583
fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
587
memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
588
pI830->DepthBuffer.Key = -1;
589
pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
591
ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
594
fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
598
memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
599
pI830->ContextMem.Key = -1;
602
ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
605
fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
610
memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
611
pI830->TexMem.Key = -1;
614
ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
617
fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
626
I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
628
if (!BindAgpRange(ctx, &pI830->LpRing->mem))
630
if (!BindAgpRange(ctx, &pI830->FrontBuffer))
632
if (!BindAgpRange(ctx, &pI830->BackBuffer))
634
if (!BindAgpRange(ctx, &pI830->DepthBuffer))
636
if (!BindAgpRange(ctx, &pI830->ContextMem))
639
if (!BindAgpRange(ctx, &pI830->TexMem))
645
static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830)
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;
650
fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize);
651
if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) {
653
"DRM MM Initialization Failed\n");
656
"DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart);
662
I830CleanupDma(const DRIDriverContext *ctx)
666
memset(&info, 0, sizeof(drmI830Init));
667
info.func = I830_CLEANUP_DMA;
669
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
670
&info, sizeof(drmI830Init))) {
671
fprintf(stderr, "I830 Dma Cleanup Failed\n");
679
I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
681
I830RingBuffer *ring = pI830->LpRing;
684
memset(&info, 0, sizeof(drmI830Init));
685
info.func = I830_INIT_DMA;
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;
691
info.mmio_offset = (unsigned int)ctx->MMIOStart;
693
info.sarea_priv_offset = sizeof(drm_sarea_t);
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;
705
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
706
&info, sizeof(drmI830Init))) {
708
"I830 Dma Initialization Failed\n");
715
static int I830CheckDRMVersion( const DRIDriverContext *ctx,
718
drmVersionPtr version;
720
version = drmGetVersion(ctx->drmFD);
723
int req_minor, req_patch;
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 */
734
"[dri] I830DRIScreenInit failed because of a version "
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,
744
drmFreeVersion(version);
748
pI830->drmMinor = version->version_minor;
749
drmFreeVersion(version);
755
I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
758
unsigned char *MMIO = ctx->MMIOAddress;
760
OUTREG(LP_RING + RING_LEN, 0);
761
OUTREG(LP_RING + RING_TAIL, 0);
762
OUTREG(LP_RING + RING_HEAD, 0);
764
if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
765
pI830->LpRing->mem.Start) {
767
"I830SetRingRegs: Ring buffer start (%lx) violates its "
768
"mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
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);
774
if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
775
pI830->LpRing->mem.Size - 4096) {
777
"I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
778
"mask (%x)\n", pI830->LpRing->mem.Size - 4096,
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);
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;
792
SetFenceRegs(ctx, pI830);
794
/* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
796
OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
801
I830SetParam(const DRIDriverContext *ctx, int param, int value)
805
memset(&sp, 0, sizeof(sp));
809
if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
810
fprintf(stderr, "I830 SetParam Failed\n");
818
I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
821
"[drm] Mapping front buffer\n");
823
if (drmAddMap(ctx->drmFD,
824
(drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
826
DRM_FRAME_BUFFER, /*DRM_AGP,*/
828
&sarea->front_handle) < 0) {
830
"[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
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);
838
if (drmAddMap(ctx->drmFD,
839
(drm_handle_t)(sarea->back_offset),
840
sarea->back_size, DRM_AGP, 0,
841
&sarea->back_handle) < 0) {
843
"[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
846
fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
849
if (drmAddMap(ctx->drmFD,
850
(drm_handle_t)sarea->depth_offset,
851
sarea->depth_size, DRM_AGP, 0,
852
&sarea->depth_handle) < 0) {
854
"[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
857
fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
858
sarea->depth_handle);
861
if (drmAddMap(ctx->drmFD,
862
(drm_handle_t)sarea->tex_offset,
863
sarea->tex_size, DRM_AGP, 0,
864
&sarea->tex_handle) < 0) {
866
"[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
869
fprintf(stderr, "[drm] textures = 0x%08x\n",
877
I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
880
if (sarea->front_handle) {
881
drmRmMap(ctx->drmFD, sarea->front_handle);
882
sarea->front_handle = 0;
885
if (sarea->back_handle) {
886
drmRmMap(ctx->drmFD, sarea->back_handle);
887
sarea->back_handle = 0;
889
if (sarea->depth_handle) {
890
drmRmMap(ctx->drmFD, sarea->depth_handle);
891
sarea->depth_handle = 0;
893
if (sarea->tex_handle) {
894
drmRmMap(ctx->drmFD, sarea->tex_handle);
895
sarea->tex_handle = 0;
900
I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
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) {
907
"[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
910
fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
913
if (I830InitDma(ctx, pI830) == FALSE) {
917
/* init to zero to be safe */
919
I830DRIMapScreenRegions(ctx, pI830, sarea);
920
SetupDRIMM(ctx, pI830);
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 );
927
/* Okay now initialize the dma engine */
929
pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
934
if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
936
"[drm] failure adding irq handler\n");
942
"[drm] dma control initialized, using IRQ %d\n",
946
fprintf(stderr, "[dri] visual configs initialized\n");
952
I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
954
/* need to drmMap front and back buffers and zero them */
958
ret = drmMap(ctx->drmFD,
965
fprintf(stderr, "Unable to map front buffer\n");
969
drimemsetio((char *)map_addr,
972
drmUnmap(map_addr, sarea->front_size);
975
ret = drmMap(ctx->drmFD,
982
fprintf(stderr, "Unable to map back buffer\n");
986
drimemsetio((char *)map_addr,
989
drmUnmap(map_addr, sarea->back_size);
995
I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
999
drmI830Sarea *pSAREAPriv;
1002
drm_page_size = getpagesize();
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.
1010
ctx->shared.SAREASize = SAREA_MAX;
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");
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));
1025
if (drmAddMap( ctx->drmFD,
1027
ctx->shared.SAREASize,
1030
&ctx->shared.hSAREA) < 0)
1032
fprintf(stderr, "[drm] drmAddMap failed\n");
1036
fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
1037
ctx->shared.SAREASize, ctx->shared.hSAREA);
1039
if (drmMap( ctx->drmFD,
1041
ctx->shared.SAREASize,
1042
(drmAddressPtr)(&ctx->pSAREA)) < 0)
1044
fprintf(stderr, "[drm] drmMap failed\n");
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);
1054
if (drmAddMap(ctx->drmFD,
1059
&pI830->registerHandle) < 0) {
1060
fprintf(stderr, "[drm] drmAddMap mmio failed\n");
1064
"[drm] register handle = 0x%08x\n", pI830->registerHandle);
1067
if (!I830CheckDRMVersion(ctx, pI830)) {
1071
/* Create a 'server' context so we can grab the lock for
1072
* initialization ioctls.
1074
if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
1075
fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
1079
DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
1081
/* Initialize the SAREA private data structure */
1082
pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
1083
sizeof(drm_sarea_t));
1084
memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
1086
pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
1087
pI830->StolenMemory.Start = 0;
1088
pI830->StolenMemory.End = pI830->StolenMemory.Size;
1090
pI830->MemoryAperture.Start = pI830->StolenMemory.End;
1091
pI830->MemoryAperture.End = KB(40000);
1092
pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
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;
1099
if (!AgpInit(ctx, pI830))
1102
if (I830AllocateMemory(ctx, pI830) == FALSE)
1107
if (I830BindMemory(ctx, pI830) == FALSE)
1112
pSAREAPriv->rotated_offset = -1;
1113
pSAREAPriv->rotated_size = 0;
1114
pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth;
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;
1128
pSAREAPriv->tex_offset = pI830->TexMem.Start;
1129
pSAREAPriv->tex_size = pI830->TexMem.Size;
1131
pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
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;
1143
pI830DRI->bitsPerPixel = ctx->bpp;
1144
pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
1146
err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
1150
I830SetupMemoryTiling(ctx, pI830);
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
1156
I830ClearScreen(ctx, pI830, pSAREAPriv);
1158
I830SetRingRegs(ctx, pI830);
1165
* \brief Validate the fbdev mode.
1167
* \param ctx display handle.
1169
* \return one on success, or zero on failure.
1171
* Saves some registers and returns 1.
1173
* \sa radeonValidateMode().
1175
static int i830ValidateMode( const DRIDriverContext *ctx )
1181
* \brief Examine mode returned by fbdev.
1183
* \param ctx display handle.
1185
* \return one on success, or zero on failure.
1187
* Restores registers that fbdev has clobbered and returns 1.
1189
* \sa i810ValidateMode().
1191
static int i830PostValidateMode( const DRIDriverContext *ctx )
1193
I830Rec *pI830 = ctx->driverPrivate;
1195
I830SetRingRegs(ctx, pI830);
1201
* \brief Initialize the framebuffer device mode
1203
* \param ctx display handle.
1205
* \return one on success, or zero on failure.
1207
* Fills in \p info with some default values and some information from \p ctx
1208
* and then calls I810ScreenInit() for the screen initialization.
1210
* Before exiting clears the framebuffer memory accessing it directly.
1212
static int i830InitFBDev( DRIDriverContext *ctx )
1214
I830Rec *pI830 = calloc(1, sizeof(I830Rec));
1218
int dummy = ctx->shared.virtualWidth;
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;
1224
case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
1227
ctx->shared.virtualWidth = dummy;
1228
ctx->shared.Width = ctx->shared.virtualWidth;
1232
for (i = 0; pitches[i] != 0; i++) {
1233
if (pitches[i] >= ctx->shared.virtualWidth) {
1234
ctx->shared.virtualWidth = pitches[i];
1239
ctx->driverPrivate = (void *)pI830;
1241
pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
1242
pI830->Chipset = ctx->chipset;
1243
pI830->LinearAddr = ctx->FBStart;
1245
if (!I830ScreenInit( ctx, pI830 ))
1254
* \brief The screen is being closed, so clean up any state and free any
1255
* resources used by the DRI.
1257
* \param ctx display handle.
1259
* Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1262
static void i830HaltFBDev( DRIDriverContext *ctx )
1264
drmI830Sarea *pSAREAPriv;
1265
I830Rec *pI830 = ctx->driverPrivate;
1268
drmCtlUninstHandler(ctx->drmFD);
1271
I830CleanupDma(ctx);
1273
pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
1274
sizeof(drm_sarea_t));
1276
I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
1277
drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
1278
drmClose(ctx->drmFD);
1280
if (ctx->driverPrivate) {
1281
free(ctx->driverPrivate);
1282
ctx->driverPrivate = 0;
1287
extern void i810NotifyFocus( int );
1290
* \brief Exported driver interface for Mini GLX.
1294
const struct DRIDriverRec __driDriver = {
1296
i830PostValidateMode,
1299
NULL,//I830EngineShutdown,
1300
NULL, //I830EngineRestore,