2 * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
3 * Precision Insight, Inc., Cedar Park, Texas, and
4 * VA Linux Systems Inc., Fremont, California.
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation on the rights to use, copy, modify, merge,
12 * publish, distribute, sublicense, and/or sell copies of the Software,
13 * and to permit persons to whom the Software is furnished to do so,
14 * subject to the following conditions:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
24 * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
32 * Kevin E. Martin <martin@valinux.com>
33 * Rickard E. Faith <faith@valinux.com>
34 * Daryll Strauss <daryll@valinux.com>
35 * Gareth Hughes <gareth@valinux.com>
44 // 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"
58 static size_t r128_drm_page_size
;
60 /* Compute log base 2 of val. */
61 static int R128MinBits(int val
)
66 for (bits
= 0; val
; val
>>= 1, ++bits
);
70 /* Initialize the AGP state. Request memory for use in AGP space, and
71 initialize the Rage 128 registers to point to that memory. */
72 static GLboolean
R128DRIAgpInit(const DRIDriverContext
*ctx
)
74 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
75 R128InfoPtr info
= ctx
->driverPrivate
;
77 unsigned int vendor
, device
;
79 unsigned long cntl
, chunk
;
82 unsigned long agpBase
;
84 if (drmAgpAcquire(ctx
->drmFD
) < 0) {
85 fprintf(stderr
, "[agp] AGP not available\n");
89 /* Modify the mode if the default mode is
90 not appropriate for this particular
91 combination of graphics card and AGP
94 mode
= drmAgpGetMode(ctx
->drmFD
); /* Default mode */
95 vendor
= drmAgpVendorId(ctx
->drmFD
);
96 device
= drmAgpDeviceId(ctx
->drmFD
);
98 mode
&= ~R128_AGP_MODE_MASK
;
99 switch (info
->agpMode
) {
100 case 4: mode
|= R128_AGP_4X_MODE
;
101 case 2: mode
|= R128_AGP_2X_MODE
;
102 case 1: default: mode
|= R128_AGP_1X_MODE
;
106 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
107 mode
, vendor
, device
,
111 if (drmAgpEnable(ctx
->drmFD
, mode
) < 0) {
112 fprintf(stderr
, "[agp] AGP not enabled\n");
113 drmAgpRelease(ctx
->drmFD
);
119 if ((ret
= drmAgpAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024, 0, NULL
,
120 &info
->agpMemHandle
)) < 0) {
121 fprintf(stderr
, "[agp] Out of memory (%d)\n", ret
);
122 drmAgpRelease(ctx
->drmFD
);
126 "[agp] %d kB allocated with handle 0x%08x\n",
127 info
->agpSize
*1024, info
->agpMemHandle
);
129 if (drmAgpBind(ctx
->drmFD
, info
->agpMemHandle
, info
->agpOffset
) < 0) {
130 fprintf(stderr
, "[agp] Could not bind\n");
131 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
132 drmAgpRelease(ctx
->drmFD
);
136 /* Initialize the CCE ring buffer data */
137 info
->ringStart
= info
->agpOffset
;
138 info
->ringMapSize
= info
->ringSize
*1024*1024 + r128_drm_page_size
;
139 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
141 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
142 info
->ringReadMapSize
= r128_drm_page_size
;
144 /* Reserve space for vertex/indirect buffers */
145 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
146 info
->bufMapSize
= info
->bufSize
*1024*1024;
148 /* Reserve the rest for AGP textures */
149 info
->agpTexStart
= info
->bufStart
+ info
->bufMapSize
;
150 s
= (info
->agpSize
*1024*1024 - info
->agpTexStart
);
151 l
= R128MinBits((s
-1) / R128_NR_TEX_REGIONS
);
152 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
153 info
->agpTexMapSize
= (s
>> l
) << l
;
154 info
->log2AGPTexGran
= l
;
156 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
159 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
160 DRM_AGP
, flags
, &info
->ringHandle
) < 0) {
162 "[agp] Could not add ring mapping\n");
166 "[agp] ring handle = 0x%08x\n", info
->ringHandle
);
168 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
169 (drmAddressPtr
)&info
->ring
) < 0) {
170 fprintf(stderr
, "[agp] Could not map ring\n");
174 "[agp] Ring mapped at 0x%08lx\n",
175 (unsigned long)info
->ring
);
177 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
178 DRM_AGP
, flags
, &info
->ringReadPtrHandle
) < 0) {
180 "[agp] Could not add ring read ptr mapping\n");
184 "[agp] ring read ptr handle = 0x%08x\n",
185 info
->ringReadPtrHandle
);
187 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
188 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
190 "[agp] Could not map ring read ptr\n");
194 "[agp] Ring read ptr mapped at 0x%08lx\n",
195 (unsigned long)info
->ringReadPtr
);
197 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
198 DRM_AGP
, 0, &info
->bufHandle
) < 0) {
200 "[agp] Could not add vertex/indirect buffers mapping\n");
204 "[agp] vertex/indirect buffers handle = 0x%08lx\n",
207 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
208 (drmAddressPtr
)&info
->buf
) < 0) {
210 "[agp] Could not map vertex/indirect buffers\n");
214 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
215 (unsigned long)info
->buf
);
217 if (drmAddMap(ctx
->drmFD
, info
->agpTexStart
, info
->agpTexMapSize
,
218 DRM_AGP
, 0, &info
->agpTexHandle
) < 0) {
220 "[agp] Could not add AGP texture map mapping\n");
224 "[agp] AGP texture map handle = 0x%08lx\n",
227 if (drmMap(ctx
->drmFD
, info
->agpTexHandle
, info
->agpTexMapSize
,
228 (drmAddressPtr
)&info
->agpTex
) < 0) {
230 "[agp] Could not map AGP texture map\n");
234 "[agp] AGP Texture map mapped at 0x%08lx\n",
235 (unsigned long)info
->agpTex
);
237 /* Initialize Rage 128's AGP registers */
238 cntl
= INREG(R128_AGP_CNTL
);
239 cntl
&= ~R128_AGP_APER_SIZE_MASK
;
240 switch (info
->agpSize
) {
241 case 256: cntl
|= R128_AGP_APER_SIZE_256MB
; break;
242 case 128: cntl
|= R128_AGP_APER_SIZE_128MB
; break;
243 case 64: cntl
|= R128_AGP_APER_SIZE_64MB
; break;
244 case 32: cntl
|= R128_AGP_APER_SIZE_32MB
; break;
245 case 16: cntl
|= R128_AGP_APER_SIZE_16MB
; break;
246 case 8: cntl
|= R128_AGP_APER_SIZE_8MB
; break;
247 case 4: cntl
|= R128_AGP_APER_SIZE_4MB
; break;
250 "[agp] Illegal aperture size %d kB\n",
254 agpBase
= drmAgpBase(ctx
->drmFD
);
255 OUTREG(R128_AGP_BASE
, agpBase
);
256 OUTREG(R128_AGP_CNTL
, cntl
);
258 /* Disable Rage 128's PCIGART registers */
259 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
260 chunk
&= ~(R128_BM_PTR_FORCE_TO_PCI
|
261 R128_BM_PM4_RD_FORCE_TO_PCI
|
262 R128_BM_GLOBAL_FORCE_TO_PCI
);
263 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
265 OUTREG(R128_PCI_GART_PAGE
, 1); /* Ensure AGP GART is used (for now) */
270 static GLboolean
R128DRIPciInit(const DRIDriverContext
*ctx
)
272 R128InfoPtr info
= ctx
->driverPrivate
;
273 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
280 ret
= drmScatterGatherAlloc(ctx
->drmFD
, info
->agpSize
*1024*1024,
281 &info
->pciMemHandle
);
283 fprintf(stderr
, "[pci] Out of memory (%d)\n", ret
);
287 "[pci] %d kB allocated with handle 0x%08x\n",
288 info
->agpSize
*1024, info
->pciMemHandle
);
290 /* Initialize the CCE ring buffer data */
291 info
->ringStart
= info
->agpOffset
;
292 info
->ringMapSize
= info
->ringSize
*1024*1024 + r128_drm_page_size
;
293 info
->ringSizeLog2QW
= R128MinBits(info
->ringSize
*1024*1024/8) - 1;
295 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
296 info
->ringReadMapSize
= r128_drm_page_size
;
298 /* Reserve space for vertex/indirect buffers */
299 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
300 info
->bufMapSize
= info
->bufSize
*1024*1024;
302 flags
= DRM_READ_ONLY
| DRM_LOCKED
| DRM_KERNEL
;
304 if (drmAddMap(ctx
->drmFD
, info
->ringStart
, info
->ringMapSize
,
305 DRM_SCATTER_GATHER
, flags
, &info
->ringHandle
) < 0) {
307 "[pci] Could not add ring mapping\n");
311 "[pci] ring handle = 0x%08lx\n", info
->ringHandle
);
313 if (drmMap(ctx
->drmFD
, info
->ringHandle
, info
->ringMapSize
,
314 (drmAddressPtr
)&info
->ring
) < 0) {
315 fprintf(stderr
, "[pci] Could not map ring\n");
319 "[pci] Ring mapped at 0x%08lx\n",
320 (unsigned long)info
->ring
);
322 "[pci] Ring contents 0x%08lx\n",
323 *(unsigned long *)info
->ring
);
325 if (drmAddMap(ctx
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
326 DRM_SCATTER_GATHER
, flags
, &info
->ringReadPtrHandle
) < 0) {
328 "[pci] Could not add ring read ptr mapping\n");
332 "[pci] ring read ptr handle = 0x%08lx\n",
333 info
->ringReadPtrHandle
);
335 if (drmMap(ctx
->drmFD
, info
->ringReadPtrHandle
, info
->ringReadMapSize
,
336 (drmAddressPtr
)&info
->ringReadPtr
) < 0) {
338 "[pci] Could not map ring read ptr\n");
342 "[pci] Ring read ptr mapped at 0x%08lx\n",
343 (unsigned long)info
->ringReadPtr
);
345 "[pci] Ring read ptr contents 0x%08lx\n",
346 *(unsigned long *)info
->ringReadPtr
);
348 if (drmAddMap(ctx
->drmFD
, info
->bufStart
, info
->bufMapSize
,
349 DRM_SCATTER_GATHER
, 0, &info
->bufHandle
) < 0) {
351 "[pci] Could not add vertex/indirect buffers mapping\n");
355 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
358 if (drmMap(ctx
->drmFD
, info
->bufHandle
, info
->bufMapSize
,
359 (drmAddressPtr
)&info
->buf
) < 0) {
361 "[pci] Could not map vertex/indirect buffers\n");
365 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
366 (unsigned long)info
->buf
);
368 "[pci] Vertex/indirect buffers contents 0x%08lx\n",
369 *(unsigned long *)info
->buf
);
372 /* This is really an AGP card, force PCI GART mode */
373 chunk
= INREG(R128_BM_CHUNK_0_VAL
);
374 chunk
|= (R128_BM_PTR_FORCE_TO_PCI
|
375 R128_BM_PM4_RD_FORCE_TO_PCI
|
376 R128_BM_GLOBAL_FORCE_TO_PCI
);
377 OUTREG(R128_BM_CHUNK_0_VAL
, chunk
);
378 OUTREG(R128_PCI_GART_PAGE
, 0); /* Ensure PCI GART is used */
384 /* Add a map for the MMIO registers that will be accessed by any
385 DRI-based clients. */
386 static GLboolean
R128DRIMapInit(const DRIDriverContext
*ctx
)
388 R128InfoPtr info
= ctx
->driverPrivate
;
391 if (info
->CCESecure
) flags
= DRM_READ_ONLY
;
395 if (drmAddMap(ctx
->drmFD
, ctx
->MMIOStart
, ctx
->MMIOSize
,
396 DRM_REGISTERS
, flags
, &info
->registerHandle
) < 0) {
400 "[drm] register handle = 0x%08x\n", info
->registerHandle
);
405 /* Initialize the kernel data structures. */
406 static int R128DRIKernelInit(const DRIDriverContext
*ctx
)
408 R128InfoPtr info
= ctx
->driverPrivate
;
409 drm_r128_init_t drmInfo
;
411 memset( &drmInfo
, 0, sizeof(&drmInfo
) );
413 drmInfo
.func
= R128_INIT_CCE
;
414 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
415 drmInfo
.is_pci
= info
->IsPCI
;
416 drmInfo
.cce_mode
= info
->CCEMode
;
417 drmInfo
.cce_secure
= info
->CCESecure
;
418 drmInfo
.ring_size
= info
->ringSize
*1024*1024;
419 drmInfo
.usec_timeout
= info
->CCEusecTimeout
;
421 drmInfo
.fb_bpp
= ctx
->bpp
;
422 drmInfo
.depth_bpp
= ctx
->bpp
;
424 drmInfo
.front_offset
= info
->frontOffset
;
425 drmInfo
.front_pitch
= info
->frontPitch
;
427 drmInfo
.back_offset
= info
->backOffset
;
428 drmInfo
.back_pitch
= info
->backPitch
;
430 drmInfo
.depth_offset
= info
->depthOffset
;
431 drmInfo
.depth_pitch
= info
->depthPitch
;
432 drmInfo
.span_offset
= info
->spanOffset
;
434 drmInfo
.fb_offset
= info
->LinearAddr
;
435 drmInfo
.mmio_offset
= info
->registerHandle
;
436 drmInfo
.ring_offset
= info
->ringHandle
;
437 drmInfo
.ring_rptr_offset
= info
->ringReadPtrHandle
;
438 drmInfo
.buffers_offset
= info
->bufHandle
;
439 drmInfo
.agp_textures_offset
= info
->agpTexHandle
;
441 if (drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
442 &drmInfo
, sizeof(drmInfo
)) < 0)
448 /* Add a map for the vertex buffers that will be accessed by any
449 DRI-based clients. */
450 static GLboolean
R128DRIBufInit(const DRIDriverContext
*ctx
)
452 R128InfoPtr info
= ctx
->driverPrivate
;
453 /* Initialize vertex buffers */
455 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
456 info
->bufMapSize
/ R128_BUFFER_SIZE
,
461 info
->bufNumBufs
= drmAddBufs(ctx
->drmFD
,
462 info
->bufMapSize
/ R128_BUFFER_SIZE
,
467 if (info
->bufNumBufs
<= 0) {
469 "[drm] Could not create vertex/indirect buffers list\n");
473 "[drm] Added %d %d byte vertex/indirect buffers\n",
474 info
->bufNumBufs
, R128_BUFFER_SIZE
);
476 if (!(info
->buffers
= drmMapBufs(ctx
->drmFD
))) {
478 "[drm] Failed to map vertex/indirect buffers list\n");
482 "[drm] Mapped %d vertex/indirect buffers\n",
483 info
->buffers
->count
);
488 static void R128DRIIrqInit(const DRIDriverContext
*ctx
)
490 R128InfoPtr info
= ctx
->driverPrivate
;
491 unsigned char *R128MMIO
= ctx
->MMIOAddress
;
494 info
->irq
= drmGetInterruptFromBusID(
500 if((drmCtlInstHandler(ctx
->drmFD
, info
->irq
)) != 0) {
502 "[drm] failure adding irq handler, "
503 "there is a device already using that irq\n"
504 "[drm] falling back to irq-free operation\n");
507 info
->gen_int_cntl
= INREG( R128_GEN_INT_CNTL
);
513 "[drm] dma control initialized, using IRQ %d\n",
517 static int R128CCEStop(const DRIDriverContext
*ctx
)
519 R128InfoPtr info
= ctx
->driverPrivate
;
520 drm_r128_cce_stop_t stop
;
526 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
527 &stop
, sizeof(stop
) );
531 } else if ( errno
!= EBUSY
) {
539 ret
= drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
540 &stop
, sizeof(stop
) );
541 } while ( ret
&& errno
== EBUSY
&& i
++ < R128_IDLE_RETRY
);
545 } else if ( errno
!= EBUSY
) {
551 if ( drmCommandWrite( ctx
->drmFD
, DRM_R128_CCE_STOP
,
552 &stop
, sizeof(stop
) )) {
559 /* Initialize the CCE state, and start the CCE (if used by the X server) */
560 static void R128DRICCEInit(const DRIDriverContext
*ctx
)
562 R128InfoPtr info
= ctx
->driverPrivate
;
564 /* Turn on bus mastering */
565 info
->BusCntl
&= ~R128_BUS_MASTER_DIS
;
567 /* CCEMode is initialized in r128_driver.c */
568 switch (info
->CCEMode
) {
569 case R128_PM4_NONPM4
: info
->CCEFifoSize
= 0; break;
570 case R128_PM4_192PIO
: info
->CCEFifoSize
= 192; break;
571 case R128_PM4_192BM
: info
->CCEFifoSize
= 192; break;
572 case R128_PM4_128PIO_64INDBM
: info
->CCEFifoSize
= 128; break;
573 case R128_PM4_128BM_64INDBM
: info
->CCEFifoSize
= 128; break;
574 case R128_PM4_64PIO_128INDBM
: info
->CCEFifoSize
= 64; break;
575 case R128_PM4_64BM_128INDBM
: info
->CCEFifoSize
= 64; break;
576 case R128_PM4_64PIO_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
577 case R128_PM4_64BM_64VCBM_64INDBM
: info
->CCEFifoSize
= 64; break;
578 case R128_PM4_64PIO_64VCPIO_64INDPIO
: info
->CCEFifoSize
= 64; break;
581 /* Make sure the CCE is on for the X server */
582 R128CCE_START(ctx
, info
);
586 static int R128MemoryInit(const DRIDriverContext
*ctx
)
588 R128InfoPtr info
= ctx
->driverPrivate
;
589 int width_bytes
= ctx
->shared
.virtualWidth
* ctx
->cpp
;
591 int bufferSize
= ((ctx
->shared
.virtualHeight
* width_bytes
593 & ~R128_BUFFER_ALIGN
);
594 int depthSize
= ((((ctx
->shared
.virtualHeight
+15) & ~15) * width_bytes
596 & ~R128_BUFFER_ALIGN
);
599 info
->frontOffset
= 0;
600 info
->frontPitch
= ctx
->shared
.virtualWidth
;
603 "Using %d MB AGP aperture\n", info
->agpSize
);
605 "Using %d MB for the ring buffer\n", info
->ringSize
);
607 "Using %d MB for vertex/indirect buffers\n", info
->bufSize
);
609 "Using %d MB for AGP textures\n", info
->agpTexSize
);
611 /* Front, back and depth buffers - everything else texture??
613 info
->textureSize
= ctx
->shared
.fbSize
- 2 * bufferSize
- depthSize
;
615 if (info
->textureSize
< 0)
618 l
= R128MinBits((info
->textureSize
-1) / R128_NR_TEX_REGIONS
);
619 if (l
< R128_LOG_TEX_GRANULARITY
) l
= R128_LOG_TEX_GRANULARITY
;
621 /* Round the texture size up to the nearest whole number of
622 * texture regions. Again, be greedy about this, don't
625 info
->log2TexGran
= l
;
626 info
->textureSize
= (info
->textureSize
>> l
) << l
;
628 /* Set a minimum usable local texture heap size. This will fit
629 * two 256x256x32bpp textures.
631 if (info
->textureSize
< 512 * 1024) {
632 info
->textureOffset
= 0;
633 info
->textureSize
= 0;
636 /* Reserve space for textures */
637 info
->textureOffset
= ((ctx
->shared
.fbSize
- info
->textureSize
+
641 /* Reserve space for the shared depth
644 info
->depthOffset
= ((info
->textureOffset
- depthSize
+
647 info
->depthPitch
= ctx
->shared
.virtualWidth
;
649 info
->backOffset
= ((info
->depthOffset
- bufferSize
+
652 info
->backPitch
= ctx
->shared
.virtualWidth
;
656 "Will use back buffer at offset 0x%x\n",
659 "Will use depth buffer at offset 0x%x\n",
662 "Will use %d kb for textures at offset 0x%x\n",
663 info
->textureSize
/1024, info
->textureOffset
);
669 /* Initialize the screen-specific data structures for the DRI and the
670 Rage 128. This is the main entry point to the device-specific
671 initialization code. It calls device-independent DRI functions to
672 create the DRI data structures and initialize the DRI state. */
673 static GLboolean
R128DRIScreenInit(DRIDriverContext
*ctx
)
675 R128InfoPtr info
= ctx
->driverPrivate
;
677 int err
, major
, minor
, patch
;
678 drmVersionPtr version
;
679 drm_r128_sarea_t
*pSAREAPriv
;
683 /* These modes are not supported (yet). */
687 "[dri] R128DRIScreenInit failed (depth %d not supported). "
688 "[dri] Disabling DRI.\n", ctx
->bpp
);
691 /* Only 16 and 32 color depths are supports currently. */
696 r128_drm_page_size
= getpagesize();
698 info
->registerSize
= ctx
->MMIOSize
;
699 ctx
->shared
.SAREASize
= SAREA_MAX
;
701 /* Note that drmOpen will try to load the kernel module, if needed. */
702 ctx
->drmFD
= drmOpen("r128", NULL
);
703 if (ctx
->drmFD
< 0) {
704 fprintf(stderr
, "[drm] drmOpen failed\n");
708 /* Check the r128 DRM version */
709 version
= drmGetVersion(ctx
->drmFD
);
711 if (version
->version_major
!= 2 ||
712 version
->version_minor
< 2) {
713 /* incompatible drm version */
715 "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
716 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
717 "[dri] Disabling the DRI.\n",
718 version
->version_major
,
719 version
->version_minor
,
720 version
->version_patchlevel
);
721 drmFreeVersion(version
);
724 info
->drmMinor
= version
->version_minor
;
725 drmFreeVersion(version
);
728 if ((err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
)) < 0) {
729 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
730 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
734 if (drmAddMap( ctx
->drmFD
,
736 ctx
->shared
.SAREASize
,
739 &ctx
->shared
.hSAREA
) < 0)
741 fprintf(stderr
, "[drm] drmAddMap failed\n");
744 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
745 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
747 if (drmMap( ctx
->drmFD
,
749 ctx
->shared
.SAREASize
,
750 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
752 fprintf(stderr
, "[drm] drmMap failed\n");
755 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
756 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
757 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
759 /* Need to AddMap the framebuffer and mmio regions here:
761 if (drmAddMap( ctx
->drmFD
,
762 (drm_handle_t
)ctx
->FBStart
,
766 &ctx
->shared
.hFrameBuffer
) < 0)
768 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
772 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
773 ctx
->shared
.hFrameBuffer
);
775 if (!R128MemoryInit(ctx
))
779 if (!info
->IsPCI
&& !R128DRIAgpInit(ctx
)) {
780 info
->IsPCI
= GL_TRUE
;
782 "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
784 "[agp] Make sure you have the agpgart kernel module loaded.\n");
787 /* Initialize PCIGART */
788 if (info
->IsPCI
&& !R128DRIPciInit(ctx
)) {
792 /* DRIScreenInit doesn't add all the
793 common mappings. Add additional
795 if (!R128DRIMapInit(ctx
)) {
799 /* Create a 'server' context so we can grab the lock for
800 * initialization ioctls.
802 if ((err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
)) != 0) {
803 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
807 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
809 /* Initialize the kernel data structures */
810 if (!R128DRIKernelInit(ctx
)) {
814 /* Initialize the vertex buffers list */
815 if (!R128DRIBufInit(ctx
)) {
822 /* Initialize and start the CCE if required */
825 /* Quick hack to clear the front & back buffers. Could also use
826 * the clear ioctl to do this, but would need to setup hw state
829 drimemsetio((char *)ctx
->FBAddress
+ info
->frontOffset
,
831 info
->frontPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
833 drimemsetio((char *)ctx
->FBAddress
+ info
->backOffset
,
835 info
->backPitch
* ctx
->cpp
* ctx
->shared
.virtualHeight
);
837 pSAREAPriv
= (drm_r128_sarea_t
*)(((char*)ctx
->pSAREA
) +
838 sizeof(drm_sarea_t
));
839 memset(pSAREAPriv
, 0, sizeof(*pSAREAPriv
));
841 /* This is the struct passed to radeon_dri.so for its initialization */
842 ctx
->driverClientMsg
= malloc(sizeof(R128DRIRec
));
843 ctx
->driverClientMsgSize
= sizeof(R128DRIRec
);
845 pR128DRI
= (R128DRIPtr
)ctx
->driverClientMsg
;
846 pR128DRI
->deviceID
= info
->Chipset
;
847 pR128DRI
->width
= ctx
->shared
.virtualWidth
;
848 pR128DRI
->height
= ctx
->shared
.virtualHeight
;
849 pR128DRI
->depth
= ctx
->bpp
;
850 pR128DRI
->bpp
= ctx
->bpp
;
852 pR128DRI
->IsPCI
= info
->IsPCI
;
853 pR128DRI
->AGPMode
= info
->agpMode
;
855 pR128DRI
->frontOffset
= info
->frontOffset
;
856 pR128DRI
->frontPitch
= info
->frontPitch
;
857 pR128DRI
->backOffset
= info
->backOffset
;
858 pR128DRI
->backPitch
= info
->backPitch
;
859 pR128DRI
->depthOffset
= info
->depthOffset
;
860 pR128DRI
->depthPitch
= info
->depthPitch
;
861 pR128DRI
->spanOffset
= info
->spanOffset
;
862 pR128DRI
->textureOffset
= info
->textureOffset
;
863 pR128DRI
->textureSize
= info
->textureSize
;
864 pR128DRI
->log2TexGran
= info
->log2TexGran
;
866 pR128DRI
->registerHandle
= info
->registerHandle
;
867 pR128DRI
->registerSize
= info
->registerSize
;
869 pR128DRI
->agpTexHandle
= info
->agpTexHandle
;
870 pR128DRI
->agpTexMapSize
= info
->agpTexMapSize
;
871 pR128DRI
->log2AGPTexGran
= info
->log2AGPTexGran
;
872 pR128DRI
->agpTexOffset
= info
->agpTexStart
;
873 pR128DRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
878 /* The screen is being closed, so clean up any state and free any
879 resources used by the DRI. */
880 void R128DRICloseScreen(const DRIDriverContext
*ctx
)
882 R128InfoPtr info
= ctx
->driverPrivate
;
883 drm_r128_init_t drmInfo
;
885 /* Stop the CCE if it is still in use */
886 R128CCE_STOP(ctx
, info
);
889 drmCtlUninstHandler(ctx
->drmFD
);
893 /* De-allocate vertex buffers */
895 drmUnmapBufs(info
->buffers
);
896 info
->buffers
= NULL
;
899 /* De-allocate all kernel resources */
900 memset(&drmInfo
, 0, sizeof(drmInfo
));
901 drmInfo
.func
= R128_CLEANUP_CCE
;
902 drmCommandWrite(ctx
->drmFD
, DRM_R128_INIT
,
903 &drmInfo
, sizeof(drmInfo
));
905 /* De-allocate all AGP resources */
907 drmUnmap(info
->agpTex
, info
->agpTexMapSize
);
911 drmUnmap(info
->buf
, info
->bufMapSize
);
914 if (info
->ringReadPtr
) {
915 drmUnmap(info
->ringReadPtr
, info
->ringReadMapSize
);
916 info
->ringReadPtr
= NULL
;
919 drmUnmap(info
->ring
, info
->ringMapSize
);
922 if (info
->agpMemHandle
!= DRM_AGP_NO_HANDLE
) {
923 drmAgpUnbind(ctx
->drmFD
, info
->agpMemHandle
);
924 drmAgpFree(ctx
->drmFD
, info
->agpMemHandle
);
925 info
->agpMemHandle
= 0;
926 drmAgpRelease(ctx
->drmFD
);
928 if (info
->pciMemHandle
) {
929 drmScatterGatherFree(ctx
->drmFD
, info
->pciMemHandle
);
930 info
->pciMemHandle
= 0;
934 static GLboolean
R128PreInitDRI(const DRIDriverContext
*ctx
)
936 R128InfoPtr info
= ctx
->driverPrivate
;
938 /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
939 info
->CCEMode
= R128_DEFAULT_CCE_BM_MODE
;
940 info
->CCESecure
= GL_TRUE
;
942 info
->agpMode
= R128_DEFAULT_AGP_MODE
;
943 info
->agpSize
= R128_DEFAULT_AGP_SIZE
;
944 info
->ringSize
= R128_DEFAULT_RING_SIZE
;
945 info
->bufSize
= R128_DEFAULT_BUFFER_SIZE
;
946 info
->agpTexSize
= R128_DEFAULT_AGP_TEX_SIZE
;
948 info
->CCEusecTimeout
= R128_DEFAULT_CCE_TIMEOUT
;
954 * \brief Initialize the framebuffer device mode
956 * \param ctx display handle.
958 * \return one on success, or zero on failure.
960 * Fills in \p info with some default values and some information from \p ctx
961 * and then calls R128ScreenInit() for the screen initialization.
963 * Before exiting clears the framebuffer memory accessing it directly.
965 static int R128InitFBDev( DRIDriverContext
*ctx
)
967 R128InfoPtr info
= calloc(1, sizeof(*info
));
970 int dummy
= ctx
->shared
.virtualWidth
;
972 switch (ctx
->bpp
/ 8) {
973 case 1: dummy
= (ctx
->shared
.virtualWidth
+ 127) & ~127; break;
974 case 2: dummy
= (ctx
->shared
.virtualWidth
+ 31) & ~31; break;
976 case 4: dummy
= (ctx
->shared
.virtualWidth
+ 15) & ~15; break;
979 ctx
->shared
.virtualWidth
= dummy
;
982 ctx
->driverPrivate
= (void *)info
;
984 info
->Chipset
= ctx
->chipset
;
986 switch (info
->Chipset
) {
987 case PCI_DEVICE_ID_ATI_RAGE128_LE
:
988 case PCI_DEVICE_ID_ATI_RAGE128_RE
:
989 case PCI_DEVICE_ID_ATI_RAGE128_RK
:
990 case PCI_DEVICE_ID_ATI_RAGE128_PD
:
991 case PCI_DEVICE_ID_ATI_RAGE128_PP
:
992 case PCI_DEVICE_ID_ATI_RAGE128_PR
:
993 /* This is a PCI card */
994 info
->IsPCI
= GL_TRUE
;
997 /* This is an AGP card */
998 info
->IsPCI
= GL_FALSE
;
1002 info
->frontPitch
= ctx
->shared
.virtualWidth
;
1003 info
->LinearAddr
= ctx
->FBStart
& 0xfc000000;
1005 if (!R128PreInitDRI(ctx
))
1008 if (!R128DRIScreenInit(ctx
))
1016 * \brief The screen is being closed, so clean up any state and free any
1017 * resources used by the DRI.
1019 * \param ctx display handle.
1021 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1024 static void R128HaltFBDev( DRIDriverContext
*ctx
)
1026 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1027 drmClose(ctx
->drmFD
);
1029 if (ctx
->driverPrivate
) {
1030 free(ctx
->driverPrivate
);
1031 ctx
->driverPrivate
= 0;
1037 * \brief Validate the fbdev mode.
1039 * \param ctx display handle.
1041 * \return one on success, or zero on failure.
1043 * Saves some registers and returns 1.
1045 * \sa R128PostValidateMode().
1047 static int R128ValidateMode( const DRIDriverContext
*ctx
)
1054 * \brief Examine mode returned by fbdev.
1056 * \param ctx display handle.
1058 * \return one on success, or zero on failure.
1060 * Restores registers that fbdev has clobbered and returns 1.
1062 * \sa R128ValidateMode().
1064 static int R128PostValidateMode( const DRIDriverContext
*ctx
)
1071 * \brief Shutdown the drawing engine.
1073 * \param ctx display handle
1075 * Turns off the command processor engine & restores the graphics card
1076 * to a state that fbdev understands.
1078 static int R128EngineShutdown( const DRIDriverContext
*ctx
)
1084 * \brief Restore the drawing engine.
1086 * \param ctx display handle
1088 * Resets the graphics card and sets initial values for several registers of
1089 * the card's drawing engine.
1091 * Turns on the R128 command processor engine (i.e., the ringbuffer).
1093 static int R128EngineRestore( const DRIDriverContext
*ctx
)
1100 * \brief Exported driver interface for Mini GLX.
1104 const struct DRIDriverRec __driDriver
= {
1106 R128PostValidateMode
,