1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */
3 * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
4 * Precision Insight, Inc., Cedar Park, Texas, and
5 * VA Linux Systems Inc., Fremont, California.
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation on the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial
19 * portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
25 * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
33 * Kevin E. Martin <martin@valinux.com>
34 * Rickard E. Faith <faith@valinux.com>
35 * Daryll Strauss <daryll@valinux.com>
36 * Gareth Hughes <gareth@valinux.com>
45 // Fix this to use kernel pci_ids.h when all of these IDs make it into the kernel
54 #include "r128_macros.h"
56 #include "r128_version.h"
59 static size_t r128_drm_page_size
;
61 /* Compute log base 2 of val. */
62 static int R128MinBits(int val
)
67 for (bits
= 0; val
; val
>>= 1, ++bits
);
71 /* Initialize the AGP state. Request memory for use in AGP space, and
72 initialize the Rage 128 registers to point to that memory. */
73 static GLboolean
R128DRIAgpInit(const DRIDriverContext
*ctx
)
75 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
76 R128InfoPtr info
= ctx
->driverPrivate
;
78 unsigned int vendor
, device
;
80 unsigned long cntl
, chunk
;
83 unsigned long agpBase
;
85 if (drmAgpAcquire(ctx
->drmFD
) < 0) {
86 fprintf(stderr
, "[agp] AGP not available\n");
90 /* Modify the mode if the default mode is
91 not appropriate for this particular
92 combination of graphics card and AGP
95 mode
= drmAgpGetMode(ctx
->drmFD
); /* Default mode */
96 vendor
= drmAgpVendorId(ctx
->drmFD
);
97 device
= drmAgpDeviceId(ctx
->drmFD
);
99 mode
&= ~R128_AGP_MODE_MASK
;
100 switch (info
->agpMode
) {
101 case 4: mode
|= R128_AGP_4X_MODE
;
102 case 2: mode
|= R128_AGP_2X_MODE
;
103 case 1: default: mode
|= R128_AGP_1X_MODE
;
107 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
108 mode
, vendor
, device
,
112 if (drmAgpEnable(ctx
->drmFD
, mode
) < 0) {
113 fprintf(stderr
, "[agp] AGP not enabled\n");
114 drmAgpRelease(ctx
->drmFD
);
120 if ((ret
= drmAgpAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024, 0, NULL
,
121 &info
->agpMemHandle
)) < 0) {
122 fprintf(stderr
, "[agp] Out of memory (%d)\n", ret
);
123 drmAgpRelease(ctx
->drmFD
);
127 "[agp] %d kB allocated with handle 0x%08x\n",
128 info
->agpSize
*1024, info
->agpMemHandle
);
130 if (drmAgpBind(ctx
->drmFD
, info
->agpMemHandle
, info
->agpOffset
) < 0) {
131 fprintf(stderr
, "[agp] Could not bind\n");
132 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
133 drmAgpRelease(ctx
->drmFD
);
137 /* Initialize the CCE ring buffer data */
138 info
->ringStart
= info
->agpOffset
;
139 info
->ringMapSize
= info
->ringSize
*1024*1024 + r128_drm_page_size
;
140 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
142 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
143 info
->ringReadMapSize
= r128_drm_page_size
;
145 /* Reserve space for vertex/indirect buffers */
146 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
147 info
->bufMapSize
= info
->bufSize
*1024*1024;
149 /* Reserve the rest for AGP textures */
150 info
->agpTexStart
= info
->bufStart
+ info
->bufMapSize
;
151 s
= (info
->agpSize
*1024*1024 - info
->agpTexStart
);
152 l
= R128MinBits((s
-1) / R128_NR_TEX_REGIONS
);
153 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
154 info
->agpTexMapSize
= (s
>> l
) << l
;
155 info
->log2AGPTexGran
= l
;
157 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
160 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
161 DRM_AGP
, flags
, &info
->ringHandle
) < 0) {
163 "[agp] Could not add ring mapping\n");
167 "[agp] ring handle = 0x%08x\n", info
->ringHandle
);
169 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
170 (drmAddressPtr
)&info
->ring
) < 0) {
171 fprintf(stderr
, "[agp] Could not map ring\n");
175 "[agp] Ring mapped at 0x%08lx\n",
176 (unsigned long)info
->ring
);
178 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
179 DRM_AGP
, flags
, &info
->ringReadPtrHandle
) < 0) {
181 "[agp] Could not add ring read ptr mapping\n");
185 "[agp] ring read ptr handle = 0x%08x\n",
186 info
->ringReadPtrHandle
);
188 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
189 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
191 "[agp] Could not map ring read ptr\n");
195 "[agp] Ring read ptr mapped at 0x%08lx\n",
196 (unsigned long)info
->ringReadPtr
);
198 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
199 DRM_AGP
, 0, &info
->bufHandle
) < 0) {
201 "[agp] Could not add vertex/indirect buffers mapping\n");
205 "[agp] vertex/indirect buffers handle = 0x%08lx\n",
208 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
209 (drmAddressPtr
)&info
->buf
) < 0) {
211 "[agp] Could not map vertex/indirect buffers\n");
215 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
216 (unsigned long)info
->buf
);
218 if (drmAddMap(ctx
->drmFD
, info
->agpTexStart
, info
->agpTexMapSize
,
219 DRM_AGP
, 0, &info
->agpTexHandle
) < 0) {
221 "[agp] Could not add AGP texture map mapping\n");
225 "[agp] AGP texture map handle = 0x%08lx\n",
228 if (drmMap(ctx
->drmFD
, info
->agpTexHandle
, info
->agpTexMapSize
,
229 (drmAddressPtr
)&info
->agpTex
) < 0) {
231 "[agp] Could not map AGP texture map\n");
235 "[agp] AGP Texture map mapped at 0x%08lx\n",
236 (unsigned long)info
->agpTex
);
238 /* Initialize Rage 128's AGP registers */
239 cntl
= INREG(R128_AGP_CNTL
);
240 cntl
&= ~R128_AGP_APER_SIZE_MASK
;
241 switch (info
->agpSize
) {
242 case 256: cntl
|= R128_AGP_APER_SIZE_256MB
; break;
243 case 128: cntl
|= R128_AGP_APER_SIZE_128MB
; break;
244 case 64: cntl
|= R128_AGP_APER_SIZE_64MB
; break;
245 case 32: cntl
|= R128_AGP_APER_SIZE_32MB
; break;
246 case 16: cntl
|= R128_AGP_APER_SIZE_16MB
; break;
247 case 8: cntl
|= R128_AGP_APER_SIZE_8MB
; break;
248 case 4: cntl
|= R128_AGP_APER_SIZE_4MB
; break;
251 "[agp] Illegal aperture size %d kB\n",
255 agpBase
= drmAgpBase(ctx
->drmFD
);
256 OUTREG(R128_AGP_BASE
, agpBase
);
257 OUTREG(R128_AGP_CNTL
, cntl
);
259 /* Disable Rage 128's PCIGART registers */
260 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
261 chunk
&= ~(R128_BM_PTR_FORCE_TO_PCI
|
262 R128_BM_PM4_RD_FORCE_TO_PCI
|
263 R128_BM_GLOBAL_FORCE_TO_PCI
);
264 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
266 OUTREG(R128_PCI_GART_PAGE
, 1); /* Ensure AGP GART is used (for now) */
271 static GLboolean
R128DRIPciInit(const DRIDriverContext
*ctx
)
273 R128InfoPtr info
= ctx
->driverPrivate
;
274 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
281 ret
= drmScatterGatherAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024,
282 &info
->pciMemHandle
);
284 fprintf(stderr
, "[pci] Out of memory (%d)\n", ret
);
288 "[pci] %d kB allocated with handle 0x%08x\n",
289 info
->agpSize
*1024, info
->pciMemHandle
);
291 /* Initialize the CCE ring buffer data */
292 info
->ringStart
= info
->agpOffset
;
293 info
->ringMapSize
= info
->ringSize
*1024*1024 + r128_drm_page_size
;
294 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
296 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
297 info
->ringReadMapSize
= r128_drm_page_size
;
299 /* Reserve space for vertex/indirect buffers */
300 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
301 info
->bufMapSize
= info
->bufSize
*1024*1024;
303 flags
= DRM_READ_ONLY
| DRM_LOCKED
| DRM_KERNEL
;
305 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
306 DRM_SCATTER_GATHER
, flags
, &info
->ringHandle
) < 0) {
308 "[pci] Could not add ring mapping\n");
312 "[pci] ring handle = 0x%08lx\n", info
->ringHandle
);
314 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
315 (drmAddressPtr
)&info
->ring
) < 0) {
316 fprintf(stderr
, "[pci] Could not map ring\n");
320 "[pci] Ring mapped at 0x%08lx\n",
321 (unsigned long)info
->ring
);
323 "[pci] Ring contents 0x%08lx\n",
324 *(unsigned long *)info
->ring
);
326 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
327 DRM_SCATTER_GATHER
, flags
, &info
->ringReadPtrHandle
) < 0) {
329 "[pci] Could not add ring read ptr mapping\n");
333 "[pci] ring read ptr handle = 0x%08lx\n",
334 info
->ringReadPtrHandle
);
336 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
337 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
339 "[pci] Could not map ring read ptr\n");
343 "[pci] Ring read ptr mapped at 0x%08lx\n",
344 (unsigned long)info
->ringReadPtr
);
346 "[pci] Ring read ptr contents 0x%08lx\n",
347 *(unsigned long *)info
->ringReadPtr
);
349 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
350 DRM_SCATTER_GATHER
, 0, &info
->bufHandle
) < 0) {
352 "[pci] Could not add vertex/indirect buffers mapping\n");
356 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
359 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
360 (drmAddressPtr
)&info
->buf
) < 0) {
362 "[pci] Could not map vertex/indirect buffers\n");
366 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
367 (unsigned long)info
->buf
);
369 "[pci] Vertex/indirect buffers contents 0x%08lx\n",
370 *(unsigned long *)info
->buf
);
373 /* This is really an AGP card, force PCI GART mode */
374 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
375 chunk
|= (R128_BM_PTR_FORCE_TO_PCI
|
376 R128_BM_PM4_RD_FORCE_TO_PCI
|
377 R128_BM_GLOBAL_FORCE_TO_PCI
);
378 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
379 OUTREG(R128_PCI_GART_PAGE
, 0); /* Ensure PCI GART is used */
385 /* Add a map for the MMIO registers that will be accessed by any
386 DRI-based clients. */
387 static GLboolean
R128DRIMapInit(const DRIDriverContext
*ctx
)
389 R128InfoPtr info
= ctx
->driverPrivate
;
392 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
396 if (drmAddMap(ctx
->drmFD
, ctx
->MMIOStart
, ctx
->MMIOSize
,
397 DRM_REGISTERS
, flags
, &info
->registerHandle
) < 0) {
401 "[drm] register handle = 0x%08x\n", info
->registerHandle
);
406 /* Initialize the kernel data structures. */
407 static int R128DRIKernelInit(const DRIDriverContext
*ctx
)
409 R128InfoPtr info
= ctx
->driverPrivate
;
410 drm_r128_init_t drmInfo
;
412 memset( &drmInfo
, 0, sizeof(&drmInfo
) );
414 drmInfo
.func
= R128_INIT_CCE
;
415 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
416 drmInfo
.is_pci
= info
->IsPCI
;
417 drmInfo
.cce_mode
= info
->CCEMode
;
418 drmInfo
.cce_secure
= info
->CCESecure
;
419 drmInfo
.ring_size
= info
->ringSize
*1024*1024;
420 drmInfo
.usec_timeout
= info
->CCEusecTimeout
;
422 drmInfo
.fb_bpp
= ctx
->bpp
;
423 drmInfo
.depth_bpp
= ctx
->bpp
;
425 drmInfo
.front_offset
= info
->frontOffset
;
426 drmInfo
.front_pitch
= info
->frontPitch
;
428 drmInfo
.back_offset
= info
->backOffset
;
429 drmInfo
.back_pitch
= info
->backPitch
;
431 drmInfo
.depth_offset
= info
->depthOffset
;
432 drmInfo
.depth_pitch
= info
->depthPitch
;
433 drmInfo
.span_offset
= info
->spanOffset
;
435 drmInfo
.fb_offset
= info
->LinearAddr
;
436 drmInfo
.mmio_offset
= info
->registerHandle
;
437 drmInfo
.ring_offset
= info
->ringHandle
;
438 drmInfo
.ring_rptr_offset
= info
->ringReadPtrHandle
;
439 drmInfo
.buffers_offset
= info
->bufHandle
;
440 drmInfo
.agp_textures_offset
= info
->agpTexHandle
;
442 if (drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
443 &drmInfo
, sizeof(drmInfo
)) < 0)
449 /* Add a map for the vertex buffers that will be accessed by any
450 DRI-based clients. */
451 static GLboolean
R128DRIBufInit(const DRIDriverContext
*ctx
)
453 R128InfoPtr info
= ctx
->driverPrivate
;
454 /* Initialize vertex buffers */
456 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
457 info
->bufMapSize
/ R128_BUFFER_SIZE
,
462 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
463 info
->bufMapSize
/ R128_BUFFER_SIZE
,
468 if (info
->bufNumBufs
<= 0) {
470 "[drm] Could not create vertex/indirect buffers list\n");
474 "[drm] Added %d %d byte vertex/indirect buffers\n",
475 info
->bufNumBufs
, R128_BUFFER_SIZE
);
477 if (!(info
->buffers
= drmMapBufs(ctx
->drmFD
))) {
479 "[drm] Failed to map vertex/indirect buffers list\n");
483 "[drm] Mapped %d vertex/indirect buffers\n",
484 info
->buffers
->count
);
489 static void R128DRIIrqInit(const DRIDriverContext
*ctx
)
491 R128InfoPtr info
= ctx
->driverPrivate
;
492 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
495 info
->irq
= drmGetInterruptFromBusID(
501 if((drmCtlInstHandler(ctx
->drmFD
, info
->irq
)) != 0) {
503 "[drm] failure adding irq handler, "
504 "there is a device already using that irq\n"
505 "[drm] falling back to irq-free operation\n");
508 info
->gen_int_cntl
= INREG( R128_GEN_INT_CNTL
);
514 "[drm] dma control initialized, using IRQ %d\n",
518 static int R128CCEStop(const DRIDriverContext
*ctx
)
520 R128InfoPtr info
= ctx
->driverPrivate
;
521 drm_r128_cce_stop_t stop
;
527 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
528 &stop
, sizeof(stop
) );
532 } else if ( errno
!= EBUSY
) {
540 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
541 &stop
, sizeof(stop
) );
542 } while ( ret
&& errno
== EBUSY
&& i
++ < R128_IDLE_RETRY
);
546 } else if ( errno
!= EBUSY
) {
552 if ( drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
553 &stop
, sizeof(stop
) )) {
560 /* Initialize the CCE state, and start the CCE (if used by the X server) */
561 static void R128DRICCEInit(const DRIDriverContext
*ctx
)
563 R128InfoPtr info
= ctx
->driverPrivate
;
565 /* Turn on bus mastering */
566 info
->BusCntl
&= ~R128_BUS_MASTER_DIS
;
568 /* CCEMode is initialized in r128_driver.c */
569 switch (info
->CCEMode
) {
570 case R128_PM4_NONPM4
: info
->CCEFifoSize
= 0; break;
571 case R128_PM4_192PIO
: info
->CCEFifoSize
= 192; break;
572 case R128_PM4_192BM
: info
->CCEFifoSize
= 192; break;
573 case R128_PM4_128PIO_64INDBM
: info
->CCEFifoSize
= 128; break;
574 case R128_PM4_128BM_64INDBM
: info
->CCEFifoSize
= 128; break;
575 case R128_PM4_64PIO_128INDBM
: info
->CCEFifoSize
= 64; break;
576 case R128_PM4_64BM_128INDBM
: info
->CCEFifoSize
= 64; break;
577 case R128_PM4_64PIO_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
578 case R128_PM4_64BM_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
579 case R128_PM4_64PIO_64VCPIO_64INDPIO
: info
->CCEFifoSize
= 64; break;
582 /* Make sure the CCE is on for the X server */
583 R128CCE_START(ctx
, info
);
587 static int R128MemoryInit(const DRIDriverContext
*ctx
)
589 R128InfoPtr info
= ctx
->driverPrivate
;
590 int width_bytes
= ctx
->shared
.virtualWidth
* ctx
->cpp
;
592 int bufferSize
= ((ctx
->shared
.virtualHeight
* width_bytes
594 & ~R128_BUFFER_ALIGN
);
595 int depthSize
= ((((ctx
->shared
.virtualHeight
+15) & ~15) * width_bytes
597 & ~R128_BUFFER_ALIGN
);
600 info
->frontOffset
= 0;
601 info
->frontPitch
= ctx
->shared
.virtualWidth
;
604 "Using %d MB AGP aperture\n", info
->agpSize
);
606 "Using %d MB for the ring buffer\n", info
->ringSize
);
608 "Using %d MB for vertex/indirect buffers\n", info
->bufSize
);
610 "Using %d MB for AGP textures\n", info
->agpTexSize
);
612 /* Front, back and depth buffers - everything else texture??
614 info
->textureSize
= ctx
->shared
.fbSize
- 2 * bufferSize
- depthSize
;
616 if (info
->textureSize
< 0)
619 l
= R128MinBits((info
->textureSize
-1) / R128_NR_TEX_REGIONS
);
620 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
622 /* Round the texture size up to the nearest whole number of
623 * texture regions. Again, be greedy about this, don't
626 info
->log2TexGran
= l
;
627 info
->textureSize
= (info
->textureSize
>> l
) << l
;
629 /* Set a minimum usable local texture heap size. This will fit
630 * two 256x256x32bpp textures.
632 if (info
->textureSize
< 512 * 1024) {
633 info
->textureOffset
= 0;
634 info
->textureSize
= 0;
637 /* Reserve space for textures */
638 info
->textureOffset
= ((ctx
->shared
.fbSize
- info
->textureSize
+
642 /* Reserve space for the shared depth
645 info
->depthOffset
= ((info
->textureOffset
- depthSize
+
648 info
->depthPitch
= ctx
->shared
.virtualWidth
;
650 info
->backOffset
= ((info
->depthOffset
- bufferSize
+
653 info
->backPitch
= ctx
->shared
.virtualWidth
;
657 "Will use back buffer at offset 0x%x\n",
660 "Will use depth buffer at offset 0x%x\n",
663 "Will use %d kb for textures at offset 0x%x\n",
664 info
->textureSize
/1024, info
->textureOffset
);
670 /* Initialize the screen-specific data structures for the DRI and the
671 Rage 128. This is the main entry point to the device-specific
672 initialization code. It calls device-independent DRI functions to
673 create the DRI data structures and initialize the DRI state. */
674 static GLboolean
R128DRIScreenInit(DRIDriverContext
*ctx
)
676 R128InfoPtr info
= ctx
->driverPrivate
;
678 int err
, major
, minor
, patch
;
679 drmVersionPtr version
;
680 drm_r128_sarea_t
*pSAREAPriv
;
684 /* These modes are not supported (yet). */
688 "[dri] R128DRIScreenInit failed (depth %d not supported). "
689 "[dri] Disabling DRI.\n", ctx
->bpp
);
692 /* Only 16 and 32 color depths are supports currently. */
697 r128_drm_page_size
= getpagesize();
699 info
->registerSize
= ctx
->MMIOSize
;
700 ctx
->shared
.SAREASize
= SAREA_MAX
;
702 /* Note that drmOpen will try to load the kernel module, if needed. */
703 ctx
->drmFD
= drmOpen("r128", NULL
);
704 if (ctx
->drmFD
< 0) {
705 fprintf(stderr
, "[drm] drmOpen failed\n");
709 /* Check the r128 DRM version */
710 version
= drmGetVersion(ctx
->drmFD
);
712 if (version
->version_major
!= 2 ||
713 version
->version_minor
< 2) {
714 /* incompatible drm version */
716 "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
717 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
718 "[dri] Disabling the DRI.\n",
719 version
->version_major
,
720 version
->version_minor
,
721 version
->version_patchlevel
);
722 drmFreeVersion(version
);
725 info
->drmMinor
= version
->version_minor
;
726 drmFreeVersion(version
);
729 if ((err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
)) < 0) {
730 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
731 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
735 if (drmAddMap( ctx
->drmFD
,
737 ctx
->shared
.SAREASize
,
740 &ctx
->shared
.hSAREA
) < 0)
742 fprintf(stderr
, "[drm] drmAddMap failed\n");
745 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
746 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
748 if (drmMap( ctx
->drmFD
,
750 ctx
->shared
.SAREASize
,
751 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
753 fprintf(stderr
, "[drm] drmMap failed\n");
756 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
757 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
758 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
760 /* Need to AddMap the framebuffer and mmio regions here:
762 if (drmAddMap( ctx
->drmFD
,
763 (drm_handle_t
)ctx
->FBStart
,
767 &ctx
->shared
.hFrameBuffer
) < 0)
769 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
773 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
774 ctx
->shared
.hFrameBuffer
);
776 if (!R128MemoryInit(ctx
))
780 if (!info
->IsPCI
&& !R128DRIAgpInit(ctx
)) {
781 info
->IsPCI
= GL_TRUE
;
783 "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
785 "[agp] Make sure you have the agpgart kernel module loaded.\n");
788 /* Initialize PCIGART */
789 if (info
->IsPCI
&& !R128DRIPciInit(ctx
)) {
793 /* DRIScreenInit doesn't add all the
794 common mappings. Add additional
796 if (!R128DRIMapInit(ctx
)) {
800 /* Create a 'server' context so we can grab the lock for
801 * initialization ioctls.
803 if ((err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
)) != 0) {
804 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
808 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
810 /* Initialize the kernel data structures */
811 if (!R128DRIKernelInit(ctx
)) {
815 /* Initialize the vertex buffers list */
816 if (!R128DRIBufInit(ctx
)) {
823 /* Initialize and start the CCE if required */
826 /* Quick hack to clear the front & back buffers. Could also use
827 * the clear ioctl to do this, but would need to setup hw state
830 drimemsetio((char *)ctx
->FBAddress
+ info
->frontOffset
,
832 info
->frontPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
834 drimemsetio((char *)ctx
->FBAddress
+ info
->backOffset
,
836 info
->backPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
838 pSAREAPriv
= (drm_r128_sarea_t
*)(((char*)ctx
->pSAREA
) +
839 sizeof(drm_sarea_t
));
840 memset(pSAREAPriv
, 0, sizeof(*pSAREAPriv
));
842 /* This is the struct passed to radeon_dri.so for its initialization */
843 ctx
->driverClientMsg
= malloc(sizeof(R128DRIRec
));
844 ctx
->driverClientMsgSize
= sizeof(R128DRIRec
);
846 pR128DRI
= (R128DRIPtr
)ctx
->driverClientMsg
;
847 pR128DRI
->deviceID
= info
->Chipset
;
848 pR128DRI
->width
= ctx
->shared
.virtualWidth
;
849 pR128DRI
->height
= ctx
->shared
.virtualHeight
;
850 pR128DRI
->depth
= ctx
->bpp
;
851 pR128DRI
->bpp
= ctx
->bpp
;
853 pR128DRI
->IsPCI
= info
->IsPCI
;
854 pR128DRI
->AGPMode
= info
->agpMode
;
856 pR128DRI
->frontOffset
= info
->frontOffset
;
857 pR128DRI
->frontPitch
= info
->frontPitch
;
858 pR128DRI
->backOffset
= info
->backOffset
;
859 pR128DRI
->backPitch
= info
->backPitch
;
860 pR128DRI
->depthOffset
= info
->depthOffset
;
861 pR128DRI
->depthPitch
= info
->depthPitch
;
862 pR128DRI
->spanOffset
= info
->spanOffset
;
863 pR128DRI
->textureOffset
= info
->textureOffset
;
864 pR128DRI
->textureSize
= info
->textureSize
;
865 pR128DRI
->log2TexGran
= info
->log2TexGran
;
867 pR128DRI
->registerHandle
= info
->registerHandle
;
868 pR128DRI
->registerSize
= info
->registerSize
;
870 pR128DRI
->agpTexHandle
= info
->agpTexHandle
;
871 pR128DRI
->agpTexMapSize
= info
->agpTexMapSize
;
872 pR128DRI
->log2AGPTexGran
= info
->log2AGPTexGran
;
873 pR128DRI
->agpTexOffset
= info
->agpTexStart
;
874 pR128DRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
879 /* The screen is being closed, so clean up any state and free any
880 resources used by the DRI. */
881 void R128DRICloseScreen(const DRIDriverContext
*ctx
)
883 R128InfoPtr info
= ctx
->driverPrivate
;
884 drm_r128_init_t drmInfo
;
886 /* Stop the CCE if it is still in use */
887 R128CCE_STOP(ctx
, info
);
890 drmCtlUninstHandler(ctx
->drmFD
);
894 /* De-allocate vertex buffers */
896 drmUnmapBufs(info
->buffers
);
897 info
->buffers
= NULL
;
900 /* De-allocate all kernel resources */
901 memset(&drmInfo
, 0, sizeof(drmInfo
));
902 drmInfo
.func
= R128_CLEANUP_CCE
;
903 drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
904 &drmInfo
, sizeof(drmInfo
));
906 /* De-allocate all AGP resources */
908 drmUnmap(info
->agpTex
, info
->agpTexMapSize
);
912 drmUnmap(info
->buf
, info
->bufMapSize
);
915 if (info
->ringReadPtr
) {
916 drmUnmap(info
->ringReadPtr
, info
->ringReadMapSize
);
917 info
->ringReadPtr
= NULL
;
920 drmUnmap(info
->ring
, info
->ringMapSize
);
923 if (info
->agpMemHandle
!= DRM_AGP_NO_HANDLE
) {
924 drmAgpUnbind(ctx
->drmFD
, info
->agpMemHandle
);
925 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
926 info
->agpMemHandle
= 0;
927 drmAgpRelease(ctx
->drmFD
);
929 if (info
->pciMemHandle
) {
930 drmScatterGatherFree(ctx
->drmFD
, info
->pciMemHandle
);
931 info
->pciMemHandle
= 0;
935 static GLboolean
R128PreInitDRI(const DRIDriverContext
*ctx
)
937 R128InfoPtr info
= ctx
->driverPrivate
;
939 /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
940 info
->CCEMode
= R128_DEFAULT_CCE_BM_MODE
;
941 info
->CCESecure
= GL_TRUE
;
943 info
->agpMode
= R128_DEFAULT_AGP_MODE
;
944 info
->agpSize
= R128_DEFAULT_AGP_SIZE
;
945 info
->ringSize
= R128_DEFAULT_RING_SIZE
;
946 info
->bufSize
= R128_DEFAULT_BUFFER_SIZE
;
947 info
->agpTexSize
= R128_DEFAULT_AGP_TEX_SIZE
;
949 info
->CCEusecTimeout
= R128_DEFAULT_CCE_TIMEOUT
;
955 * \brief Initialize the framebuffer device mode
957 * \param ctx display handle.
959 * \return one on success, or zero on failure.
961 * Fills in \p info with some default values and some information from \p ctx
962 * and then calls R128ScreenInit() for the screen initialization.
964 * Before exiting clears the framebuffer memory accessing it directly.
966 static int R128InitFBDev( DRIDriverContext
*ctx
)
968 R128InfoPtr info
= calloc(1, sizeof(*info
));
971 int dummy
= ctx
->shared
.virtualWidth
;
973 switch (ctx
->bpp
/ 8) {
974 case 1: dummy
= (ctx
->shared
.virtualWidth
+ 127) & ~127; break;
975 case 2: dummy
= (ctx
->shared
.virtualWidth
+ 31) & ~31; break;
977 case 4: dummy
= (ctx
->shared
.virtualWidth
+ 15) & ~15; break;
980 ctx
->shared
.virtualWidth
= dummy
;
983 ctx
->driverPrivate
= (void *)info
;
985 info
->Chipset
= ctx
->chipset
;
987 switch (info
->Chipset
) {
988 case PCI_DEVICE_ID_ATI_RAGE128_LE
:
989 case PCI_DEVICE_ID_ATI_RAGE128_RE
:
990 case PCI_DEVICE_ID_ATI_RAGE128_RK
:
991 case PCI_DEVICE_ID_ATI_RAGE128_PD
:
992 case PCI_DEVICE_ID_ATI_RAGE128_PP
:
993 case PCI_DEVICE_ID_ATI_RAGE128_PR
:
994 /* This is a PCI card */
995 info
->IsPCI
= GL_TRUE
;
998 /* This is an AGP card */
999 info
->IsPCI
= GL_FALSE
;
1003 info
->frontPitch
= ctx
->shared
.virtualWidth
;
1004 info
->LinearAddr
= ctx
->FBStart
& 0xfc000000;
1006 if (!R128PreInitDRI(ctx
))
1009 if (!R128DRIScreenInit(ctx
))
1017 * \brief The screen is being closed, so clean up any state and free any
1018 * resources used by the DRI.
1020 * \param ctx display handle.
1022 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1025 static void R128HaltFBDev( DRIDriverContext
*ctx
)
1027 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1028 drmClose(ctx
->drmFD
);
1030 if (ctx
->driverPrivate
) {
1031 free(ctx
->driverPrivate
);
1032 ctx
->driverPrivate
= 0;
1038 * \brief Validate the fbdev mode.
1040 * \param ctx display handle.
1042 * \return one on success, or zero on failure.
1044 * Saves some registers and returns 1.
1046 * \sa R128PostValidateMode().
1048 static int R128ValidateMode( const DRIDriverContext
*ctx
)
1055 * \brief Examine mode returned by fbdev.
1057 * \param ctx display handle.
1059 * \return one on success, or zero on failure.
1061 * Restores registers that fbdev has clobbered and returns 1.
1063 * \sa R128ValidateMode().
1065 static int R128PostValidateMode( const DRIDriverContext
*ctx
)
1072 * \brief Shutdown the drawing engine.
1074 * \param ctx display handle
1076 * Turns off the command processor engine & restores the graphics card
1077 * to a state that fbdev understands.
1079 static int R128EngineShutdown( const DRIDriverContext
*ctx
)
1085 * \brief Restore the drawing engine.
1087 * \param ctx display handle
1089 * Resets the graphics card and sets initial values for several registers of
1090 * the card's drawing engine.
1092 * Turns on the R128 command processor engine (i.e., the ringbuffer).
1094 static int R128EngineRestore( const DRIDriverContext
*ctx
)
1101 * \brief Exported driver interface for Mini GLX.
1105 const struct DRIDriverRec __driDriver
= {
1107 R128PostValidateMode
,