2 * \file server/i810_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) 2004 Dave Airlie (airlied@linux.ie)
27 /* HACK - for now, put this here... */
28 /* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
29 #if defined(__alpha__)
30 # define DRM_PAGE_SIZE 8192
31 #elif defined(__ia64__)
32 # define DRM_PAGE_SIZE getpagesize()
34 # define DRM_PAGE_SIZE 4096
37 static int i810_pitches
[] = {
45 static int i810_pitch_flags
[] = {
53 static unsigned int i810_drm_version
= 0;
56 I810AllocLow(I810MemRange
* result
, I810MemRange
* pool
, int size
)
58 if (size
> pool
->Size
)
63 result
->Start
= pool
->Start
;
64 result
->End
= pool
->Start
+= size
;
70 I810AllocHigh(I810MemRange
* result
, I810MemRange
* pool
, int size
)
72 if (size
> pool
->Size
)
77 result
->End
= pool
->End
;
78 result
->Start
= pool
->End
-= size
;
85 * \brief Wait for free FIFO entries.
87 * \param ctx display handle.
88 * \param entries number of free entries to wait.
90 * It polls the free entries from the chip until it reaches the requested value
91 * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out.
93 static void I810WaitForFifo( const DRIDriverContext
*ctx
,
99 * \brief Reset graphics card to known state.
101 * \param ctx display handle.
103 * Resets the values of several I810 registers.
105 static void I810EngineReset( const DRIDriverContext
*ctx
)
107 unsigned char *I810MMIO
= ctx
->MMIOAddress
;
111 * \brief Restore the drawing engine.
113 * \param ctx display handle
115 * Resets the graphics card and sets initial values for several registers of
116 * the card's drawing engine.
118 * Turns on the i810 command processor engine (i.e., the ringbuffer).
120 static int I810EngineRestore( const DRIDriverContext
*ctx
)
122 I810Ptr info
= ctx
->driverPrivate
;
123 unsigned char *I810MMIO
= ctx
->MMIOAddress
;
125 fprintf(stderr
, "%s\n", __FUNCTION__
);
132 * \brief Shutdown the drawing engine.
134 * \param ctx display handle
136 * Turns off the command processor engine & restores the graphics card
137 * to a state that fbdev understands.
139 static int I810EngineShutdown( const DRIDriverContext
*ctx
)
144 memset(&info
, 0, sizeof(drmI810Init
));
145 info
.func
= I810_CLEANUP_DMA
;
147 ret
= drmCommandWrite(ctx
->drmFD
, DRM_I810_INIT
, &info
, sizeof(drmI810Init
));
150 fprintf(stderr
,"[dri] I810 DMA Cleanup failed\n");
157 * \brief Compute base 2 logarithm.
161 * \return base 2 logarithm of \p val.
163 static int I810MinBits(int val
)
168 for (bits
= 0; val
; val
>>= 1, ++bits
);
172 static int I810DRIAgpPreInit( const DRIDriverContext
*ctx
, I810Ptr info
)
175 if (drmAgpAcquire(ctx
->drmFD
) < 0) {
176 fprintf(stderr
, "[gart] AGP not available\n");
181 if (drmAgpEnable(ctx
->drmFD
, 0) < 0) {
182 fprintf(stderr
, "[gart] AGP not enabled\n");
183 drmAgpRelease(ctx
->drmFD
);
189 * \brief Initialize the AGP state
191 * \param ctx display handle.
192 * \param info driver private data.
194 * \return one on success, or zero on failure.
196 * Acquires and enables the AGP device. Reserves memory in the AGP space for
197 * the ring buffer, vertex buffers and textures. Initialize the I810
198 * registers to point to that memory and add client mappings.
200 static int I810DRIAgpInit( const DRIDriverContext
*ctx
, I810Ptr info
)
202 unsigned char *I810MMIO
= ctx
->MMIOAddress
;
205 unsigned long dcacheHandle
;
206 unsigned long agpHandle
;
210 int width
= ctx
->shared
.virtualWidth
* ctx
->cpp
;
213 info
->backHandle
= DRM_AGP_NO_HANDLE
;
214 info
->zHandle
= DRM_AGP_NO_HANDLE
;
215 info
->sysmemHandle
= DRM_AGP_NO_HANDLE
;
216 info
->dcacheHandle
= DRM_AGP_NO_HANDLE
;
218 memset(&info
->DcacheMem
, 0, sizeof(I810MemRange
));
219 memset(&info
->BackBuffer
, 0, sizeof(I810MemRange
));
220 memset(&info
->DepthBuffer
, 0, sizeof(I810MemRange
));
222 drmAgpAlloc(ctx
->drmFD
, 4096 * 1024, 1, NULL
, &dcacheHandle
);
223 info
->dcacheHandle
= dcacheHandle
;
225 fprintf(stderr
, "[agp] dcacheHandle : %p\n", dcacheHandle
);
227 #define Elements(x) sizeof(x)/sizeof(*x)
228 for (pitch_idx
= 0; pitch_idx
< Elements(i810_pitches
); pitch_idx
++)
229 if (width
<= i810_pitches
[pitch_idx
])
232 if (pitch_idx
== Elements(i810_pitches
)) {
233 fprintf(stderr
,"[dri] Couldn't find depth/back buffer pitch\n");
238 int lines
= (ctx
->shared
.virtualWidth
+ 15) / 16 * 16;
239 back_size
= i810_pitches
[pitch_idx
] * lines
;
240 back_size
= ((back_size
+ 4096 - 1) / 4096) * 4096;
243 sysmem_size
= ctx
->shared
.fbSize
;
244 fprintf(stderr
,"sysmem_size is %lu back_size is %lu\n", sysmem_size
, back_size
);
245 if (dcacheHandle
!= DRM_AGP_NO_HANDLE
) {
246 if (back_size
> 4 * 1024 * 1024) {
247 fprintf(stderr
,"[dri] Backsize is larger then 4 meg\n");
248 sysmem_size
= sysmem_size
- 2 * back_size
;
249 drmAgpFree(ctx
->drmFD
, dcacheHandle
);
250 info
->dcacheHandle
= dcacheHandle
= DRM_AGP_NO_HANDLE
;
252 sysmem_size
= sysmem_size
- back_size
;
255 sysmem_size
= sysmem_size
- 2 * back_size
;
258 info
->SysMem
.Start
=0;
259 info
->SysMem
.Size
= sysmem_size
;
260 info
->SysMem
.End
= sysmem_size
;
262 if (dcacheHandle
!= DRM_AGP_NO_HANDLE
) {
263 if (drmAgpBind(ctx
->drmFD
, dcacheHandle
, info
->DepthOffset
) == 0) {
264 memset(&info
->DcacheMem
, 0, sizeof(I810MemRange
));
265 fprintf(stderr
,"[agp] GART: Found 4096K Z buffer memory\n");
266 info
->DcacheMem
.Start
= info
->DepthOffset
;
267 info
->DcacheMem
.Size
= 1024 * 4096;
268 info
->DcacheMem
.End
= info
->DcacheMem
.Start
+ info
->DcacheMem
.Size
;
270 fprintf(stderr
, "[agp] GART: dcache bind failed\n");
271 drmAgpFree(ctx
->drmFD
, dcacheHandle
);
272 info
->dcacheHandle
= dcacheHandle
= DRM_AGP_NO_HANDLE
;
275 fprintf(stderr
, "[agp] GART: no dcache memory found\n");
278 drmAgpAlloc(ctx
->drmFD
, back_size
, 0, NULL
, &agpHandle
);
279 info
->backHandle
= agpHandle
;
281 if (agpHandle
!= DRM_AGP_NO_HANDLE
) {
282 if (drmAgpBind(ctx
->drmFD
, agpHandle
, info
->BackOffset
) == 0) {
283 fprintf(stderr
, "[agp] Bound backbuffer memory\n");
285 info
->BackBuffer
.Start
= info
->BackOffset
;
286 info
->BackBuffer
.Size
= back_size
;
287 info
->BackBuffer
.End
= (info
->BackBuffer
.Start
+
288 info
->BackBuffer
.Size
);
290 fprintf(stderr
,"[agp] Unable to bind backbuffer. Disabling DRI.\n");
294 fprintf(stderr
, "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n");
298 if (dcacheHandle
== DRM_AGP_NO_HANDLE
) {
299 drmAgpAlloc(ctx
->drmFD
, back_size
, 0, NULL
, &agpHandle
);
301 info
->zHandle
= agpHandle
;
303 if (agpHandle
!= DRM_AGP_NO_HANDLE
) {
304 if (drmAgpBind(ctx
->drmFD
, agpHandle
, info
->DepthOffset
) == 0) {
305 fprintf(stderr
,"[agp] Bound depthbuffer memory\n");
306 info
->DepthBuffer
.Start
= info
->DepthOffset
;
307 info
->DepthBuffer
.Size
= back_size
;
308 info
->DepthBuffer
.End
= (info
->DepthBuffer
.Start
+
309 info
->DepthBuffer
.Size
);
311 fprintf(stderr
,"[agp] Unable to bind depthbuffer. Disabling DRI.\n");
315 fprintf(stderr
,"[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n");
320 /* Now allocate and bind the agp space. This memory will include the
321 * regular framebuffer as well as texture memory.
323 drmAgpAlloc(ctx
->drmFD
, sysmem_size
, 0, NULL
, &agpHandle
);
324 info
->sysmemHandle
= agpHandle
;
326 if (agpHandle
!= DRM_AGP_NO_HANDLE
) {
327 if (drmAgpBind(ctx
->drmFD
, agpHandle
, 0) == 0) {
328 fprintf(stderr
, "[agp] Bound System Texture Memory\n");
330 fprintf(stderr
, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
334 fprintf(stderr
, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
338 info
->auxPitch
= i810_pitches
[pitch_idx
];
339 info
->auxPitchBits
= i810_pitch_flags
[pitch_idx
];
346 * \brief Initialize the kernel data structures and enable the CP engine.
348 * \param ctx display handle.
349 * \param info driver private data.
351 * \return non-zero on success, or zero on failure.
353 * This function is a wrapper around the DRM_I810_CP_INIT command, passing
354 * all the parameters in a drmI810Init structure.
356 static int I810DRIKernelInit( const DRIDriverContext
*ctx
,
359 int cpp
= ctx
->bpp
/ 8;
362 I810RingBuffer
*ring
= &(info
->LpRing
);
364 /* This is the struct passed to the kernel module for its initialization */
365 memset(&drmInfo
, 0, sizeof(drmI810Init
));
367 /* make sure we have at least 1.4 */
368 drmInfo
.func
= I810_INIT_DMA_1_4
;
370 drmInfo
.ring_start
= ring
->mem
.Start
;
371 drmInfo
.ring_end
= ring
->mem
.End
;
372 drmInfo
.ring_size
= ring
->mem
.Size
;
374 drmInfo
.mmio_offset
= (unsigned int)info
->regs
;
375 drmInfo
.buffers_offset
= (unsigned int)info
->buffer_map
;
376 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
378 drmInfo
.front_offset
= 0;
379 drmInfo
.back_offset
= info
->BackBuffer
.Start
;
380 drmInfo
.depth_offset
= info
->DepthBuffer
.Start
;
382 drmInfo
.w
= ctx
->shared
.virtualWidth
;
383 drmInfo
.h
= ctx
->shared
.virtualHeight
;
384 drmInfo
.pitch
= info
->auxPitch
;
385 drmInfo
.pitch_bits
= info
->auxPitchBits
;
388 ret
= drmCommandWrite(ctx
->drmFD
, DRM_I810_INIT
, &drmInfo
,
389 sizeof(drmI810Init
));
396 * \brief Add a map for the vertex buffers that will be accessed by any
399 * \param ctx display handle.
400 * \param info driver private data.
402 * \return one on success, or zero on failure.
404 * Calls drmAddBufs() with the previously allocated vertex buffers.
406 static int I810DRIBufInit( const DRIDriverContext
*ctx
, I810Ptr info
)
408 /* Initialize vertex buffers */
409 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
413 info
->BufferMem
.Start
);
415 if (info
->bufNumBufs
<= 0) {
417 "[drm] Could not create vertex/indirect buffers list\n");
421 "[drm] Added %d %d byte vertex/indirect buffers\n",
422 info
->bufNumBufs
, I810_DMA_BUF_SZ
);
428 * \brief Install an IRQ handler.
430 * \param ctx display handle.
431 * \param info driver private data.
433 * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to
434 * IRQ-free operation on failure.
436 static void I810DRIIrqInit(const DRIDriverContext
*ctx
,
440 info
->irq
= drmGetInterruptFromBusID(ctx
->drmFD
,
445 if ((drmCtlInstHandler(ctx
->drmFD
, info
->irq
)) != 0) {
447 "[drm] failure adding irq handler, "
448 "there is a device already using that irq\n"
449 "[drm] falling back to irq-free operation\n");
456 "[drm] dma control initialized, using IRQ %d\n",
460 static int I810CheckDRMVersion( const DRIDriverContext
*ctx
,
463 drmVersionPtr version
;
465 version
= drmGetVersion(ctx
->drmFD
);
467 int req_minor
, req_patch
;
472 i810_drm_version
= (version
->version_major
<<16) | version
->version_minor
;
473 if (version
->version_major
!= 1 ||
474 version
->version_minor
< req_minor
||
475 (version
->version_minor
== req_minor
&&
476 version
->version_patchlevel
< req_patch
)) {
477 /* Incompatible drm version */
479 "[dri] I810DRIScreenInit failed because of a version "
481 "[dri] i810.o kernel module version is %d.%d.%d "
482 "but version 1.%d.%d or newer is needed.\n"
483 "[dri] Disabling DRI.\n",
484 version
->version_major
,
485 version
->version_minor
,
486 version
->version_patchlevel
,
489 drmFreeVersion(version
);
493 info
->drmMinor
= version
->version_minor
;
494 drmFreeVersion(version
);
500 static int I810MemoryInit( const DRIDriverContext
*ctx
, I810Ptr info
)
502 int width_bytes
= ctx
->shared
.virtualWidth
* ctx
->cpp
;
504 int bufferSize
= (ctx
->shared
.virtualHeight
* width_bytes
);
505 int depthSize
= (((ctx
->shared
.virtualHeight
+15) & ~15) * width_bytes
);
508 if (drmAddMap(ctx
->drmFD
, (drm_handle_t
) info
->BackBuffer
.Start
,
509 info
->BackBuffer
.Size
, DRM_AGP
, 0,
510 &info
->backbuffer
) < 0) {
511 fprintf(stderr
, "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
515 if (drmAddMap(ctx
->drmFD
, (drm_handle_t
) info
->DepthBuffer
.Start
,
516 info
->DepthBuffer
.Size
, DRM_AGP
, 0,
517 &info
->depthbuffer
) < 0) {
518 fprintf(stderr
, "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n");
522 if (!I810AllocLow(&(info
->FrontBuffer
), &(info
->SysMem
), (((ctx
->shared
.virtualHeight
* width_bytes
) + 4095) & ~4095)))
524 fprintf(stderr
,"Framebuffer allocation failed\n");
528 fprintf(stderr
,"Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
529 info
->FrontBuffer
.Start
,
530 info
->FrontBuffer
.Size
/ 1024, info
->FrontBuffer
.Size
);
532 memset(&(info
->LpRing
), 0, sizeof(I810RingBuffer
));
533 if (I810AllocLow(&(info
->LpRing
.mem
), &(info
->SysMem
), 16 * 4096)) {
535 "Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
536 info
->LpRing
.mem
.Start
,
537 info
->LpRing
.mem
.Size
/ 1024, info
->LpRing
.mem
.Size
);
539 info
->LpRing
.tail_mask
= info
->LpRing
.mem
.Size
- 1;
540 info
->LpRing
.virtual_start
= info
->LpRing
.mem
.Start
;
541 info
->LpRing
.head
= 0;
542 info
->LpRing
.tail
= 0;
543 info
->LpRing
.space
= 0;
545 fprintf(stderr
, "Ring buffer allocation failed\n");
549 /* Allocate buffer memory */
550 I810AllocHigh(&(info
->BufferMem
), &(info
->SysMem
),
551 I810_DMA_BUF_NR
* I810_DMA_BUF_SZ
);
554 fprintf(stderr
, "[dri] Buffer map : %lx\n",
555 info
->BufferMem
.Start
);
557 if (info
->BufferMem
.Start
== 0 ||
558 info
->BufferMem
.End
- info
->BufferMem
.Start
>
559 I810_DMA_BUF_NR
* I810_DMA_BUF_SZ
) {
560 fprintf(stderr
,"[dri] Not enough memory for dma buffers. Disabling DRI.\n");
564 if (drmAddMap(ctx
->drmFD
, (drm_handle_t
) info
->BufferMem
.Start
,
565 info
->BufferMem
.Size
, DRM_AGP
, 0, &info
->buffer_map
) < 0) {
566 fprintf(stderr
, "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n");
570 if (drmAddMap(ctx
->drmFD
, (drm_handle_t
) info
->LpRing
.mem
.Start
,
571 info
->LpRing
.mem
.Size
, DRM_AGP
, 0, &info
->ring_map
) < 0) {
572 fprintf(stderr
, "[drm] drmAddMap(ring_map) failed. Disabling DRI. \n");
576 /* Front, back and depth buffers - everything else texture??
578 info
->textureSize
= info
->SysMem
.Size
;
580 if (info
->textureSize
< 0)
584 l
= I810MinBits((info
->textureSize
-1) / I810_NR_TEX_REGIONS
);
585 if (l
< I810_LOG_MIN_TEX_REGION_SIZE
) l
= I810_LOG_MIN_TEX_REGION_SIZE
;
587 /* Round the texture size up to the nearest whole number of
588 * texture regions. Again, be greedy about this, don't
591 info
->logTextureGranularity
= l
;
592 info
->textureSize
= (info
->textureSize
>> l
) << l
;
594 /* Set a minimum usable local texture heap size. This will fit
595 * two 256x256x32bpp textures.
597 if (info
->textureSize
< 512 * 1024) {
598 info
->textureOffset
= 0;
599 info
->textureSize
= 0;
602 I810AllocLow(&(info
->TexMem
), &(info
->SysMem
), info
->textureSize
);
604 if (drmAddMap(ctx
->drmFD
, (drm_handle_t
) info
->TexMem
.Start
,
605 info
->TexMem
.Size
, DRM_AGP
, 0, &info
->textures
) < 0) {
607 "[drm] drmAddMap(textures) failed. Disabling DRI.\n");
611 /* Reserve space for textures */
613 "Will use back buffer at offset 0x%x\n",
616 "Will use depth buffer at offset 0x%x\n",
619 "Will use %d kb for textures at offset 0x%x\n",
620 info
->TexMem
.Size
/1024, info
->TexMem
.Start
);
628 * Called at the start of each server generation.
630 * \param ctx display handle.
631 * \param info driver private data.
633 * \return non-zero on success, or zero on failure.
635 * Performs static frame buffer allocation. Opens the DRM device and add maps
636 * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more
637 * information. Creates a \e server context to grab the lock for the
638 * initialization ioctls and calls the other initilization functions in this
639 * file. Starts the CP engine via the DRM_I810_CP_START command.
641 * Setups a I810DRIRec structure to be passed to i810_dri.so for its
644 static int I810ScreenInit( DRIDriverContext
*ctx
, I810Ptr info
)
650 /*assert(!ctx->IsClient);*/
652 /* from XFree86 driver */
653 info
->DepthOffset
= 0x3000000;
654 info
->BackOffset
= 0x3800000;
656 int width_bytes
= (ctx
->shared
.virtualWidth
* ctx
->cpp
);
657 int maxy
= ctx
->shared
.fbSize
/ width_bytes
;
660 if (maxy
<= ctx
->shared
.virtualHeight
* 3) {
662 "Static buffer allocation failed -- "
663 "need at least %d kB video memory (have %d kB)\n",
664 (ctx
->shared
.virtualWidth
* ctx
->shared
.virtualHeight
*
665 ctx
->cpp
* 3 + 1023) / 1024,
666 ctx
->shared
.fbSize
/ 1024);
672 info
->regsSize
= ctx
->MMIOSize
;
673 ctx
->shared
.SAREASize
= 0x2000;
675 /* Note that drmOpen will try to load the kernel module, if needed. */
676 ctx
->drmFD
= drmOpen("i810", NULL
);
677 if (ctx
->drmFD
< 0) {
678 fprintf(stderr
, "[drm] drmOpen failed\n");
682 if ((err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
)) < 0) {
683 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
684 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
688 if (drmAddMap( ctx
->drmFD
,
690 ctx
->shared
.SAREASize
,
693 &ctx
->shared
.hSAREA
) < 0)
695 fprintf(stderr
, "[drm] drmAddMap failed\n");
698 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
699 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
701 if (drmMap( ctx
->drmFD
,
703 ctx
->shared
.SAREASize
,
704 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
706 fprintf(stderr
, "[drm] drmMap failed\n");
709 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
710 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
711 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
713 if (drmAddMap(ctx
->drmFD
,
719 fprintf(stderr
, "[drm] drmAddMap mmio failed\n");
723 "[drm] register handle = 0x%08lx\n", info
->regs
);
725 I810DRIAgpPreInit(ctx
, info
);
726 /* Need to AddMap the framebuffer and mmio regions here:
728 if (drmAddMap( ctx
->drmFD
,
729 (drm_handle_t
)ctx
->FBStart
,
737 &ctx
->shared
.hFrameBuffer
) < 0)
739 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
743 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
744 ctx
->shared
.hFrameBuffer
);
746 /* Check the i810 DRM version */
747 if (!I810CheckDRMVersion(ctx
, info
)) {
752 if (!I810DRIAgpInit(ctx
, info
)) {
757 /* Memory manager setup */
758 if (!I810MemoryInit(ctx
, info
)) {
762 /* Initialize the SAREA private data structure */
764 I810SAREAPtr pSAREAPriv
;
765 pSAREAPriv
= (I810SAREAPtr
)(((char*)ctx
->pSAREA
) +
766 sizeof(drm_sarea_t
));
767 memset(pSAREAPriv
, 0, sizeof(*pSAREAPriv
));
768 // pSAREAPriv->pf_enabled=1;
772 /* Create a 'server' context so we can grab the lock for
773 * initialization ioctls.
775 if ((err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
)) != 0) {
776 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
780 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
782 /* Initialize the vertex buffers list */
783 if (!I810DRIBufInit(ctx
, info
)) {
784 fprintf(stderr
, "I810DRIBufInit failed\n");
785 DRM_UNLOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
);
789 /* Initialize the kernel data structures */
790 if (!I810DRIKernelInit(ctx
, info
)) {
791 fprintf(stderr
, "I810DRIKernelInit failed\n");
792 DRM_UNLOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
);
797 I810DRIIrqInit(ctx
, info
);
799 /* Quick hack to clear the front & back buffers. Could also use
800 * the clear ioctl to do this, but would need to setup hw state
804 memset((char *)ctx
->FBAddress
,
806 info
->auxPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
808 memset((char *)info
->backbuffer
,
810 info
->auxPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
813 /* This is the struct passed to i810_dri.so for its initialization */
814 ctx
->driverClientMsg
= malloc(sizeof(I810DRIRec
));
815 ctx
->driverClientMsgSize
= sizeof(I810DRIRec
);
816 pI810DRI
= (I810DRIPtr
)ctx
->driverClientMsg
;
818 pI810DRI
->regs
= info
->regs
;
819 pI810DRI
->regsSize
= info
->regsSize
;
822 pI810DRI
->backbufferSize
= info
->BackBuffer
.Size
;
823 pI810DRI
->backbuffer
= info
->backbuffer
;
825 pI810DRI
->depthbufferSize
= info
->DepthBuffer
.Size
;
826 pI810DRI
->depthbuffer
= info
->depthbuffer
;
828 pI810DRI
->textures
= info
->textures
;
829 pI810DRI
->textureSize
= info
->textureSize
;
831 pI810DRI
->agp_buffers
= info
->buffer_map
;
832 pI810DRI
->agp_buf_size
= info
->BufferMem
.Size
;
834 pI810DRI
->deviceID
= info
->Chipset
;
835 pI810DRI
->width
= ctx
->shared
.virtualWidth
;
836 pI810DRI
->height
= ctx
->shared
.virtualHeight
;
837 pI810DRI
->mem
= ctx
->shared
.fbSize
;
838 pI810DRI
->cpp
= ctx
->bpp
/ 8;
839 pI810DRI
->bitsPerPixel
= ctx
->bpp
;
840 pI810DRI
->fbOffset
= info
->FrontBuffer
.Start
;
841 pI810DRI
->fbStride
= info
->auxPitch
;
843 pI810DRI
->backOffset
= info
->BackBuffer
.Start
;
844 pI810DRI
->depthOffset
= info
->DepthBuffer
.Start
;
846 pI810DRI
->auxPitch
= info
->auxPitch
;
847 pI810DRI
->auxPitchBits
= info
->auxPitchBits
;
849 pI810DRI
->logTextureGranularity
= info
->logTextureGranularity
;
850 pI810DRI
->textureOffset
= info
->TexMem
.Start
;
852 pI810DRI
->ringOffset
= info
->LpRing
.mem
.Start
;
853 pI810DRI
->ringSize
= info
->LpRing
.mem
.Size
;
855 // drmBufs looks unused
856 pI810DRI
->irq
= info
->irq
;
857 pI810DRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
859 /* Don't release the lock now - let the VT switch handler do it. */
865 * \brief Validate the fbdev mode.
867 * \param ctx display handle.
869 * \return one on success, or zero on failure.
871 * Saves some registers and returns 1.
873 * \sa i810ValidateMode().
875 static int i810ValidateMode( const DRIDriverContext
*ctx
)
877 unsigned char *I810MMIO
= ctx
->MMIOAddress
;
878 I810Ptr info
= ctx
->driverPrivate
;
885 * \brief Examine mode returned by fbdev.
887 * \param ctx display handle.
889 * \return one on success, or zero on failure.
891 * Restores registers that fbdev has clobbered and returns 1.
893 * \sa i810ValidateMode().
895 static int i810PostValidateMode( const DRIDriverContext
*ctx
)
897 unsigned char *I810MMIO
= ctx
->MMIOAddress
;
898 I810Ptr info
= ctx
->driverPrivate
;
905 * \brief Initialize the framebuffer device mode
907 * \param ctx display handle.
909 * \return one on success, or zero on failure.
911 * Fills in \p info with some default values and some information from \p ctx
912 * and then calls I810ScreenInit() for the screen initialization.
914 * Before exiting clears the framebuffer memory accessing it directly.
916 static int i810InitFBDev( DRIDriverContext
*ctx
)
918 I810Ptr info
= calloc(1, sizeof(*info
));
921 int dummy
= ctx
->shared
.virtualWidth
;
923 switch (ctx
->bpp
/ 8) {
924 case 1: dummy
= (ctx
->shared
.virtualWidth
+ 127) & ~127; break;
925 case 2: dummy
= (ctx
->shared
.virtualWidth
+ 31) & ~31; break;
927 case 4: dummy
= (ctx
->shared
.virtualWidth
+ 15) & ~15; break;
930 ctx
->shared
.virtualWidth
= dummy
;
933 ctx
->driverPrivate
= (void *)info
;
935 info
->Chipset
= ctx
->chipset
;
937 if (!I810ScreenInit( ctx
, info
))
946 * \brief The screen is being closed, so clean up any state and free any
947 * resources used by the DRI.
949 * \param ctx display handle.
951 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
954 static void i810HaltFBDev( DRIDriverContext
*ctx
)
956 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
957 drmClose(ctx
->drmFD
);
959 if (ctx
->driverPrivate
) {
960 free(ctx
->driverPrivate
);
961 ctx
->driverPrivate
= 0;
966 extern void i810NotifyFocus( int );
969 * \brief Exported driver interface for Mini GLX.
973 const struct DRIDriverRec __driDriver
= {
975 i810PostValidateMode
,