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