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
53 #include "r128_macros.h"
55 #include "r128_version.h"
59 /* ?? HACK - for now, put this here... */
60 /* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
61 #if defined(__alpha__)
62 # define DRM_PAGE_SIZE 8192
63 #elif defined(__ia64__)
64 # define DRM_PAGE_SIZE getpagesize()
66 # define DRM_PAGE_SIZE 4096
70 * \brief Establish the set of modes available for the display.
72 * \param ctx display handle.
73 * \param numModes will receive the number of supported modes.
74 * \param modes will point to the list of supported modes.
76 * \return one on success, or zero on failure.
78 * Allocates a single visual and fills it with information according to the
79 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
82 const __GLcontextModes __glModes
[] = {
84 /* 32 bit, RGBA Depth=24 Stencil=8 */
85 {.rgbMode
= GL_TRUE
, .colorIndexMode
= GL_FALSE
, .doubleBufferMode
= GL_TRUE
, .stereoMode
= GL_FALSE
,
86 .haveAccumBuffer
= GL_FALSE
, .haveDepthBuffer
= GL_TRUE
, .haveStencilBuffer
= GL_TRUE
,
87 .redBits
= 8, .greenBits
= 8, .blueBits
= 8, .alphaBits
= 8,
88 .redMask
= 0xff0000, .greenMask
= 0xff00, .blueMask
= 0xff, .alphaMask
= 0xff000000,
89 .rgbBits
= 32, .indexBits
= 0,
90 .accumRedBits
= 0, .accumGreenBits
= 0, .accumBlueBits
= 0, .accumAlphaBits
= 0,
91 .depthBits
= 24, .stencilBits
= 8,
92 .numAuxBuffers
= 0, .level
= 0, .pixmapMode
= GL_FALSE
, },
94 /* 16 bit, RGB Depth=16 */
95 {.rgbMode
= GL_TRUE
, .colorIndexMode
= GL_FALSE
, .doubleBufferMode
= GL_TRUE
, .stereoMode
= GL_FALSE
,
96 .haveAccumBuffer
= GL_FALSE
, .haveDepthBuffer
= GL_TRUE
, .haveStencilBuffer
= GL_FALSE
,
97 .redBits
= 5, .greenBits
= 6, .blueBits
= 5, .alphaBits
= 0,
98 .redMask
= 0xf800, .greenMask
= 0x07e0, .blueMask
= 0x001f, .alphaMask
= 0x0,
99 .rgbBits
= 16, .indexBits
= 0,
100 .accumRedBits
= 0, .accumGreenBits
= 0, .accumBlueBits
= 0, .accumAlphaBits
= 0,
101 .depthBits
= 16, .stencilBits
= 0,
102 .numAuxBuffers
= 0, .level
= 0, .pixmapMode
= GL_FALSE
, },
104 static int R128InitContextModes( const DRIDriverContext
*ctx
,
105 int *numModes
, const __GLcontextModes
**modes
)
107 *numModes
= sizeof(__glModes
)/sizeof(__GLcontextModes
*);
108 *modes
= &__glModes
[0];
112 /* Compute log base 2 of val. */
113 static int R128MinBits(int val
)
118 for (bits
= 0; val
; val
>>= 1, ++bits
);
122 /* Initialize the AGP state. Request memory for use in AGP space, and
123 initialize the Rage 128 registers to point to that memory. */
124 static GLboolean
R128DRIAgpInit(const DRIDriverContext
*ctx
)
126 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
127 R128InfoPtr info
= ctx
->driverPrivate
;
129 unsigned int vendor
, device
;
131 unsigned long cntl
, chunk
;
134 unsigned long agpBase
;
136 if (drmAgpAcquire(ctx
->drmFD
) < 0) {
137 fprintf(stderr
, "[agp] AGP not available\n");
141 /* Modify the mode if the default mode is
142 not appropriate for this particular
143 combination of graphics card and AGP
146 mode
= drmAgpGetMode(ctx
->drmFD
); /* Default mode */
147 vendor
= drmAgpVendorId(ctx
->drmFD
);
148 device
= drmAgpDeviceId(ctx
->drmFD
);
150 mode
&= ~R128_AGP_MODE_MASK
;
151 switch (info
->agpMode
) {
152 case 4: mode
|= R128_AGP_4X_MODE
;
153 case 2: mode
|= R128_AGP_2X_MODE
;
154 case 1: default: mode
|= R128_AGP_1X_MODE
;
158 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
159 mode
, vendor
, device
,
163 if (drmAgpEnable(ctx
->drmFD
, mode
) < 0) {
164 fprintf(stderr
, "[agp] AGP not enabled\n");
165 drmAgpRelease(ctx
->drmFD
);
171 if ((ret
= drmAgpAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024, 0, NULL
,
172 &info
->agpMemHandle
)) < 0) {
173 fprintf(stderr
, "[agp] Out of memory (%d)\n", ret
);
174 drmAgpRelease(ctx
->drmFD
);
178 "[agp] %d kB allocated with handle 0x%08x\n",
179 info
->agpSize
*1024, info
->agpMemHandle
);
181 if (drmAgpBind(ctx
->drmFD
, info
->agpMemHandle
, info
->agpOffset
) < 0) {
182 fprintf(stderr
, "[agp] Could not bind\n");
183 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
184 drmAgpRelease(ctx
->drmFD
);
188 /* Initialize the CCE ring buffer data */
189 info
->ringStart
= info
->agpOffset
;
190 info
->ringMapSize
= info
->ringSize
*1024*1024 + DRM_PAGE_SIZE
;
191 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
193 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
194 info
->ringReadMapSize
= DRM_PAGE_SIZE
;
196 /* Reserve space for vertex/indirect buffers */
197 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
198 info
->bufMapSize
= info
->bufSize
*1024*1024;
200 /* Reserve the rest for AGP textures */
201 info
->agpTexStart
= info
->bufStart
+ info
->bufMapSize
;
202 s
= (info
->agpSize
*1024*1024 - info
->agpTexStart
);
203 l
= R128MinBits((s
-1) / R128_NR_TEX_REGIONS
);
204 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
205 info
->agpTexMapSize
= (s
>> l
) << l
;
206 info
->log2AGPTexGran
= l
;
208 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
211 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
212 DRM_AGP
, flags
, &info
->ringHandle
) < 0) {
214 "[agp] Could not add ring mapping\n");
218 "[agp] ring handle = 0x%08lx\n", info
->ringHandle
);
220 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
221 (drmAddressPtr
)&info
->ring
) < 0) {
222 fprintf(stderr
, "[agp] Could not map ring\n");
226 "[agp] Ring mapped at 0x%08lx\n",
227 (unsigned long)info
->ring
);
229 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
230 DRM_AGP
, flags
, &info
->ringReadPtrHandle
) < 0) {
232 "[agp] Could not add ring read ptr mapping\n");
236 "[agp] ring read ptr handle = 0x%08lx\n",
237 info
->ringReadPtrHandle
);
239 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
240 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
242 "[agp] Could not map ring read ptr\n");
246 "[agp] Ring read ptr mapped at 0x%08lx\n",
247 (unsigned long)info
->ringReadPtr
);
249 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
250 DRM_AGP
, 0, &info
->bufHandle
) < 0) {
252 "[agp] Could not add vertex/indirect buffers mapping\n");
256 "[agp] vertex/indirect buffers handle = 0x%08lx\n",
259 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
260 (drmAddressPtr
)&info
->buf
) < 0) {
262 "[agp] Could not map vertex/indirect buffers\n");
266 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
267 (unsigned long)info
->buf
);
269 if (drmAddMap(ctx
->drmFD
, info
->agpTexStart
, info
->agpTexMapSize
,
270 DRM_AGP
, 0, &info
->agpTexHandle
) < 0) {
272 "[agp] Could not add AGP texture map mapping\n");
276 "[agp] AGP texture map handle = 0x%08lx\n",
279 if (drmMap(ctx
->drmFD
, info
->agpTexHandle
, info
->agpTexMapSize
,
280 (drmAddressPtr
)&info
->agpTex
) < 0) {
282 "[agp] Could not map AGP texture map\n");
286 "[agp] AGP Texture map mapped at 0x%08lx\n",
287 (unsigned long)info
->agpTex
);
289 /* Initialize Rage 128's AGP registers */
290 cntl
= INREG(R128_AGP_CNTL
);
291 cntl
&= ~R128_AGP_APER_SIZE_MASK
;
292 switch (info
->agpSize
) {
293 case 256: cntl
|= R128_AGP_APER_SIZE_256MB
; break;
294 case 128: cntl
|= R128_AGP_APER_SIZE_128MB
; break;
295 case 64: cntl
|= R128_AGP_APER_SIZE_64MB
; break;
296 case 32: cntl
|= R128_AGP_APER_SIZE_32MB
; break;
297 case 16: cntl
|= R128_AGP_APER_SIZE_16MB
; break;
298 case 8: cntl
|= R128_AGP_APER_SIZE_8MB
; break;
299 case 4: cntl
|= R128_AGP_APER_SIZE_4MB
; break;
302 "[agp] Illegal aperture size %d kB\n",
306 agpBase
= drmAgpBase(ctx
->drmFD
);
307 OUTREG(R128_AGP_BASE
, agpBase
);
308 OUTREG(R128_AGP_CNTL
, cntl
);
310 /* Disable Rage 128's PCIGART registers */
311 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
312 chunk
&= ~(R128_BM_PTR_FORCE_TO_PCI
|
313 R128_BM_PM4_RD_FORCE_TO_PCI
|
314 R128_BM_GLOBAL_FORCE_TO_PCI
);
315 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
317 OUTREG(R128_PCI_GART_PAGE
, 1); /* Ensure AGP GART is used (for now) */
322 static GLboolean
R128DRIPciInit(const DRIDriverContext
*ctx
)
324 R128InfoPtr info
= ctx
->driverPrivate
;
325 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
332 ret
= drmScatterGatherAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024,
333 &info
->pciMemHandle
);
335 fprintf(stderr
, "[pci] Out of memory (%d)\n", ret
);
339 "[pci] %d kB allocated with handle 0x%08x\n",
340 info
->agpSize
*1024, info
->pciMemHandle
);
342 /* Initialize the CCE ring buffer data */
343 info
->ringStart
= info
->agpOffset
;
344 info
->ringMapSize
= info
->ringSize
*1024*1024 + DRM_PAGE_SIZE
;
345 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
347 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
348 info
->ringReadMapSize
= DRM_PAGE_SIZE
;
350 /* Reserve space for vertex/indirect buffers */
351 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
352 info
->bufMapSize
= info
->bufSize
*1024*1024;
354 flags
= DRM_READ_ONLY
| DRM_LOCKED
| DRM_KERNEL
;
356 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
357 DRM_SCATTER_GATHER
, flags
, &info
->ringHandle
) < 0) {
359 "[pci] Could not add ring mapping\n");
363 "[pci] ring handle = 0x%08lx\n", info
->ringHandle
);
365 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
366 (drmAddressPtr
)&info
->ring
) < 0) {
367 fprintf(stderr
, "[pci] Could not map ring\n");
371 "[pci] Ring mapped at 0x%08lx\n",
372 (unsigned long)info
->ring
);
374 "[pci] Ring contents 0x%08lx\n",
375 *(unsigned long *)info
->ring
);
377 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
378 DRM_SCATTER_GATHER
, flags
, &info
->ringReadPtrHandle
) < 0) {
380 "[pci] Could not add ring read ptr mapping\n");
384 "[pci] ring read ptr handle = 0x%08lx\n",
385 info
->ringReadPtrHandle
);
387 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
388 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
390 "[pci] Could not map ring read ptr\n");
394 "[pci] Ring read ptr mapped at 0x%08lx\n",
395 (unsigned long)info
->ringReadPtr
);
397 "[pci] Ring read ptr contents 0x%08lx\n",
398 *(unsigned long *)info
->ringReadPtr
);
400 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
401 DRM_SCATTER_GATHER
, 0, &info
->bufHandle
) < 0) {
403 "[pci] Could not add vertex/indirect buffers mapping\n");
407 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
410 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
411 (drmAddressPtr
)&info
->buf
) < 0) {
413 "[pci] Could not map vertex/indirect buffers\n");
417 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
418 (unsigned long)info
->buf
);
420 "[pci] Vertex/indirect buffers contents 0x%08lx\n",
421 *(unsigned long *)info
->buf
);
424 /* This is really an AGP card, force PCI GART mode */
425 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
426 chunk
|= (R128_BM_PTR_FORCE_TO_PCI
|
427 R128_BM_PM4_RD_FORCE_TO_PCI
|
428 R128_BM_GLOBAL_FORCE_TO_PCI
);
429 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
430 OUTREG(R128_PCI_GART_PAGE
, 0); /* Ensure PCI GART is used */
436 /* Add a map for the MMIO registers that will be accessed by any
437 DRI-based clients. */
438 static GLboolean
R128DRIMapInit(const DRIDriverContext
*ctx
)
440 R128InfoPtr info
= ctx
->driverPrivate
;
443 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
447 if (drmAddMap(ctx
->drmFD
, ctx
->MMIOStart
, ctx
->MMIOSize
,
448 DRM_REGISTERS
, flags
, &info
->registerHandle
) < 0) {
452 "[drm] register handle = 0x%08lx\n", info
->registerHandle
);
457 /* Initialize the kernel data structures. */
458 static int R128DRIKernelInit(const DRIDriverContext
*ctx
)
460 R128InfoPtr info
= ctx
->driverPrivate
;
461 drm_r128_init_t drmInfo
;
463 memset( &drmInfo
, 0, sizeof(&drmInfo
) );
465 drmInfo
.func
= R128_INIT_CCE
;
466 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
467 drmInfo
.is_pci
= info
->IsPCI
;
468 drmInfo
.cce_mode
= info
->CCEMode
;
469 drmInfo
.cce_secure
= info
->CCESecure
;
470 drmInfo
.ring_size
= info
->ringSize
*1024*1024;
471 drmInfo
.usec_timeout
= info
->CCEusecTimeout
;
473 drmInfo
.fb_bpp
= ctx
->bpp
;
474 drmInfo
.depth_bpp
= ctx
->bpp
;
476 drmInfo
.front_offset
= info
->frontOffset
;
477 drmInfo
.front_pitch
= info
->frontPitch
;
479 drmInfo
.back_offset
= info
->backOffset
;
480 drmInfo
.back_pitch
= info
->backPitch
;
482 drmInfo
.depth_offset
= info
->depthOffset
;
483 drmInfo
.depth_pitch
= info
->depthPitch
;
484 drmInfo
.span_offset
= info
->spanOffset
;
486 drmInfo
.fb_offset
= info
->LinearAddr
;
487 drmInfo
.mmio_offset
= info
->registerHandle
;
488 drmInfo
.ring_offset
= info
->ringHandle
;
489 drmInfo
.ring_rptr_offset
= info
->ringReadPtrHandle
;
490 drmInfo
.buffers_offset
= info
->bufHandle
;
491 drmInfo
.agp_textures_offset
= info
->agpTexHandle
;
493 if (drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
494 &drmInfo
, sizeof(drmInfo
)) < 0)
500 /* Add a map for the vertex buffers that will be accessed by any
501 DRI-based clients. */
502 static GLboolean
R128DRIBufInit(const DRIDriverContext
*ctx
)
504 R128InfoPtr info
= ctx
->driverPrivate
;
505 /* Initialize vertex buffers */
507 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
508 info
->bufMapSize
/ R128_BUFFER_SIZE
,
513 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
514 info
->bufMapSize
/ R128_BUFFER_SIZE
,
519 if (info
->bufNumBufs
<= 0) {
521 "[drm] Could not create vertex/indirect buffers list\n");
525 "[drm] Added %d %d byte vertex/indirect buffers\n",
526 info
->bufNumBufs
, R128_BUFFER_SIZE
);
528 if (!(info
->buffers
= drmMapBufs(ctx
->drmFD
))) {
530 "[drm] Failed to map vertex/indirect buffers list\n");
534 "[drm] Mapped %d vertex/indirect buffers\n",
535 info
->buffers
->count
);
540 static void R128DRIIrqInit(const DRIDriverContext
*ctx
)
542 R128InfoPtr info
= ctx
->driverPrivate
;
543 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
546 info
->irq
= drmGetInterruptFromBusID(
552 if((drmCtlInstHandler(ctx
->drmFD
, info
->irq
)) != 0) {
554 "[drm] failure adding irq handler, "
555 "there is a device already using that irq\n"
556 "[drm] falling back to irq-free operation\n");
559 info
->gen_int_cntl
= INREG( R128_GEN_INT_CNTL
);
565 "[drm] dma control initialized, using IRQ %d\n",
569 static int R128CCEStop(const DRIDriverContext
*ctx
)
571 R128InfoPtr info
= ctx
->driverPrivate
;
572 drm_r128_cce_stop_t stop
;
578 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
579 &stop
, sizeof(stop
) );
583 } else if ( errno
!= EBUSY
) {
591 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
592 &stop
, sizeof(stop
) );
593 } while ( ret
&& errno
== EBUSY
&& i
++ < R128_IDLE_RETRY
);
597 } else if ( errno
!= EBUSY
) {
603 if ( drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
604 &stop
, sizeof(stop
) )) {
611 /* Initialize the CCE state, and start the CCE (if used by the X server) */
612 static void R128DRICCEInit(const DRIDriverContext
*ctx
)
614 R128InfoPtr info
= ctx
->driverPrivate
;
616 /* Turn on bus mastering */
617 info
->BusCntl
&= ~R128_BUS_MASTER_DIS
;
619 /* CCEMode is initialized in r128_driver.c */
620 switch (info
->CCEMode
) {
621 case R128_PM4_NONPM4
: info
->CCEFifoSize
= 0; break;
622 case R128_PM4_192PIO
: info
->CCEFifoSize
= 192; break;
623 case R128_PM4_192BM
: info
->CCEFifoSize
= 192; break;
624 case R128_PM4_128PIO_64INDBM
: info
->CCEFifoSize
= 128; break;
625 case R128_PM4_128BM_64INDBM
: info
->CCEFifoSize
= 128; break;
626 case R128_PM4_64PIO_128INDBM
: info
->CCEFifoSize
= 64; break;
627 case R128_PM4_64BM_128INDBM
: info
->CCEFifoSize
= 64; break;
628 case R128_PM4_64PIO_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
629 case R128_PM4_64BM_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
630 case R128_PM4_64PIO_64VCPIO_64INDPIO
: info
->CCEFifoSize
= 64; break;
633 /* Make sure the CCE is on for the X server */
634 R128CCE_START(ctx
, info
);
638 static int R128MemoryInit(const DRIDriverContext
*ctx
)
640 R128InfoPtr info
= ctx
->driverPrivate
;
641 int width_bytes
= ctx
->shared
.virtualWidth
* ctx
->cpp
;
643 int bufferSize
= ((ctx
->shared
.virtualHeight
* width_bytes
645 & ~R128_BUFFER_ALIGN
);
646 int depthSize
= ((((ctx
->shared
.virtualHeight
+15) & ~15) * width_bytes
648 & ~R128_BUFFER_ALIGN
);
651 info
->frontOffset
= 0;
652 info
->frontPitch
= ctx
->shared
.virtualWidth
;
655 "Using %d MB AGP aperture\n", info
->agpSize
);
657 "Using %d MB for the ring buffer\n", info
->ringSize
);
659 "Using %d MB for vertex/indirect buffers\n", info
->bufSize
);
661 "Using %d MB for AGP textures\n", info
->agpTexSize
);
663 /* Front, back and depth buffers - everything else texture??
665 info
->textureSize
= ctx
->shared
.fbSize
- 2 * bufferSize
- depthSize
;
667 if (info
->textureSize
< 0)
670 l
= R128MinBits((info
->textureSize
-1) / R128_NR_TEX_REGIONS
);
671 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
673 /* Round the texture size up to the nearest whole number of
674 * texture regions. Again, be greedy about this, don't
677 info
->log2TexGran
= l
;
678 info
->textureSize
= (info
->textureSize
>> l
) << l
;
680 /* Set a minimum usable local texture heap size. This will fit
681 * two 256x256x32bpp textures.
683 if (info
->textureSize
< 512 * 1024) {
684 info
->textureOffset
= 0;
685 info
->textureSize
= 0;
688 /* Reserve space for textures */
689 info
->textureOffset
= ((ctx
->shared
.fbSize
- info
->textureSize
+
693 /* Reserve space for the shared depth
696 info
->depthOffset
= ((info
->textureOffset
- depthSize
+
699 info
->depthPitch
= ctx
->shared
.virtualWidth
;
701 info
->backOffset
= ((info
->depthOffset
- bufferSize
+
704 info
->backPitch
= ctx
->shared
.virtualWidth
;
708 "Will use back buffer at offset 0x%x\n",
711 "Will use depth buffer at offset 0x%x\n",
714 "Will use %d kb for textures at offset 0x%x\n",
715 info
->textureSize
/1024, info
->textureOffset
);
721 /* Initialize the screen-specific data structures for the DRI and the
722 Rage 128. This is the main entry point to the device-specific
723 initialization code. It calls device-independent DRI functions to
724 create the DRI data structures and initialize the DRI state. */
725 static GLboolean
R128DRIScreenInit(DRIDriverContext
*ctx
)
727 R128InfoPtr info
= ctx
->driverPrivate
;
729 int err
, major
, minor
, patch
;
730 drmVersionPtr version
;
734 /* These modes are not supported (yet). */
738 "[dri] R128DRIScreenInit failed (depth %d not supported). "
739 "[dri] Disabling DRI.\n", ctx
->bpp
);
742 /* Only 16 and 32 color depths are supports currently. */
748 info
->registerSize
= ctx
->MMIOSize
;
749 ctx
->shared
.SAREASize
= DRM_PAGE_SIZE
;
751 /* Note that drmOpen will try to load the kernel module, if needed. */
752 ctx
->drmFD
= drmOpen("r128", NULL
);
753 if (ctx
->drmFD
< 0) {
754 fprintf(stderr
, "[drm] drmOpen failed\n");
758 /* Check the r128 DRM version */
759 version
= drmGetVersion(ctx
->drmFD
);
761 if (version
->version_major
!= 2 ||
762 version
->version_minor
< 2) {
763 /* incompatible drm version */
765 "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
766 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
767 "[dri] Disabling the DRI.\n",
768 version
->version_major
,
769 version
->version_minor
,
770 version
->version_patchlevel
);
771 drmFreeVersion(version
);
774 info
->drmMinor
= version
->version_minor
;
775 drmFreeVersion(version
);
778 if ((err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
)) < 0) {
779 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
780 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
784 if (drmAddMap( ctx
->drmFD
,
786 ctx
->shared
.SAREASize
,
789 &ctx
->shared
.hSAREA
) < 0)
791 fprintf(stderr
, "[drm] drmAddMap failed\n");
794 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
795 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
797 if (drmMap( ctx
->drmFD
,
799 ctx
->shared
.SAREASize
,
800 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
802 fprintf(stderr
, "[drm] drmMap failed\n");
805 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
806 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
807 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
809 /* Need to AddMap the framebuffer and mmio regions here:
811 if (drmAddMap( ctx
->drmFD
,
812 (drmHandle
)ctx
->FBStart
,
816 &ctx
->shared
.hFrameBuffer
) < 0)
818 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
822 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
823 ctx
->shared
.hFrameBuffer
);
825 if (!R128MemoryInit(ctx
))
829 if (!info
->IsPCI
&& !R128DRIAgpInit(ctx
)) {
830 info
->IsPCI
= GL_TRUE
;
832 "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
834 "[agp] Make sure you have the agpgart kernel module loaded.\n");
837 /* Initialize PCIGART */
838 if (info
->IsPCI
&& !R128DRIPciInit(ctx
)) {
842 /* DRIScreenInit doesn't add all the
843 common mappings. Add additional
845 if (!R128DRIMapInit(ctx
)) {
849 /* Create a 'server' context so we can grab the lock for
850 * initialization ioctls.
852 if ((err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
)) != 0) {
853 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
857 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
859 /* Initialize the kernel data structures */
860 if (!R128DRIKernelInit(ctx
)) {
864 /* Initialize the vertex buffers list */
865 if (!R128DRIBufInit(ctx
)) {
872 /* Initialize and start the CCE if required */
875 /* Quick hack to clear the front & back buffers. Could also use
876 * the clear ioctl to do this, but would need to setup hw state
879 memset((char *)ctx
->FBAddress
+ info
->frontOffset
,
881 info
->frontPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
883 memset((char *)ctx
->FBAddress
+ info
->backOffset
,
885 info
->backPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
887 drm_r128_sarea_t
*pSAREAPriv
;
888 pSAREAPriv
= (drm_r128_sarea_t
*)(((char*)ctx
->pSAREA
) +
889 sizeof(drm_sarea_t
));
890 memset(pSAREAPriv
, 0, sizeof(*pSAREAPriv
));
892 /* This is the struct passed to radeon_dri.so for its initialization */
893 ctx
->driverClientMsg
= malloc(sizeof(R128DRIRec
));
894 ctx
->driverClientMsgSize
= sizeof(R128DRIRec
);
896 pR128DRI
= (R128DRIPtr
)ctx
->driverClientMsg
;
897 pR128DRI
->deviceID
= info
->Chipset
;
898 pR128DRI
->width
= ctx
->shared
.virtualWidth
;
899 pR128DRI
->height
= ctx
->shared
.virtualHeight
;
900 pR128DRI
->depth
= ctx
->bpp
;
901 pR128DRI
->bpp
= ctx
->bpp
;
903 pR128DRI
->IsPCI
= info
->IsPCI
;
904 pR128DRI
->AGPMode
= info
->agpMode
;
906 pR128DRI
->frontOffset
= info
->frontOffset
;
907 pR128DRI
->frontPitch
= info
->frontPitch
;
908 pR128DRI
->backOffset
= info
->backOffset
;
909 pR128DRI
->backPitch
= info
->backPitch
;
910 pR128DRI
->depthOffset
= info
->depthOffset
;
911 pR128DRI
->depthPitch
= info
->depthPitch
;
912 pR128DRI
->spanOffset
= info
->spanOffset
;
913 pR128DRI
->textureOffset
= info
->textureOffset
;
914 pR128DRI
->textureSize
= info
->textureSize
;
915 pR128DRI
->log2TexGran
= info
->log2TexGran
;
917 pR128DRI
->registerHandle
= info
->registerHandle
;
918 pR128DRI
->registerSize
= info
->registerSize
;
920 pR128DRI
->agpTexHandle
= info
->agpTexHandle
;
921 pR128DRI
->agpTexMapSize
= info
->agpTexMapSize
;
922 pR128DRI
->log2AGPTexGran
= info
->log2AGPTexGran
;
923 pR128DRI
->agpTexOffset
= info
->agpTexStart
;
924 pR128DRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
929 /* The screen is being closed, so clean up any state and free any
930 resources used by the DRI. */
931 void R128DRICloseScreen(const DRIDriverContext
*ctx
)
933 R128InfoPtr info
= ctx
->driverPrivate
;
934 drm_r128_init_t drmInfo
;
936 /* Stop the CCE if it is still in use */
937 R128CCE_STOP(ctx
, info
);
940 drmCtlUninstHandler(ctx
->drmFD
);
944 /* De-allocate vertex buffers */
946 drmUnmapBufs(info
->buffers
);
947 info
->buffers
= NULL
;
950 /* De-allocate all kernel resources */
951 memset(&drmInfo
, 0, sizeof(drmInfo
));
952 drmInfo
.func
= R128_CLEANUP_CCE
;
953 drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
954 &drmInfo
, sizeof(drmInfo
));
956 /* De-allocate all AGP resources */
958 drmUnmap(info
->agpTex
, info
->agpTexMapSize
);
962 drmUnmap(info
->buf
, info
->bufMapSize
);
965 if (info
->ringReadPtr
) {
966 drmUnmap(info
->ringReadPtr
, info
->ringReadMapSize
);
967 info
->ringReadPtr
= NULL
;
970 drmUnmap(info
->ring
, info
->ringMapSize
);
973 if (info
->agpMemHandle
!= DRM_AGP_NO_HANDLE
) {
974 drmAgpUnbind(ctx
->drmFD
, info
->agpMemHandle
);
975 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
976 info
->agpMemHandle
= 0;
977 drmAgpRelease(ctx
->drmFD
);
979 if (info
->pciMemHandle
) {
980 drmScatterGatherFree(ctx
->drmFD
, info
->pciMemHandle
);
981 info
->pciMemHandle
= 0;
985 static GLboolean
R128PreInitDRI(const DRIDriverContext
*ctx
)
987 R128InfoPtr info
= ctx
->driverPrivate
;
989 /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
990 info
->CCEMode
= R128_DEFAULT_CCE_BM_MODE
;
991 info
->CCESecure
= GL_TRUE
;
993 info
->agpMode
= R128_DEFAULT_AGP_MODE
;
994 info
->agpSize
= R128_DEFAULT_AGP_SIZE
;
995 info
->ringSize
= R128_DEFAULT_RING_SIZE
;
996 info
->bufSize
= R128_DEFAULT_BUFFER_SIZE
;
997 info
->agpTexSize
= R128_DEFAULT_AGP_TEX_SIZE
;
999 info
->CCEusecTimeout
= R128_DEFAULT_CCE_TIMEOUT
;
1005 * \brief Initialize the framebuffer device mode
1007 * \param ctx display handle.
1009 * \return one on success, or zero on failure.
1011 * Fills in \p info with some default values and some information from \p ctx
1012 * and then calls R128ScreenInit() for the screen initialization.
1014 * Before exiting clears the framebuffer memory accessing it directly.
1016 static int R128InitFBDev( DRIDriverContext
*ctx
)
1018 R128InfoPtr info
= calloc(1, sizeof(*info
));
1021 int dummy
= ctx
->shared
.virtualWidth
;
1023 switch (ctx
->bpp
/ 8) {
1024 case 1: dummy
= (ctx
->shared
.virtualWidth
+ 127) & ~127; break;
1025 case 2: dummy
= (ctx
->shared
.virtualWidth
+ 31) & ~31; break;
1027 case 4: dummy
= (ctx
->shared
.virtualWidth
+ 15) & ~15; break;
1030 ctx
->shared
.virtualWidth
= dummy
;
1033 ctx
->driverPrivate
= (void *)info
;
1035 info
->Chipset
= ctx
->chipset
;
1037 switch (info
->Chipset
) {
1038 case PCI_DEVICE_ID_ATI_RAGE128_LE
:
1039 case PCI_DEVICE_ID_ATI_RAGE128_RE
:
1040 case PCI_DEVICE_ID_ATI_RAGE128_RK
:
1041 case PCI_DEVICE_ID_ATI_RAGE128_PD
:
1042 case PCI_DEVICE_ID_ATI_RAGE128_PP
:
1043 case PCI_DEVICE_ID_ATI_RAGE128_PR
:
1044 /* This is a PCI card */
1045 info
->IsPCI
= GL_TRUE
;
1048 /* This is an AGP card */
1049 info
->IsPCI
= GL_FALSE
;
1053 info
->frontPitch
= ctx
->shared
.virtualWidth
;
1054 info
->LinearAddr
= ctx
->FBStart
& 0xfc000000;
1056 if (!R128PreInitDRI(ctx
))
1059 if (!R128DRIScreenInit(ctx
))
1067 * \brief The screen is being closed, so clean up any state and free any
1068 * resources used by the DRI.
1070 * \param ctx display handle.
1072 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1075 static void R128HaltFBDev( DRIDriverContext
*ctx
)
1077 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1078 drmClose(ctx
->drmFD
);
1080 if (ctx
->driverPrivate
) {
1081 free(ctx
->driverPrivate
);
1082 ctx
->driverPrivate
= 0;
1088 * \brief Validate the fbdev mode.
1090 * \param ctx display handle.
1092 * \return one on success, or zero on failure.
1094 * Saves some registers and returns 1.
1096 * \sa R128PostValidateMode().
1098 static int R128ValidateMode( const DRIDriverContext
*ctx
)
1105 * \brief Examine mode returned by fbdev.
1107 * \param ctx display handle.
1109 * \return one on success, or zero on failure.
1111 * Restores registers that fbdev has clobbered and returns 1.
1113 * \sa R128ValidateMode().
1115 static int R128PostValidateMode( const DRIDriverContext
*ctx
)
1122 * \brief Shutdown the drawing engine.
1124 * \param ctx display handle
1126 * Turns off the command processor engine & restores the graphics card
1127 * to a state that fbdev understands.
1129 static int R128EngineShutdown( const DRIDriverContext
*ctx
)
1135 * \brief Restore the drawing engine.
1137 * \param ctx display handle
1139 * Resets the graphics card and sets initial values for several registers of
1140 * the card's drawing engine.
1142 * Turns on the R128 command processor engine (i.e., the ringbuffer).
1144 static int R128EngineRestore( const DRIDriverContext
*ctx
)
1151 * \brief Exported driver interface for Mini GLX.
1155 const struct DRIDriverRec __driDriver
= {
1156 R128InitContextModes
,
1158 R128PostValidateMode
,