gl: updated glxext.h to version 27
[mesa.git] / src / mesa / drivers / dri / i810 / server / i810_dri.c
1 /**
2 * \file server/i810_dri.c
3 * \brief File to perform the device-specific initialization tasks typically
4 * done in the X server.
5 *
6 * Here they are converted to run in the client (or perhaps a standalone
7 * process), and to work with the frame buffer device rather than the X
8 * server infrastructure.
9 *
10 * Copyright (C) 2004 Dave Airlie (airlied@linux.ie)
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18
19 #include "driver.h"
20 #include "drm.h"
21
22 #include "i810.h"
23 #include "i810_dri.h"
24 #include "i810_reg.h"
25
26
27 static int i810_pitches[] = {
28 512,
29 1024,
30 2048,
31 4096,
32 0
33 };
34
35 static int i810_pitch_flags[] = {
36 0x0,
37 0x1,
38 0x2,
39 0x3,
40 0
41 };
42
43 static unsigned int i810_drm_version = 0;
44
45 static int
46 I810AllocLow(I810MemRange * result, I810MemRange * pool, int size)
47 {
48 if (size > pool->Size)
49 return 0;
50
51 pool->Size -= size;
52 result->Size = size;
53 result->Start = pool->Start;
54 result->End = pool->Start += size;
55
56 return 1;
57 }
58
59 static int
60 I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size)
61 {
62 if (size > pool->Size)
63 return 0;
64
65 pool->Size -= size;
66 result->Size = size;
67 result->End = pool->End;
68 result->Start = pool->End -= size;
69
70 return 1;
71 }
72
73
74 /**
75 * \brief Wait for free FIFO entries.
76 *
77 * \param ctx display handle.
78 * \param entries number of free entries to wait.
79 *
80 * It polls the free entries from the chip until it reaches the requested value
81 * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out.
82 */
83 static void I810WaitForFifo( const DRIDriverContext *ctx,
84 int entries )
85 {
86 }
87
88 /**
89 * \brief Reset graphics card to known state.
90 *
91 * \param ctx display handle.
92 *
93 * Resets the values of several I810 registers.
94 */
95 static void I810EngineReset( const DRIDriverContext *ctx )
96 {
97 unsigned char *I810MMIO = ctx->MMIOAddress;
98 }
99
100 /**
101 * \brief Restore the drawing engine.
102 *
103 * \param ctx display handle
104 *
105 * Resets the graphics card and sets initial values for several registers of
106 * the card's drawing engine.
107 *
108 * Turns on the i810 command processor engine (i.e., the ringbuffer).
109 */
110 static int I810EngineRestore( const DRIDriverContext *ctx )
111 {
112 I810Ptr info = ctx->driverPrivate;
113 unsigned char *I810MMIO = ctx->MMIOAddress;
114
115 fprintf(stderr, "%s\n", __FUNCTION__);
116
117 return 1;
118 }
119
120
121 /**
122 * \brief Shutdown the drawing engine.
123 *
124 * \param ctx display handle
125 *
126 * Turns off the command processor engine & restores the graphics card
127 * to a state that fbdev understands.
128 */
129 static int I810EngineShutdown( const DRIDriverContext *ctx )
130 {
131 drmI810Init info;
132 int ret;
133
134 memset(&info, 0, sizeof(drmI810Init));
135 info.func = I810_CLEANUP_DMA;
136
137 ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &info, sizeof(drmI810Init));
138 if (ret>0)
139 {
140 fprintf(stderr,"[dri] I810 DMA Cleanup failed\n");
141 return -errno;
142 }
143 return 0;
144 }
145
146 /**
147 * \brief Compute base 2 logarithm.
148 *
149 * \param val value.
150 *
151 * \return base 2 logarithm of \p val.
152 */
153 static int I810MinBits(int val)
154 {
155 int bits;
156
157 if (!val) return 1;
158 for (bits = 0; val; val >>= 1, ++bits);
159 return bits;
160 }
161
162 static int I810DRIAgpPreInit( const DRIDriverContext *ctx, I810Ptr info)
163 {
164
165 if (drmAgpAcquire(ctx->drmFD) < 0) {
166 fprintf(stderr, "[gart] AGP not available\n");
167 return 0;
168 }
169
170
171 if (drmAgpEnable(ctx->drmFD, 0) < 0) {
172 fprintf(stderr, "[gart] AGP not enabled\n");
173 drmAgpRelease(ctx->drmFD);
174 return 0;
175 }
176 }
177
178 /**
179 * \brief Initialize the AGP state
180 *
181 * \param ctx display handle.
182 * \param info driver private data.
183 *
184 * \return one on success, or zero on failure.
185 *
186 * Acquires and enables the AGP device. Reserves memory in the AGP space for
187 * the ring buffer, vertex buffers and textures. Initialize the I810
188 * registers to point to that memory and add client mappings.
189 */
190 static int I810DRIAgpInit( const DRIDriverContext *ctx, I810Ptr info)
191 {
192 unsigned char *I810MMIO = ctx->MMIOAddress;
193 int ret;
194 int s, l;
195 unsigned long dcacheHandle;
196 unsigned long agpHandle;
197 int pitch_idx = 0;
198 int back_size = 0;
199 int sysmem_size = 0;
200 int width = ctx->shared.virtualWidth * ctx->cpp;
201
202
203 info->backHandle = DRM_AGP_NO_HANDLE;
204 info->zHandle = DRM_AGP_NO_HANDLE;
205 info->sysmemHandle = DRM_AGP_NO_HANDLE;
206 info->dcacheHandle = DRM_AGP_NO_HANDLE;
207
208 memset(&info->DcacheMem, 0, sizeof(I810MemRange));
209 memset(&info->BackBuffer, 0, sizeof(I810MemRange));
210 memset(&info->DepthBuffer, 0, sizeof(I810MemRange));
211
212 drmAgpAlloc(ctx->drmFD, 4096 * 1024, 1, NULL, &dcacheHandle);
213 info->dcacheHandle = dcacheHandle;
214
215 fprintf(stderr, "[agp] dcacheHandle : 0x%x\n", dcacheHandle);
216
217 #define Elements(x) sizeof(x)/sizeof(*x)
218 for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
219 if (width <= i810_pitches[pitch_idx])
220 break;
221
222 if (pitch_idx == Elements(i810_pitches)) {
223 fprintf(stderr,"[dri] Couldn't find depth/back buffer pitch\n");
224 exit(-1);
225 }
226 else
227 {
228 int lines = (ctx->shared.virtualWidth + 15) / 16 * 16;
229 back_size = i810_pitches[pitch_idx] * lines;
230 back_size = ((back_size + 4096 - 1) / 4096) * 4096;
231 }
232
233 sysmem_size = ctx->shared.fbSize;
234 fprintf(stderr,"sysmem_size is %lu back_size is %lu\n", sysmem_size, back_size);
235 if (dcacheHandle != DRM_AGP_NO_HANDLE) {
236 if (back_size > 4 * 1024 * 1024) {
237 fprintf(stderr,"[dri] Backsize is larger then 4 meg\n");
238 sysmem_size = sysmem_size - 2 * back_size;
239 drmAgpFree(ctx->drmFD, dcacheHandle);
240 info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
241 } else {
242 sysmem_size = sysmem_size - back_size;
243 }
244 } else {
245 sysmem_size = sysmem_size - 2 * back_size;
246 }
247
248 info->SysMem.Start=0;
249 info->SysMem.Size = sysmem_size;
250 info->SysMem.End = sysmem_size;
251
252 if (dcacheHandle != DRM_AGP_NO_HANDLE) {
253 if (drmAgpBind(ctx->drmFD, dcacheHandle, info->DepthOffset) == 0) {
254 memset(&info->DcacheMem, 0, sizeof(I810MemRange));
255 fprintf(stderr,"[agp] GART: Found 4096K Z buffer memory\n");
256 info->DcacheMem.Start = info->DepthOffset;
257 info->DcacheMem.Size = 1024 * 4096;
258 info->DcacheMem.End = info->DcacheMem.Start + info->DcacheMem.Size;
259 } else {
260 fprintf(stderr, "[agp] GART: dcache bind failed\n");
261 drmAgpFree(ctx->drmFD, dcacheHandle);
262 info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
263 }
264 } else {
265 fprintf(stderr, "[agp] GART: no dcache memory found\n");
266 }
267
268 drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle);
269 info->backHandle = agpHandle;
270
271 if (agpHandle != DRM_AGP_NO_HANDLE) {
272 if (drmAgpBind(ctx->drmFD, agpHandle, info->BackOffset) == 0) {
273 fprintf(stderr, "[agp] Bound backbuffer memory\n");
274
275 info->BackBuffer.Start = info->BackOffset;
276 info->BackBuffer.Size = back_size;
277 info->BackBuffer.End = (info->BackBuffer.Start +
278 info->BackBuffer.Size);
279 } else {
280 fprintf(stderr,"[agp] Unable to bind backbuffer. Disabling DRI.\n");
281 return 0;
282 }
283 } else {
284 fprintf(stderr, "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n");
285 return 0;
286 }
287
288 if (dcacheHandle == DRM_AGP_NO_HANDLE) {
289 drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle);
290
291 info->zHandle = agpHandle;
292
293 if (agpHandle != DRM_AGP_NO_HANDLE) {
294 if (drmAgpBind(ctx->drmFD, agpHandle, info->DepthOffset) == 0) {
295 fprintf(stderr,"[agp] Bound depthbuffer memory\n");
296 info->DepthBuffer.Start = info->DepthOffset;
297 info->DepthBuffer.Size = back_size;
298 info->DepthBuffer.End = (info->DepthBuffer.Start +
299 info->DepthBuffer.Size);
300 } else {
301 fprintf(stderr,"[agp] Unable to bind depthbuffer. Disabling DRI.\n");
302 return 0;
303 }
304 } else {
305 fprintf(stderr,"[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n");
306 return 0;
307 }
308 }
309
310 /* Now allocate and bind the agp space. This memory will include the
311 * regular framebuffer as well as texture memory.
312 */
313 drmAgpAlloc(ctx->drmFD, sysmem_size, 0, NULL, &agpHandle);
314 info->sysmemHandle = agpHandle;
315
316 if (agpHandle != DRM_AGP_NO_HANDLE) {
317 if (drmAgpBind(ctx->drmFD, agpHandle, 0) == 0) {
318 fprintf(stderr, "[agp] Bound System Texture Memory\n");
319 } else {
320 fprintf(stderr, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
321 return 0;
322 }
323 } else {
324 fprintf(stderr, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
325 return 0;
326 }
327
328 info->auxPitch = i810_pitches[pitch_idx];
329 info->auxPitchBits = i810_pitch_flags[pitch_idx];
330
331 return 1;
332 }
333
334
335 /**
336 * \brief Initialize the kernel data structures and enable the CP engine.
337 *
338 * \param ctx display handle.
339 * \param info driver private data.
340 *
341 * \return non-zero on success, or zero on failure.
342 *
343 * This function is a wrapper around the DRM_I810_CP_INIT command, passing
344 * all the parameters in a drmI810Init structure.
345 */
346 static int I810DRIKernelInit( const DRIDriverContext *ctx,
347 I810Ptr info)
348 {
349 int cpp = ctx->bpp / 8;
350 drmI810Init drmInfo;
351 int ret;
352 I810RingBuffer *ring = &(info->LpRing);
353
354 /* This is the struct passed to the kernel module for its initialization */
355 memset(&drmInfo, 0, sizeof(drmI810Init));
356
357 /* make sure we have at least 1.4 */
358 drmInfo.func = I810_INIT_DMA_1_4;
359
360 drmInfo.ring_start = ring->mem.Start;
361 drmInfo.ring_end = ring->mem.End;
362 drmInfo.ring_size = ring->mem.Size;
363
364 drmInfo.mmio_offset = (unsigned int)info->regs;
365 drmInfo.buffers_offset = (unsigned int)info->buffer_map;
366 drmInfo.sarea_priv_offset = sizeof(drm_sarea_t);
367
368 drmInfo.front_offset = 0;
369 drmInfo.back_offset = info->BackBuffer.Start;
370 drmInfo.depth_offset = info->DepthBuffer.Start;
371
372 drmInfo.w = ctx->shared.virtualWidth;
373 drmInfo.h = ctx->shared.virtualHeight;
374 drmInfo.pitch = info->auxPitch;
375 drmInfo.pitch_bits = info->auxPitchBits;
376
377
378 ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &drmInfo,
379 sizeof(drmI810Init));
380
381 return ret >= 0;
382 }
383
384
385 /**
386 * \brief Add a map for the vertex buffers that will be accessed by any
387 * DRI-based clients.
388 *
389 * \param ctx display handle.
390 * \param info driver private data.
391 *
392 * \return one on success, or zero on failure.
393 *
394 * Calls drmAddBufs() with the previously allocated vertex buffers.
395 */
396 static int I810DRIBufInit( const DRIDriverContext *ctx, I810Ptr info )
397 {
398 /* Initialize vertex buffers */
399 info->bufNumBufs = drmAddBufs(ctx->drmFD,
400 I810_DMA_BUF_NR,
401 I810_DMA_BUF_SZ,
402 DRM_AGP_BUFFER,
403 info->BufferMem.Start);
404
405 if (info->bufNumBufs <= 0) {
406 fprintf(stderr,
407 "[drm] Could not create vertex/indirect buffers list\n");
408 return 0;
409 }
410 fprintf(stderr,
411 "[drm] Added %d %d byte vertex/indirect buffers\n",
412 info->bufNumBufs, I810_DMA_BUF_SZ);
413
414 return 1;
415 }
416
417 /**
418 * \brief Install an IRQ handler.
419 *
420 * \param ctx display handle.
421 * \param info driver private data.
422 *
423 * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to
424 * IRQ-free operation on failure.
425 */
426 static void I810DRIIrqInit(const DRIDriverContext *ctx,
427 I810Ptr info)
428 {
429 if (!info->irq) {
430 info->irq = drmGetInterruptFromBusID(ctx->drmFD,
431 ctx->pciBus,
432 ctx->pciDevice,
433 ctx->pciFunc);
434
435 if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) {
436 fprintf(stderr,
437 "[drm] failure adding irq handler, "
438 "there is a device already using that irq\n"
439 "[drm] falling back to irq-free operation\n");
440 info->irq = 0;
441 }
442 }
443
444 if (info->irq)
445 fprintf(stderr,
446 "[drm] dma control initialized, using IRQ %d\n",
447 info->irq);
448 }
449
450 static int I810CheckDRMVersion( const DRIDriverContext *ctx,
451 I810Ptr info )
452 {
453 drmVersionPtr version;
454
455 version = drmGetVersion(ctx->drmFD);
456 if (version) {
457 int req_minor, req_patch;
458
459 req_minor = 4;
460 req_patch = 0;
461
462 i810_drm_version = (version->version_major<<16) | version->version_minor;
463 if (version->version_major != 1 ||
464 version->version_minor < req_minor ||
465 (version->version_minor == req_minor &&
466 version->version_patchlevel < req_patch)) {
467 /* Incompatible drm version */
468 fprintf(stderr,
469 "[dri] I810DRIScreenInit failed because of a version "
470 "mismatch.\n"
471 "[dri] i810.o kernel module version is %d.%d.%d "
472 "but version 1.%d.%d or newer is needed.\n"
473 "[dri] Disabling DRI.\n",
474 version->version_major,
475 version->version_minor,
476 version->version_patchlevel,
477 req_minor,
478 req_patch);
479 drmFreeVersion(version);
480 return 0;
481 }
482
483 info->drmMinor = version->version_minor;
484 drmFreeVersion(version);
485 }
486
487 return 1;
488 }
489
490 static int I810MemoryInit( const DRIDriverContext *ctx, I810Ptr info )
491 {
492 int width_bytes = ctx->shared.virtualWidth * ctx->cpp;
493 int cpp = ctx->cpp;
494 int bufferSize = (ctx->shared.virtualHeight * width_bytes);
495 int depthSize = (((ctx->shared.virtualHeight+15) & ~15) * width_bytes);
496 int l;
497
498 if (drmAddMap(ctx->drmFD, (drm_handle_t) info->BackBuffer.Start,
499 info->BackBuffer.Size, DRM_AGP, 0,
500 &info->backbuffer) < 0) {
501 fprintf(stderr, "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
502 return 0;
503 }
504
505 if (drmAddMap(ctx->drmFD, (drm_handle_t) info->DepthBuffer.Start,
506 info->DepthBuffer.Size, DRM_AGP, 0,
507 &info->depthbuffer) < 0) {
508 fprintf(stderr, "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n");
509 return 0;
510 }
511
512 if (!I810AllocLow(&(info->FrontBuffer), &(info->SysMem), (((ctx->shared.virtualHeight * width_bytes) + 4095) & ~4095)))
513 {
514 fprintf(stderr,"Framebuffer allocation failed\n");
515 return 0;
516 }
517 else
518 fprintf(stderr,"Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
519 info->FrontBuffer.Start,
520 info->FrontBuffer.Size / 1024, info->FrontBuffer.Size);
521
522 memset(&(info->LpRing), 0, sizeof(I810RingBuffer));
523 if (I810AllocLow(&(info->LpRing.mem), &(info->SysMem), 16 * 4096)) {
524 fprintf(stderr,
525 "Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
526 info->LpRing.mem.Start,
527 info->LpRing.mem.Size / 1024, info->LpRing.mem.Size);
528
529 info->LpRing.tail_mask = info->LpRing.mem.Size - 1;
530 info->LpRing.virtual_start = info->LpRing.mem.Start;
531 info->LpRing.head = 0;
532 info->LpRing.tail = 0;
533 info->LpRing.space = 0;
534 } else {
535 fprintf(stderr, "Ring buffer allocation failed\n");
536 return (0);
537 }
538
539 /* Allocate buffer memory */
540 I810AllocHigh(&(info->BufferMem), &(info->SysMem),
541 I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
542
543
544 fprintf(stderr, "[dri] Buffer map : %lx\n",
545 info->BufferMem.Start);
546
547 if (info->BufferMem.Start == 0 ||
548 info->BufferMem.End - info->BufferMem.Start >
549 I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
550 fprintf(stderr,"[dri] Not enough memory for dma buffers. Disabling DRI.\n");
551 return 0;
552 }
553
554 if (drmAddMap(ctx->drmFD, (drm_handle_t) info->BufferMem.Start,
555 info->BufferMem.Size, DRM_AGP, 0, &info->buffer_map) < 0) {
556 fprintf(stderr, "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n");
557 return 0;
558 }
559
560 if (drmAddMap(ctx->drmFD, (drm_handle_t) info->LpRing.mem.Start,
561 info->LpRing.mem.Size, DRM_AGP, 0, &info->ring_map) < 0) {
562 fprintf(stderr, "[drm] drmAddMap(ring_map) failed. Disabling DRI. \n");
563 return 0;
564 }
565
566 /* Front, back and depth buffers - everything else texture??
567 */
568 info->textureSize = info->SysMem.Size;
569
570 if (info->textureSize < 0)
571 return 0;
572
573
574 l = I810MinBits((info->textureSize-1) / I810_NR_TEX_REGIONS);
575 if (l < I810_LOG_MIN_TEX_REGION_SIZE) l = I810_LOG_MIN_TEX_REGION_SIZE;
576
577 /* Round the texture size up to the nearest whole number of
578 * texture regions. Again, be greedy about this, don't
579 * round down.
580 */
581 info->logTextureGranularity = l;
582 info->textureSize = (info->textureSize >> l) << l;
583
584 /* Set a minimum usable local texture heap size. This will fit
585 * two 256x256x32bpp textures.
586 */
587 if (info->textureSize < 512 * 1024) {
588 info->textureOffset = 0;
589 info->textureSize = 0;
590 }
591
592 I810AllocLow(&(info->TexMem), &(info->SysMem), info->textureSize);
593
594 if (drmAddMap(ctx->drmFD, (drm_handle_t) info->TexMem.Start,
595 info->TexMem.Size, DRM_AGP, 0, &info->textures) < 0) {
596 fprintf(stderr,
597 "[drm] drmAddMap(textures) failed. Disabling DRI.\n");
598 return 0;
599 }
600
601 /* Reserve space for textures */
602 fprintf(stderr,
603 "Will use back buffer at offset 0x%x\n",
604 info->BackOffset);
605 fprintf(stderr,
606 "Will use depth buffer at offset 0x%x\n",
607 info->DepthOffset);
608 fprintf(stderr,
609 "Will use %d kb for textures at offset 0x%x\n",
610 info->TexMem.Size/1024, info->TexMem.Start);
611
612 return 1;
613 }
614
615
616
617 /**
618 * Called at the start of each server generation.
619 *
620 * \param ctx display handle.
621 * \param info driver private data.
622 *
623 * \return non-zero on success, or zero on failure.
624 *
625 * Performs static frame buffer allocation. Opens the DRM device and add maps
626 * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more
627 * information. Creates a \e server context to grab the lock for the
628 * initialization ioctls and calls the other initilization functions in this
629 * file. Starts the CP engine via the DRM_I810_CP_START command.
630 *
631 * Setups a I810DRIRec structure to be passed to i810_dri.so for its
632 * initialization.
633 */
634 static int I810ScreenInit( DRIDriverContext *ctx, I810Ptr info )
635 {
636 I810DRIPtr pI810DRI;
637 int err;
638
639 usleep(100);
640 /*assert(!ctx->IsClient);*/
641
642 /* from XFree86 driver */
643 info->DepthOffset = 0x3000000;
644 info->BackOffset = 0x3800000;
645 {
646 int width_bytes = (ctx->shared.virtualWidth * ctx->cpp);
647 int maxy = ctx->shared.fbSize / width_bytes;
648
649
650 if (maxy <= ctx->shared.virtualHeight * 3) {
651 fprintf(stderr,
652 "Static buffer allocation failed -- "
653 "need at least %d kB video memory (have %d kB)\n",
654 (ctx->shared.virtualWidth * ctx->shared.virtualHeight *
655 ctx->cpp * 3 + 1023) / 1024,
656 ctx->shared.fbSize / 1024);
657 return 0;
658 }
659 }
660
661
662 info->regsSize = ctx->MMIOSize;
663 ctx->shared.SAREASize = 0x2000;
664
665 /* Note that drmOpen will try to load the kernel module, if needed. */
666 ctx->drmFD = drmOpen("i810", NULL );
667 if (ctx->drmFD < 0) {
668 fprintf(stderr, "[drm] drmOpen failed\n");
669 return 0;
670 }
671
672 if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
673 fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
674 ctx->drmFD, ctx->pciBusID, strerror(-err));
675 return 0;
676 }
677
678 if (drmAddMap( ctx->drmFD,
679 0,
680 ctx->shared.SAREASize,
681 DRM_SHM,
682 DRM_CONTAINS_LOCK,
683 &ctx->shared.hSAREA) < 0)
684 {
685 fprintf(stderr, "[drm] drmAddMap failed\n");
686 return 0;
687 }
688 fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
689 ctx->shared.SAREASize, ctx->shared.hSAREA);
690
691 if (drmMap( ctx->drmFD,
692 ctx->shared.hSAREA,
693 ctx->shared.SAREASize,
694 (drmAddressPtr)(&ctx->pSAREA)) < 0)
695 {
696 fprintf(stderr, "[drm] drmMap failed\n");
697 return 0;
698 }
699 memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
700 fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
701 ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
702
703 if (drmAddMap(ctx->drmFD,
704 ctx->MMIOStart,
705 ctx->MMIOSize,
706 DRM_REGISTERS,
707 DRM_READ_ONLY,
708 &info->regs) < 0) {
709 fprintf(stderr, "[drm] drmAddMap mmio failed\n");
710 return 0;
711 }
712 fprintf(stderr,
713 "[drm] register handle = 0x%08x\n", info->regs);
714
715 I810DRIAgpPreInit(ctx, info);
716 /* Need to AddMap the framebuffer and mmio regions here:
717 */
718 if (drmAddMap( ctx->drmFD,
719 (drm_handle_t)ctx->FBStart,
720 ctx->FBSize,
721 DRM_FRAME_BUFFER,
722 #ifndef _EMBEDDED
723 0,
724 #else
725 DRM_READ_ONLY,
726 #endif
727 &ctx->shared.hFrameBuffer) < 0)
728 {
729 fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
730 return 0;
731 }
732
733 fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
734 ctx->shared.hFrameBuffer);
735
736 /* Check the i810 DRM version */
737 if (!I810CheckDRMVersion(ctx, info)) {
738 return 0;
739 }
740
741 /* Initialize AGP */
742 if (!I810DRIAgpInit(ctx, info)) {
743 return 0;
744 }
745
746
747 /* Memory manager setup */
748 if (!I810MemoryInit(ctx, info)) {
749 return 0;
750 }
751
752 /* Initialize the SAREA private data structure */
753 {
754 I810SAREAPtr pSAREAPriv;
755 pSAREAPriv = (I810SAREAPtr)(((char*)ctx->pSAREA) +
756 sizeof(drm_sarea_t));
757 memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
758 // pSAREAPriv->pf_enabled=1;
759 }
760
761
762 /* Create a 'server' context so we can grab the lock for
763 * initialization ioctls.
764 */
765 if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
766 fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
767 return 0;
768 }
769
770 DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
771
772 /* Initialize the vertex buffers list */
773 if (!I810DRIBufInit(ctx, info)) {
774 fprintf(stderr, "I810DRIBufInit failed\n");
775 DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
776 return 0;
777 }
778
779 /* Initialize the kernel data structures */
780 if (!I810DRIKernelInit(ctx, info)) {
781 fprintf(stderr, "I810DRIKernelInit failed\n");
782 DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
783 return 0;
784 }
785
786 /* Initialize IRQ */
787 I810DRIIrqInit(ctx, info);
788
789 /* Quick hack to clear the front & back buffers. Could also use
790 * the clear ioctl to do this, but would need to setup hw state
791 * first.
792 */
793 #if 0
794 memset((char *)ctx->FBAddress,
795 0,
796 info->auxPitch * ctx->cpp * ctx->shared.virtualHeight );
797
798 memset((char *)info->backbuffer,
799 0,
800 info->auxPitch * ctx->cpp * ctx->shared.virtualHeight );
801 #endif
802
803 /* This is the struct passed to i810_dri.so for its initialization */
804 ctx->driverClientMsg = malloc(sizeof(I810DRIRec));
805 ctx->driverClientMsgSize = sizeof(I810DRIRec);
806 pI810DRI = (I810DRIPtr)ctx->driverClientMsg;
807
808 pI810DRI->regs = info->regs;
809 pI810DRI->regsSize = info->regsSize;
810 // regsMap is unused
811
812 pI810DRI->backbufferSize = info->BackBuffer.Size;
813 pI810DRI->backbuffer = info->backbuffer;
814
815 pI810DRI->depthbufferSize = info->DepthBuffer.Size;
816 pI810DRI->depthbuffer = info->depthbuffer;
817
818 pI810DRI->textures = info->textures;
819 pI810DRI->textureSize = info->textureSize;
820
821 pI810DRI->agp_buffers = info->buffer_map;
822 pI810DRI->agp_buf_size = info->BufferMem.Size;
823
824 pI810DRI->deviceID = info->Chipset;
825 pI810DRI->width = ctx->shared.virtualWidth;
826 pI810DRI->height = ctx->shared.virtualHeight;
827 pI810DRI->mem = ctx->shared.fbSize;
828 pI810DRI->cpp = ctx->bpp / 8;
829 pI810DRI->bitsPerPixel = ctx->bpp;
830 pI810DRI->fbOffset = info->FrontBuffer.Start;
831 pI810DRI->fbStride = info->auxPitch;
832
833 pI810DRI->backOffset = info->BackBuffer.Start;
834 pI810DRI->depthOffset = info->DepthBuffer.Start;
835
836 pI810DRI->auxPitch = info->auxPitch;
837 pI810DRI->auxPitchBits = info->auxPitchBits;
838
839 pI810DRI->logTextureGranularity = info->logTextureGranularity;
840 pI810DRI->textureOffset = info->TexMem.Start;
841
842 pI810DRI->ringOffset = info->LpRing.mem.Start;
843 pI810DRI->ringSize = info->LpRing.mem.Size;
844
845 // drmBufs looks unused
846 pI810DRI->irq = info->irq;
847 pI810DRI->sarea_priv_offset = sizeof(drm_sarea_t);
848
849 /* Don't release the lock now - let the VT switch handler do it. */
850 return 1;
851 }
852
853
854 /**
855 * \brief Validate the fbdev mode.
856 *
857 * \param ctx display handle.
858 *
859 * \return one on success, or zero on failure.
860 *
861 * Saves some registers and returns 1.
862 *
863 * \sa i810ValidateMode().
864 */
865 static int i810ValidateMode( const DRIDriverContext *ctx )
866 {
867 unsigned char *I810MMIO = ctx->MMIOAddress;
868 I810Ptr info = ctx->driverPrivate;
869
870 return 1;
871 }
872
873
874 /**
875 * \brief Examine mode returned by fbdev.
876 *
877 * \param ctx display handle.
878 *
879 * \return one on success, or zero on failure.
880 *
881 * Restores registers that fbdev has clobbered and returns 1.
882 *
883 * \sa i810ValidateMode().
884 */
885 static int i810PostValidateMode( const DRIDriverContext *ctx )
886 {
887 unsigned char *I810MMIO = ctx->MMIOAddress;
888 I810Ptr info = ctx->driverPrivate;
889
890 return 1;
891 }
892
893
894 /**
895 * \brief Initialize the framebuffer device mode
896 *
897 * \param ctx display handle.
898 *
899 * \return one on success, or zero on failure.
900 *
901 * Fills in \p info with some default values and some information from \p ctx
902 * and then calls I810ScreenInit() for the screen initialization.
903 *
904 * Before exiting clears the framebuffer memory accessing it directly.
905 */
906 static int i810InitFBDev( DRIDriverContext *ctx )
907 {
908 I810Ptr info = calloc(1, sizeof(*info));
909
910 {
911 int dummy = ctx->shared.virtualWidth;
912
913 switch (ctx->bpp / 8) {
914 case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
915 case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
916 case 3:
917 case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
918 }
919
920 ctx->shared.virtualWidth = dummy;
921 }
922
923 ctx->driverPrivate = (void *)info;
924
925 info->Chipset = ctx->chipset;
926
927 if (!I810ScreenInit( ctx, info ))
928 return 0;
929
930
931 return 1;
932 }
933
934
935 /**
936 * \brief The screen is being closed, so clean up any state and free any
937 * resources used by the DRI.
938 *
939 * \param ctx display handle.
940 *
941 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
942 * private data.
943 */
944 static void i810HaltFBDev( DRIDriverContext *ctx )
945 {
946 drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
947 drmClose(ctx->drmFD);
948
949 if (ctx->driverPrivate) {
950 free(ctx->driverPrivate);
951 ctx->driverPrivate = 0;
952 }
953 }
954
955
956 extern void i810NotifyFocus( int );
957
958 /**
959 * \brief Exported driver interface for Mini GLX.
960 *
961 * \sa DRIDriverRec.
962 */
963 const struct DRIDriverRec __driDriver = {
964 i810ValidateMode,
965 i810PostValidateMode,
966 i810InitFBDev,
967 i810HaltFBDev,
968 I810EngineShutdown,
969 I810EngineRestore,
970 #ifndef _EMBEDDED
971 0,
972 #else
973 i810NotifyFocus,
974 #endif
975 };