eab4ab087a3f91c39f27924684422f937066a2c4
[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
47 /* Quiescence, locking
48 */
49 #define MGA_TIMEOUT 2048
50
51 static void MGAWaitForIdleDMA( struct DRIDriverContextRec *ctx, MGAPtr pMga )
52 {
53 drmMGALock lock;
54 int ret;
55 int i = 0;
56
57 memset( &lock, 0, sizeof(drmMGALock) );
58
59 for (;;) {
60 do {
61 /* first ask for quiescent and flush */
62 lock.flags = DRM_MGA_LOCK_QUIESCENT | DRM_MGA_LOCK_FLUSH;
63 do {
64 ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
65 &lock, sizeof( drmMGALock ) );
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_MGA_LOCK_QUIESCENT;
71 do {
72 ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
73 &lock, sizeof( drmMGALock ) );
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%08lx\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%08lx\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%08lx\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%08lx\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 (drmHandle)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%08lx\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 drmMGAInit init;
362 int ret;
363
364 memset( &init, 0, sizeof(drmMGAInit) );
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(drmMGAInit));
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 (drmHandle)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 MGASAREAPrivPtr pSAREAPriv;
800 pSAREAPriv = (MGASAREAPrivPtr)(((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 memset((char *)ctx->FBAddress + pMga->frontOffset,
810 0,
811 pMga->frontPitch * ctx->shared.virtualHeight );
812
813 memset((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 Establish the set of modes available for the display.
882 *
883 * \param ctx display handle.
884 * \param numModes will receive the number of supported modes.
885 * \param modes will point to the list of supported modes.
886 *
887 * \return one on success, or zero on failure.
888 *
889 * Allocates a single visual and fills it with information according to the
890 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
891 * otherwise.
892 */
893 const __GLcontextModes __glModes[] = {
894
895 /* 32 bit, RGBA Depth=24 Stencil=8 */
896 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
897 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
898 .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
899 .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
900 .rgbBits = 32, .indexBits = 0,
901 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
902 .depthBits = 24, .stencilBits = 8,
903 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
904
905 /* 16 bit, RGB Depth=16 */
906 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
907 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
908 .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
909 .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
910 .rgbBits = 16, .indexBits = 0,
911 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
912 .depthBits = 16, .stencilBits = 0,
913 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
914 };
915 static int mgaInitContextModes( const DRIDriverContext *ctx,
916 int *numModes, const __GLcontextModes **modes)
917 {
918 *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
919 *modes = &__glModes[0];
920 return 1;
921 }
922
923
924 /**
925 * \brief Validate the fbdev mode.
926 *
927 * \param ctx display handle.
928 *
929 * \return one on success, or zero on failure.
930 *
931 * Saves some registers and returns 1.
932 *
933 * \sa mgaValidateMode().
934 */
935 static int mgaValidateMode( const DRIDriverContext *ctx )
936 {
937 return 1;
938 }
939
940
941 /**
942 * \brief Examine mode returned by fbdev.
943 *
944 * \param ctx display handle.
945 *
946 * \return one on success, or zero on failure.
947 *
948 * Restores registers that fbdev has clobbered and returns 1.
949 *
950 * \sa mgaValidateMode().
951 */
952 static int mgaPostValidateMode( const DRIDriverContext *ctx )
953 {
954 return 1;
955 }
956
957
958 /**
959 * \brief Initialize the framebuffer device mode
960 *
961 * \param ctx display handle.
962 *
963 * \return one on success, or zero on failure.
964 *
965 * Fills in \p info with some default values and some information from \p ctx
966 * and then calls MGAScreenInit() for the screen initialization.
967 *
968 * Before exiting clears the framebuffer memomry accessing it directly.
969 */
970 static int mgaInitFBDev( struct DRIDriverContextRec *ctx )
971 {
972 MGAPtr pMga = calloc(1, sizeof(*pMga));
973
974 {
975 int dummy = ctx->shared.virtualWidth;
976
977 switch (ctx->bpp / 8) {
978 case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
979 case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
980 case 3:
981 case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
982 }
983
984 ctx->shared.virtualWidth = dummy;
985 }
986
987 ctx->driverPrivate = (void *)pMga;
988
989 pMga->agpMode = MGA_DEFAULT_AGP_MODE;
990 pMga->agpSize = MGA_DEFAULT_AGP_SIZE;
991
992 pMga->Chipset = ctx->chipset;
993
994 pMga->IOAddress = ctx->MMIOStart;
995 pMga->IOBase = ctx->MMIOAddress;
996
997 pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp;
998
999 if (!MGAScreenInit( ctx, pMga ))
1000 return 0;
1001
1002 return 1;
1003 }
1004
1005
1006 /**
1007 * \brief The screen is being closed, so clean up any state and free any
1008 * resources used by the DRI.
1009 *
1010 * \param ctx display handle.
1011 *
1012 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1013 * private data.
1014 */
1015 static void mgaHaltFBDev( struct DRIDriverContextRec *ctx )
1016 {
1017 drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
1018 drmClose(ctx->drmFD);
1019
1020 if (ctx->driverPrivate) {
1021 free(ctx->driverPrivate);
1022 ctx->driverPrivate = NULL;
1023 }
1024 }
1025
1026
1027 static int mgaEngineShutdown( const DRIDriverContext *ctx )
1028 {
1029 fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
1030
1031 return 1;
1032 }
1033
1034 static int mgaEngineRestore( const DRIDriverContext *ctx )
1035 {
1036 fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
1037
1038 return 1;
1039 }
1040
1041 /**
1042 * \brief Exported driver interface for Mini GLX.
1043 *
1044 * \sa DRIDriverRec.
1045 */
1046 struct DRIDriverRec __driDriver = {
1047 mgaInitContextModes,
1048 mgaValidateMode,
1049 mgaPostValidateMode,
1050 mgaInitFBDev,
1051 mgaHaltFBDev,
1052 mgaEngineShutdown,
1053 mgaEngineRestore,
1054 0
1055 };
1056
1057
1058
1059
1060 #if 0
1061 void MGADRICloseScreen( ScreenPtr pScreen )
1062 {
1063 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1064 MGAPtr pMga = MGAPTR(pScrn);
1065 MGADRIServerPrivatePtr pMga = pMga->DRIServerInfo;
1066 drmMGAInit init;
1067
1068 if ( pMga->drmBuffers ) {
1069 drmUnmapBufs( pMga->drmBuffers );
1070 pMga->drmBuffers = NULL;
1071 }
1072
1073 if (pMga->irq) {
1074 drmCtlUninstHandler(ctx->drmFD);
1075 pMga->irq = 0;
1076 }
1077
1078 /* Cleanup DMA */
1079 memset( &init, 0, sizeof(drmMGAInit) );
1080 init.func = MGA_CLEANUP_DMA;
1081 drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(drmMGAInit) );
1082
1083 if ( pMga->status.map ) {
1084 drmUnmap( pMga->status.map, pMga->status.size );
1085 pMga->status.map = NULL;
1086 }
1087 if ( pMga->buffers.map ) {
1088 drmUnmap( pMga->buffers.map, pMga->buffers.size );
1089 pMga->buffers.map = NULL;
1090 }
1091 if ( pMga->primary.map ) {
1092 drmUnmap( pMga->primary.map, pMga->primary.size );
1093 pMga->primary.map = NULL;
1094 }
1095 if ( pMga->warp.map ) {
1096 drmUnmap( pMga->warp.map, pMga->warp.size );
1097 pMga->warp.map = NULL;
1098 }
1099
1100 if ( pMga->agpTextures.map ) {
1101 drmUnmap( pMga->agpTextures.map, pMga->agpTextures.size );
1102 pMga->agpTextures.map = NULL;
1103 }
1104
1105 if ( pMga->agp.handle ) {
1106 drmAgpUnbind( ctx->drmFD, pMga->agp.handle );
1107 drmAgpFree( ctx->drmFD, pMga->agp.handle );
1108 pMga->agp.handle = 0;
1109 drmAgpRelease( ctx->drmFD );
1110 }
1111
1112 DRICloseScreen( pScreen );
1113
1114 if ( pMga->pDRIInfo ) {
1115 if ( pMga->pDRIpMga->devPrivate ) {
1116 xfree( pMga->pDRIpMga->devPrivate );
1117 pMga->pDRIpMga->devPrivate = 0;
1118 }
1119 DRIDestroyInfoRec( pMga->pDRIInfo );
1120 pMga->pDRIInfo = 0;
1121 }
1122 if ( pMga->DRIServerInfo ) {
1123 xfree( pMga->DRIServerInfo );
1124 pMga->DRIServerInfo = 0;
1125 }
1126 if ( pMga->pVisualConfigs ) {
1127 xfree( pMga->pVisualConfigs );
1128 }
1129 if ( pMga->pVisualConfigsPriv ) {
1130 xfree( pMga->pVisualConfigsPriv );
1131 }
1132 }
1133 #endif