DRI2: report swap events correctly in direct rendered case
[mesa.git] / src / mesa / drivers / dri / mga / server / mga_dri.c
1
2 /*
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES
21 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Keith Whitwell <keith@tungstengraphics.com>
27 * Gareth Hughes <gareth@valinux.com>
28 */
29
30 #include <errno.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <inttypes.h>
36
37 #include "driver.h"
38 #include "drm.h"
39 #include "memops.h"
40
41 #include "mga_reg.h"
42 #include "mga.h"
43 #include "mga_macros.h"
44 #include "mga_dri.h"
45
46
47 /* Quiescence, locking
48 */
49 #define MGA_TIMEOUT 2048
50
51 static void MGAWaitForIdleDMA( struct DRIDriverContextRec *ctx, MGAPtr pMga )
52 {
53 drm_lock_t lock;
54 int ret;
55 int i = 0;
56
57 memset( &lock, 0, sizeof(lock) );
58
59 for (;;) {
60 do {
61 /* first ask for quiescent and flush */
62 lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH;
63 do {
64 ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
65 &lock, sizeof( lock ) );
66 } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
67
68 /* if it's still busy just try quiescent */
69 if ( ret == -EBUSY ) {
70 lock.flags = DRM_LOCK_QUIESCENT;
71 do {
72 ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
73 &lock, sizeof( lock ) );
74 } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
75 }
76 } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) );
77
78 if ( ret == 0 )
79 return;
80
81 fprintf( stderr,
82 "[dri] Idle timed out, resetting engine...\n" );
83
84 drmCommandNone( ctx->drmFD, DRM_MGA_RESET );
85 }
86 }
87
88 static unsigned int mylog2( unsigned int n )
89 {
90 unsigned int log2 = 1;
91 while ( n > 1 ) n >>= 1, log2++;
92 return log2;
93 }
94
95 static int MGADRIAgpInit(struct DRIDriverContextRec *ctx, MGAPtr pMga)
96 {
97 unsigned long mode;
98 unsigned int vendor, device;
99 int ret, count, i;
100
101 if(pMga->agpSize < 12)pMga->agpSize = 12;
102 if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */
103
104 /* FIXME: Make these configurable...
105 */
106 pMga->agp.size = pMga->agpSize * 1024 * 1024;
107
108 pMga->warp.offset = 0;
109 pMga->warp.size = MGA_WARP_UCODE_SIZE;
110
111 pMga->primary.offset = (pMga->warp.offset +
112 pMga->warp.size);
113 pMga->primary.size = 1024 * 1024;
114
115 pMga->buffers.offset = (pMga->primary.offset +
116 pMga->primary.size);
117 pMga->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE;
118
119
120 pMga->agpTextures.offset = (pMga->buffers.offset +
121 pMga->buffers.size);
122
123 pMga->agpTextures.size = pMga->agp.size -
124 pMga->agpTextures.offset;
125
126 if ( drmAgpAcquire( ctx->drmFD ) < 0 ) {
127 fprintf( stderr, "[agp] AGP not available\n" );
128 return 0;
129 }
130
131 mode = drmAgpGetMode( ctx->drmFD ); /* Default mode */
132 vendor = drmAgpVendorId( ctx->drmFD );
133 device = drmAgpDeviceId( ctx->drmFD );
134
135 mode &= ~MGA_AGP_MODE_MASK;
136 switch ( pMga->agpMode ) {
137 case 4:
138 mode |= MGA_AGP_4X_MODE;
139 case 2:
140 mode |= MGA_AGP_2X_MODE;
141 case 1:
142 default:
143 mode |= MGA_AGP_1X_MODE;
144 }
145
146 #if 0
147 fprintf( stderr,
148 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
149 mode, vendor, device,
150 ctx->pciVendor,
151 ctx->pciChipType );
152 #endif
153
154 if ( drmAgpEnable( ctx->drmFD, mode ) < 0 ) {
155 fprintf( stderr, "[agp] AGP not enabled\n" );
156 drmAgpRelease( ctx->drmFD );
157 return 0;
158 }
159
160 if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
161 switch ( pMga->agpMode ) {
162 case 2:
163 fprintf( stderr,
164 "[drm] Enabling AGP 2x PLL encoding\n" );
165 OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE );
166 break;
167
168 case 1:
169 default:
170 fprintf( stderr,
171 "[drm] Disabling AGP 2x PLL encoding\n" );
172 OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE );
173 pMga->agpMode = 1;
174 break;
175 }
176 }
177
178 ret = drmAgpAlloc( ctx->drmFD, pMga->agp.size,
179 0, NULL, &pMga->agp.handle );
180 if ( ret < 0 ) {
181 fprintf( stderr, "[agp] Out of memory (%d)\n", ret );
182 drmAgpRelease( ctx->drmFD );
183 return 0;
184 }
185 fprintf( stderr,
186 "[agp] %d kB allocated with handle 0x%08x\n",
187 pMga->agp.size/1024, (unsigned int)pMga->agp.handle );
188
189 if ( drmAgpBind( ctx->drmFD, pMga->agp.handle, 0 ) < 0 ) {
190 fprintf( stderr, "[agp] Could not bind memory\n" );
191 drmAgpFree( ctx->drmFD, pMga->agp.handle );
192 drmAgpRelease( ctx->drmFD );
193 return 0;
194 }
195
196 /* WARP microcode space
197 */
198 if ( drmAddMap( ctx->drmFD,
199 pMga->warp.offset,
200 pMga->warp.size,
201 DRM_AGP, DRM_READ_ONLY,
202 &pMga->warp.handle ) < 0 ) {
203 fprintf( stderr,
204 "[agp] Could not add WARP microcode mapping\n" );
205 return 0;
206 }
207 fprintf( stderr,
208 "[agp] WARP microcode handle = 0x%08x\n",
209 pMga->warp.handle );
210
211 if ( drmMap( ctx->drmFD,
212 pMga->warp.handle,
213 pMga->warp.size,
214 &pMga->warp.map ) < 0 ) {
215 fprintf( stderr,
216 "[agp] Could not map WARP microcode\n" );
217 return 0;
218 }
219 fprintf( stderr,
220 "[agp] WARP microcode mapped at 0x%08lx\n",
221 (unsigned long)pMga->warp.map );
222
223 /* Primary DMA space
224 */
225 if ( drmAddMap( ctx->drmFD,
226 pMga->primary.offset,
227 pMga->primary.size,
228 DRM_AGP, DRM_READ_ONLY,
229 &pMga->primary.handle ) < 0 ) {
230 fprintf( stderr,
231 "[agp] Could not add primary DMA mapping\n" );
232 return 0;
233 }
234 fprintf( stderr,
235 "[agp] Primary DMA handle = 0x%08x\n",
236 pMga->primary.handle );
237
238 if ( drmMap( ctx->drmFD,
239 pMga->primary.handle,
240 pMga->primary.size,
241 &pMga->primary.map ) < 0 ) {
242 fprintf( stderr,
243 "[agp] Could not map primary DMA\n" );
244 return 0;
245 }
246 fprintf( stderr,
247 "[agp] Primary DMA mapped at 0x%08lx\n",
248 (unsigned long)pMga->primary.map );
249
250 /* DMA buffers
251 */
252 if ( drmAddMap( ctx->drmFD,
253 pMga->buffers.offset,
254 pMga->buffers.size,
255 DRM_AGP, 0,
256 &pMga->buffers.handle ) < 0 ) {
257 fprintf( stderr,
258 "[agp] Could not add DMA buffers mapping\n" );
259 return 0;
260 }
261 fprintf( stderr,
262 "[agp] DMA buffers handle = 0x%08x\n",
263 pMga->buffers.handle );
264
265 if ( drmMap( ctx->drmFD,
266 pMga->buffers.handle,
267 pMga->buffers.size,
268 &pMga->buffers.map ) < 0 ) {
269 fprintf( stderr,
270 "[agp] Could not map DMA buffers\n" );
271 return 0;
272 }
273 fprintf( stderr,
274 "[agp] DMA buffers mapped at 0x%08lx\n",
275 (unsigned long)pMga->buffers.map );
276
277 count = drmAddBufs( ctx->drmFD,
278 MGA_NUM_BUFFERS, MGA_BUFFER_SIZE,
279 DRM_AGP_BUFFER, pMga->buffers.offset );
280 if ( count <= 0 ) {
281 fprintf( stderr,
282 "[drm] failure adding %d %d byte DMA buffers\n",
283 MGA_NUM_BUFFERS, MGA_BUFFER_SIZE );
284 return 0;
285 }
286 fprintf( stderr,
287 "[drm] Added %d %d byte DMA buffers\n",
288 count, MGA_BUFFER_SIZE );
289
290 i = mylog2(pMga->agpTextures.size / MGA_NR_TEX_REGIONS);
291 if(i < MGA_LOG_MIN_TEX_REGION_SIZE)
292 i = MGA_LOG_MIN_TEX_REGION_SIZE;
293 pMga->agpTextures.size = (pMga->agpTextures.size >> i) << i;
294
295 if ( drmAddMap( ctx->drmFD,
296 pMga->agpTextures.offset,
297 pMga->agpTextures.size,
298 DRM_AGP, 0,
299 &pMga->agpTextures.handle ) < 0 ) {
300 fprintf( stderr,
301 "[agp] Could not add agpTexture mapping\n" );
302 return 0;
303 }
304 /* should i map it ? */
305 fprintf( stderr,
306 "[agp] agpTexture handle = 0x%08x\n",
307 pMga->agpTextures.handle );
308 fprintf( stderr,
309 "[agp] agpTexture size: %d kb\n", pMga->agpTextures.size/1024 );
310
311 return 1;
312 }
313
314 static int MGADRIMapInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
315 {
316 pMga->registers.size = MGAIOMAPSIZE;
317
318 if ( drmAddMap( ctx->drmFD,
319 (drm_handle_t)pMga->IOAddress,
320 pMga->registers.size,
321 DRM_REGISTERS, DRM_READ_ONLY,
322 &pMga->registers.handle ) < 0 ) {
323 fprintf( stderr,
324 "[drm] Could not add MMIO registers mapping\n" );
325 return 0;
326 }
327 fprintf( stderr,
328 "[drm] Registers handle = 0x%08lx\n",
329 pMga->registers.handle );
330
331 pMga->status.size = SAREA_MAX;
332
333 if ( drmAddMap( ctx->drmFD, 0, pMga->status.size,
334 DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
335 &pMga->status.handle ) < 0 ) {
336 fprintf( stderr,
337 "[drm] Could not add status page mapping\n" );
338 return 0;
339 }
340 fprintf( stderr,
341 "[drm] Status handle = 0x%08x\n",
342 pMga->status.handle );
343
344 if ( drmMap( ctx->drmFD,
345 pMga->status.handle,
346 pMga->status.size,
347 &pMga->status.map ) < 0 ) {
348 fprintf( stderr,
349 "[agp] Could not map status page\n" );
350 return 0;
351 }
352 fprintf( stderr,
353 "[agp] Status page mapped at 0x%08lx\n",
354 (unsigned long)pMga->status.map );
355
356 return 1;
357 }
358
359 static int MGADRIKernelInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
360 {
361 drm_mga_init_t init;
362 int ret;
363
364 memset( &init, 0, sizeof(init) );
365
366 init.func = MGA_INIT_DMA;
367 init.sarea_priv_offset = sizeof(drm_sarea_t);
368
369 switch ( pMga->Chipset ) {
370 case PCI_CHIP_MGAG550:
371 case PCI_CHIP_MGAG400:
372 init.chipset = MGA_CARD_TYPE_G400;
373 break;
374 case PCI_CHIP_MGAG200:
375 case PCI_CHIP_MGAG200_PCI:
376 init.chipset = MGA_CARD_TYPE_G200;
377 break;
378 default:
379 return 0;
380 }
381
382 init.sgram = 0; /* FIXME !pMga->HasSDRAM; */
383
384
385 switch (ctx->bpp)
386 {
387 case 16:
388 init.maccess = MGA_MACCESS_PW16;
389 break;
390 case 32:
391 init.maccess = MGA_MACCESS_PW32;
392 break;
393 default:
394 fprintf( stderr, "[mga] invalid bpp (%d)\n", ctx->bpp );
395 return 0;
396 }
397
398
399 init.fb_cpp = ctx->bpp / 8;
400 init.front_offset = pMga->frontOffset;
401 init.front_pitch = pMga->frontPitch / init.fb_cpp;
402 init.back_offset = pMga->backOffset;
403 init.back_pitch = pMga->backPitch / init.fb_cpp;
404
405 init.depth_cpp = ctx->bpp / 8;
406 init.depth_offset = pMga->depthOffset;
407 init.depth_pitch = pMga->depthPitch / init.depth_cpp;
408
409 init.texture_offset[0] = pMga->textureOffset;
410 init.texture_size[0] = pMga->textureSize;
411
412 init.fb_offset = ctx->shared.hFrameBuffer;
413 init.mmio_offset = pMga->registers.handle;
414 init.status_offset = pMga->status.handle;
415
416 init.warp_offset = pMga->warp.handle;
417 init.primary_offset = pMga->primary.handle;
418 init.buffers_offset = pMga->buffers.handle;
419
420 init.texture_offset[1] = pMga->agpTextures.handle;
421 init.texture_size[1] = pMga->agpTextures.size;
422
423 ret = drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(init));
424 if ( ret < 0 ) {
425 fprintf( stderr,
426 "[drm] Failed to initialize DMA! (%d)\n", ret );
427 return 0;
428 }
429
430 return 1;
431 }
432
433 static void MGADRIIrqInit(struct DRIDriverContextRec *ctx, MGAPtr pMga)
434 {
435 if (!pMga->irq)
436 {
437 pMga->irq = drmGetInterruptFromBusID(ctx->drmFD,
438 ctx->pciBus,
439 ctx->pciDevice,
440 ctx->pciFunc);
441
442 fprintf(stderr, "[drm] got IRQ %d\n", pMga->irq);
443
444 if((drmCtlInstHandler(ctx->drmFD, pMga->irq)) != 0)
445 {
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 pMga->irq = 0;
451 }
452 else
453 {
454 pMga->reg_ien = INREG( MGAREG_IEN );
455 }
456 }
457
458 if (pMga->irq)
459 fprintf(stderr,
460 "[drm] dma control initialized, using IRQ %d\n",
461 pMga->irq);
462 }
463
464 static int MGADRIBuffersInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
465 {
466 pMga->drmBuffers = drmMapBufs( ctx->drmFD );
467 if ( !pMga->drmBuffers )
468 {
469 fprintf( stderr,
470 "[drm] Failed to map DMA buffers list\n" );
471 return 0;
472 }
473
474 fprintf( stderr,
475 "[drm] Mapped %d DMA buffers\n",
476 pMga->drmBuffers->count );
477
478 return 1;
479 }
480
481 static int MGAMemoryInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
482 {
483 int width_bytes = ctx->shared.virtualWidth * ctx->cpp;
484 int bufferSize = ((ctx->shared.virtualHeight * width_bytes
485 + MGA_BUFFER_ALIGN)
486 & ~MGA_BUFFER_ALIGN);
487 int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes
488 + MGA_BUFFER_ALIGN)
489 & ~MGA_BUFFER_ALIGN);
490 int l;
491
492 pMga->frontOffset = 0;
493 pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp;
494
495 fprintf(stderr,
496 "Using %d MB AGP aperture\n", pMga->agpSize);
497 fprintf(stderr,
498 "Using %d MB for vertex/indirect buffers\n", pMga->buffers.size>>20);
499 fprintf(stderr,
500 "Using %d MB for AGP textures\n", pMga->agpTextures.size>>20);
501
502 /* Front, back and depth buffers - everything else texture??
503 */
504 pMga->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;
505
506 if (pMga->textureSize < 0)
507 return 0;
508
509 l = mylog2( pMga->textureSize / MGA_NR_TEX_REGIONS );
510 if ( l < MGA_LOG_MIN_TEX_REGION_SIZE )
511 l = MGA_LOG_MIN_TEX_REGION_SIZE;
512
513 /* Round the texture size up to the nearest whole number of
514 * texture regions. Again, be greedy about this, don't
515 * round down.
516 */
517 pMga->logTextureGranularity = l;
518 pMga->textureSize = (pMga->textureSize >> l) << l;
519
520 /* Set a minimum usable local texture heap size. This will fit
521 * two 256x256x32bpp textures.
522 */
523 if (pMga->textureSize < 512 * 1024) {
524 pMga->textureOffset = 0;
525 pMga->textureSize = 0;
526 }
527
528 /* Reserve space for textures */
529 pMga->textureOffset = ((ctx->shared.fbSize - pMga->textureSize +
530 MGA_BUFFER_ALIGN) &
531 ~MGA_BUFFER_ALIGN);
532
533 /* Reserve space for the shared depth
534 * buffer.
535 */
536 pMga->depthOffset = ((pMga->textureOffset - depthSize +
537 MGA_BUFFER_ALIGN) &
538 ~MGA_BUFFER_ALIGN);
539 pMga->depthPitch = ctx->shared.virtualWidth * ctx->cpp;
540
541 pMga->backOffset = ((pMga->depthOffset - bufferSize +
542 MGA_BUFFER_ALIGN) &
543 ~MGA_BUFFER_ALIGN);
544 pMga->backPitch = ctx->shared.virtualWidth * ctx->cpp;
545
546
547 fprintf(stderr,
548 "Will use back buffer at offset 0x%x\n",
549 pMga->backOffset);
550 fprintf(stderr,
551 "Will use depth buffer at offset 0x%x\n",
552 pMga->depthOffset);
553 fprintf(stderr,
554 "Will use %d kb for textures at offset 0x%x\n",
555 pMga->textureSize/1024, pMga->textureOffset);
556
557 return 1;
558 }
559
560 static int MGACheckDRMVersion( struct DRIDriverContextRec *ctx, MGAPtr pMga )
561 {
562 drmVersionPtr version;
563
564 /* Check the MGA DRM version */
565 version = drmGetVersion(ctx->drmFD);
566 if ( version ) {
567 if ( version->version_major != 3 ||
568 version->version_minor < 0 ) {
569 /* incompatible drm version */
570 fprintf( stderr,
571 "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
572 "[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n"
573 "[dri] Disabling DRI.\n",
574 version->version_major,
575 version->version_minor,
576 version->version_patchlevel );
577 drmFreeVersion( version );
578 return 0;
579 }
580 drmFreeVersion( version );
581 }
582
583 return 1;
584 }
585
586 static void print_client_msg( MGADRIPtr pMGADRI )
587 {
588 fprintf( stderr, "chipset: %d\n", pMGADRI->chipset );
589
590 fprintf( stderr, "width: %d\n", pMGADRI->width );
591 fprintf( stderr, "height: %d\n", pMGADRI->height );
592 fprintf( stderr, "mem: %d\n", pMGADRI->mem );
593 fprintf( stderr, "cpp: %d\n", pMGADRI->cpp );
594
595 fprintf( stderr, "agpMode: %d\n", pMGADRI->agpMode );
596
597 fprintf( stderr, "frontOffset: %d\n", pMGADRI->frontOffset );
598 fprintf( stderr, "frontPitch: %d\n", pMGADRI->frontPitch );
599
600 fprintf( stderr, "backOffset: %d\n", pMGADRI->backOffset );
601 fprintf( stderr, "backPitch: %d\n", pMGADRI->backPitch );
602
603 fprintf( stderr, "depthOffset: %d\n", pMGADRI->depthOffset );
604 fprintf( stderr, "depthPitch: %d\n", pMGADRI->depthPitch );
605
606 fprintf( stderr, "textureOffset: %d\n", pMGADRI->textureOffset );
607 fprintf( stderr, "textureSize: %d\n", pMGADRI->textureSize );
608
609 fprintf( stderr, "logTextureGranularity: %d\n", pMGADRI->logTextureGranularity );
610 fprintf( stderr, "logAgpTextureGranularity: %d\n", pMGADRI->logAgpTextureGranularity );
611
612 fprintf( stderr, "agpTextureHandle: %u\n", (unsigned int)pMGADRI->agpTextureOffset );
613 fprintf( stderr, "agpTextureSize: %u\n", (unsigned int)pMGADRI->agpTextureSize );
614
615 #if 0
616 pMGADRI->registers.handle = pMga->registers.handle;
617 pMGADRI->registers.size = pMga->registers.size;
618 pMGADRI->status.handle = pMga->status.handle;
619 pMGADRI->status.size = pMga->status.size;
620 pMGADRI->primary.handle = pMga->primary.handle;
621 pMGADRI->primary.size = pMga->primary.size;
622 pMGADRI->buffers.handle = pMga->buffers.handle;
623 pMGADRI->buffers.size = pMga->buffers.size;
624 pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t);
625 #endif
626 }
627
628 static int MGAScreenInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
629 {
630 int i;
631 int err;
632 MGADRIPtr pMGADRI;
633
634 usleep(100);
635 /*assert(!ctx->IsClient);*/
636
637 {
638 int width_bytes = (ctx->shared.virtualWidth * ctx->cpp);
639 int maxy = ctx->shared.fbSize / width_bytes;
640
641
642 if (maxy <= ctx->shared.virtualHeight * 3) {
643 fprintf(stderr,
644 "Static buffer allocation failed -- "
645 "need at least %d kB video memory (have %d kB)\n",
646 (ctx->shared.virtualWidth * ctx->shared.virtualHeight *
647 ctx->cpp * 3 + 1023) / 1024,
648 ctx->shared.fbSize / 1024);
649 return 0;
650 }
651 }
652
653 switch(pMga->Chipset) {
654 case PCI_CHIP_MGAG550:
655 case PCI_CHIP_MGAG400:
656 case PCI_CHIP_MGAG200:
657 #if 0
658 case PCI_CHIP_MGAG200_PCI:
659 #endif
660 break;
661 default:
662 fprintf(stderr, "[drm] Direct rendering only supported with G200/G400/G550 AGP\n");
663 return 0;
664 }
665
666 fprintf( stderr,
667 "[drm] bpp: %d depth: %d\n",
668 ctx->bpp, ctx->bpp /* FIXME: depth */ );
669
670 if ( (ctx->bpp / 8) != 2 &&
671 (ctx->bpp / 8) != 4 ) {
672 fprintf( stderr,
673 "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
674 return 0;
675 }
676
677 ctx->shared.SAREASize = SAREA_MAX;
678
679
680 /* Note that drmOpen will try to load the kernel module, if needed. */
681 ctx->drmFD = drmOpen("mga", NULL );
682 if (ctx->drmFD < 0) {
683 fprintf(stderr, "[drm] drmOpen failed\n");
684 return 0;
685 }
686
687 if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
688 fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
689 ctx->drmFD, ctx->pciBusID, strerror(-err));
690 return 0;
691 }
692
693
694 if (drmAddMap( ctx->drmFD,
695 0,
696 ctx->shared.SAREASize,
697 DRM_SHM,
698 DRM_CONTAINS_LOCK,
699 &ctx->shared.hSAREA) < 0)
700 {
701 fprintf(stderr, "[drm] drmAddMap failed\n");
702 return 0;
703 }
704 fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
705 ctx->shared.SAREASize, ctx->shared.hSAREA);
706
707 if (drmMap( ctx->drmFD,
708 ctx->shared.hSAREA,
709 ctx->shared.SAREASize,
710 (drmAddressPtr)(&ctx->pSAREA)) < 0)
711 {
712 fprintf(stderr, "[drm] drmMap failed\n");
713 return 0;
714 }
715 memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
716 fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
717 ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
718
719 /* Need to AddMap the framebuffer and mmio regions here:
720 */
721 if (drmAddMap( ctx->drmFD,
722 (drm_handle_t)ctx->FBStart,
723 ctx->FBSize,
724 DRM_FRAME_BUFFER,
725 0,
726 &ctx->shared.hFrameBuffer) < 0)
727 {
728 fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
729 return 0;
730 }
731 fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
732 ctx->shared.hFrameBuffer);
733
734
735 #if 0 /* will be done in MGADRIMapInit */
736 if (drmAddMap(ctx->drmFD,
737 ctx->FixedInfo.mmio_start,
738 ctx->FixedInfo.mmio_len,
739 DRM_REGISTERS,
740 DRM_READ_ONLY,
741 &pMga->registers.handle) < 0) {
742 fprintf(stderr, "[drm] drmAddMap mmio failed\n");
743 return 0;
744 }
745 fprintf(stderr,
746 "[drm] register handle = 0x%08lx\n", pMga->registers.handle);
747 #endif
748
749
750 /* Check the mga DRM version */
751 if (!MGACheckDRMVersion(ctx, pMga)) {
752 return 0;
753 }
754
755 if ( !MGADRIAgpInit( ctx, pMga ) ) {
756 return 0;
757 }
758
759 if ( !MGADRIMapInit( ctx, pMga ) ) {
760 return 0;
761 }
762
763 /* Memory manager setup */
764 if (!MGAMemoryInit(ctx, pMga)) {
765 return 0;
766 }
767
768
769 /* Create a 'server' context so we can grab the lock for
770 * initialization ioctls.
771 */
772 if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
773 fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
774 return 0;
775 }
776
777 DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
778
779 /* Initialize the kernel data structures */
780 if (!MGADRIKernelInit(ctx, pMga)) {
781 fprintf(stderr, "MGADRIKernelInit failed\n");
782 DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
783 return 0;
784 }
785
786 /* Initialize the vertex buffers list */
787 if (!MGADRIBuffersInit(ctx, pMga)) {
788 fprintf(stderr, "MGADRIBuffersInit failed\n");
789 DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
790 return 0;
791 }
792
793 /* Initialize IRQ */
794 MGADRIIrqInit(ctx, pMga);
795
796
797 /* Initialize the SAREA private data structure */
798 {
799 drm_mga_sarea_t *pSAREAPriv;
800 pSAREAPriv = (drm_mga_sarea_t *)(((char*)ctx->pSAREA) +
801 sizeof(drm_sarea_t));
802 memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
803 }
804
805 /* Quick hack to clear the front & back buffers. Could also use
806 * the clear ioctl to do this, but would need to setup hw state
807 * first.
808 */
809 drimemsetio((char *)ctx->FBAddress + pMga->frontOffset,
810 0,
811 pMga->frontPitch * ctx->shared.virtualHeight );
812
813 drimemsetio((char *)ctx->FBAddress + pMga->backOffset,
814 0,
815 pMga->backPitch * ctx->shared.virtualHeight );
816
817 /* Can release the lock now */
818 /* DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);*/
819
820 /* This is the struct passed to radeon_dri.so for its initialization */
821 ctx->driverClientMsg = malloc(sizeof(MGADRIRec));
822 ctx->driverClientMsgSize = sizeof(MGADRIRec);
823
824 pMGADRI = (MGADRIPtr)ctx->driverClientMsg;
825
826
827 switch(pMga->Chipset) {
828 case PCI_CHIP_MGAG550:
829 case PCI_CHIP_MGAG400:
830 pMGADRI->chipset = MGA_CARD_TYPE_G400;
831 break;
832 case PCI_CHIP_MGAG200:
833 case PCI_CHIP_MGAG200_PCI:
834 pMGADRI->chipset = MGA_CARD_TYPE_G200;
835 break;
836 default:
837 return 0;
838 }
839 pMGADRI->width = ctx->shared.virtualWidth;
840 pMGADRI->height = ctx->shared.virtualHeight;
841 pMGADRI->mem = ctx->shared.fbSize;
842 pMGADRI->cpp = ctx->bpp / 8;
843
844 pMGADRI->agpMode = pMga->agpMode;
845
846 pMGADRI->frontOffset = pMga->frontOffset;
847 pMGADRI->frontPitch = pMga->frontPitch;
848 pMGADRI->backOffset = pMga->backOffset;
849 pMGADRI->backPitch = pMga->backPitch;
850 pMGADRI->depthOffset = pMga->depthOffset;
851 pMGADRI->depthPitch = pMga->depthPitch;
852 pMGADRI->textureOffset = pMga->textureOffset;
853 pMGADRI->textureSize = pMga->textureSize;
854 pMGADRI->logTextureGranularity = pMga->logTextureGranularity;
855
856 i = mylog2( pMga->agpTextures.size / MGA_NR_TEX_REGIONS );
857 if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
858 i = MGA_LOG_MIN_TEX_REGION_SIZE;
859
860 pMGADRI->logAgpTextureGranularity = i;
861 pMGADRI->agpTextureOffset = (unsigned int)pMga->agpTextures.handle;
862 pMGADRI->agpTextureSize = (unsigned int)pMga->agpTextures.size;
863
864 pMGADRI->registers.handle = pMga->registers.handle;
865 pMGADRI->registers.size = pMga->registers.size;
866 pMGADRI->status.handle = pMga->status.handle;
867 pMGADRI->status.size = pMga->status.size;
868 pMGADRI->primary.handle = pMga->primary.handle;
869 pMGADRI->primary.size = pMga->primary.size;
870 pMGADRI->buffers.handle = pMga->buffers.handle;
871 pMGADRI->buffers.size = pMga->buffers.size;
872 pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t);
873
874 print_client_msg( pMGADRI );
875
876 return 1;
877 }
878
879
880 /**
881 * \brief Validate the fbdev mode.
882 *
883 * \param ctx display handle.
884 *
885 * \return one on success, or zero on failure.
886 *
887 * Saves some registers and returns 1.
888 *
889 * \sa mgaValidateMode().
890 */
891 static int mgaValidateMode( const DRIDriverContext *ctx )
892 {
893 return 1;
894 }
895
896
897 /**
898 * \brief Examine mode returned by fbdev.
899 *
900 * \param ctx display handle.
901 *
902 * \return one on success, or zero on failure.
903 *
904 * Restores registers that fbdev has clobbered and returns 1.
905 *
906 * \sa mgaValidateMode().
907 */
908 static int mgaPostValidateMode( const DRIDriverContext *ctx )
909 {
910 return 1;
911 }
912
913
914 /**
915 * \brief Initialize the framebuffer device mode
916 *
917 * \param ctx display handle.
918 *
919 * \return one on success, or zero on failure.
920 *
921 * Fills in \p info with some default values and some information from \p ctx
922 * and then calls MGAScreenInit() for the screen initialization.
923 *
924 * Before exiting clears the framebuffer memomry accessing it directly.
925 */
926 static int mgaInitFBDev( struct DRIDriverContextRec *ctx )
927 {
928 MGAPtr pMga = calloc(1, sizeof(*pMga));
929
930 {
931 int dummy = ctx->shared.virtualWidth;
932
933 switch (ctx->bpp / 8) {
934 case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
935 case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
936 case 3:
937 case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
938 }
939
940 ctx->shared.virtualWidth = dummy;
941 }
942
943 ctx->driverPrivate = (void *)pMga;
944
945 pMga->agpMode = MGA_DEFAULT_AGP_MODE;
946 pMga->agpSize = MGA_DEFAULT_AGP_SIZE;
947
948 pMga->Chipset = ctx->chipset;
949
950 pMga->IOAddress = ctx->MMIOStart;
951 pMga->IOBase = ctx->MMIOAddress;
952
953 pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp;
954
955 if (!MGAScreenInit( ctx, pMga ))
956 return 0;
957
958 return 1;
959 }
960
961
962 /**
963 * \brief The screen is being closed, so clean up any state and free any
964 * resources used by the DRI.
965 *
966 * \param ctx display handle.
967 *
968 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
969 * private data.
970 */
971 static void mgaHaltFBDev( struct DRIDriverContextRec *ctx )
972 {
973 drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
974 drmClose(ctx->drmFD);
975
976 if (ctx->driverPrivate) {
977 free(ctx->driverPrivate);
978 ctx->driverPrivate = NULL;
979 }
980 }
981
982
983 static int mgaEngineShutdown( const DRIDriverContext *ctx )
984 {
985 fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
986
987 return 1;
988 }
989
990 static int mgaEngineRestore( const DRIDriverContext *ctx )
991 {
992 fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
993
994 return 1;
995 }
996
997 /**
998 * \brief Exported driver interface for Mini GLX.
999 *
1000 * \sa DRIDriverRec.
1001 */
1002 struct DRIDriverRec __driDriver = {
1003 mgaValidateMode,
1004 mgaPostValidateMode,
1005 mgaInitFBDev,
1006 mgaHaltFBDev,
1007 mgaEngineShutdown,
1008 mgaEngineRestore,
1009 0
1010 };
1011
1012
1013
1014
1015 #if 0
1016 void MGADRICloseScreen( ScreenPtr pScreen )
1017 {
1018 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1019 MGAPtr pMga = MGAPTR(pScrn);
1020 MGADRIServerPrivatePtr pMga = pMga->DRIServerInfo;
1021 drmMGAInit init;
1022
1023 if ( pMga->drmBuffers ) {
1024 drmUnmapBufs( pMga->drmBuffers );
1025 pMga->drmBuffers = NULL;
1026 }
1027
1028 if (pMga->irq) {
1029 drmCtlUninstHandler(ctx->drmFD);
1030 pMga->irq = 0;
1031 }
1032
1033 /* Cleanup DMA */
1034 memset( &init, 0, sizeof(drmMGAInit) );
1035 init.func = MGA_CLEANUP_DMA;
1036 drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(drmMGAInit) );
1037
1038 if ( pMga->status.map ) {
1039 drmUnmap( pMga->status.map, pMga->status.size );
1040 pMga->status.map = NULL;
1041 }
1042 if ( pMga->buffers.map ) {
1043 drmUnmap( pMga->buffers.map, pMga->buffers.size );
1044 pMga->buffers.map = NULL;
1045 }
1046 if ( pMga->primary.map ) {
1047 drmUnmap( pMga->primary.map, pMga->primary.size );
1048 pMga->primary.map = NULL;
1049 }
1050 if ( pMga->warp.map ) {
1051 drmUnmap( pMga->warp.map, pMga->warp.size );
1052 pMga->warp.map = NULL;
1053 }
1054
1055 if ( pMga->agpTextures.map ) {
1056 drmUnmap( pMga->agpTextures.map, pMga->agpTextures.size );
1057 pMga->agpTextures.map = NULL;
1058 }
1059
1060 if ( pMga->agp.handle ) {
1061 drmAgpUnbind( ctx->drmFD, pMga->agp.handle );
1062 drmAgpFree( ctx->drmFD, pMga->agp.handle );
1063 pMga->agp.handle = 0;
1064 drmAgpRelease( ctx->drmFD );
1065 }
1066
1067 DRICloseScreen( pScreen );
1068
1069 if ( pMga->pDRIInfo ) {
1070 if ( pMga->pDRIpMga->devPrivate ) {
1071 xfree( pMga->pDRIpMga->devPrivate );
1072 pMga->pDRIpMga->devPrivate = 0;
1073 }
1074 DRIDestroyInfoRec( pMga->pDRIInfo );
1075 pMga->pDRIInfo = 0;
1076 }
1077 if ( pMga->DRIServerInfo ) {
1078 xfree( pMga->DRIServerInfo );
1079 pMga->DRIServerInfo = 0;
1080 }
1081 if ( pMga->pVisualConfigs ) {
1082 xfree( pMga->pVisualConfigs );
1083 }
1084 if ( pMga->pVisualConfigsPriv ) {
1085 xfree( pMga->pVisualConfigsPriv );
1086 }
1087 }
1088 #endif