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,