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