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