1140 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1140 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * $Id$
 | 
						|
 *
 | 
						|
 * Copyright © 2003 Eric Anholt
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of Eric Anholt not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Eric Anholt makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
/* $Header$ */
 | 
						|
 | 
						|
#include <sys/time.h>
 | 
						|
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <config.h>
 | 
						|
#endif
 | 
						|
#include "ati.h"
 | 
						|
#include "ati_reg.h"
 | 
						|
#include "ati_dma.h"
 | 
						|
#include "ati_dri.h"
 | 
						|
#include "ati_dripriv.h"
 | 
						|
#include "sarea.h"
 | 
						|
#include "ati_sarea.h"
 | 
						|
#include "ati_draw.h"
 | 
						|
#include "r128_common.h"
 | 
						|
#include "radeon_common.h"
 | 
						|
 | 
						|
/* ?? HACK - for now, put this here... */
 | 
						|
/* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
 | 
						|
#if defined(__alpha__)
 | 
						|
# define DRM_PAGE_SIZE 8192
 | 
						|
#elif defined(__ia64__)
 | 
						|
# define DRM_PAGE_SIZE getpagesize()
 | 
						|
#else
 | 
						|
# define DRM_PAGE_SIZE 4096
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef GLXEXT
 | 
						|
/* Initialize the visual configs that are supported by the hardware.
 | 
						|
 * These are combined with the visual configs that the indirect
 | 
						|
 * rendering core supports, and the intersection is exported to the
 | 
						|
 * client.
 | 
						|
 */
 | 
						|
static Bool ATIInitVisualConfigs(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	int numConfigs = 0;
 | 
						|
	__GLXvisualConfig *pConfigs = NULL;
 | 
						|
	ATIConfigPrivPtr pATIConfigs = NULL;
 | 
						|
	ATIConfigPrivPtr *pATIConfigPtrs = NULL;
 | 
						|
	int i, accum, stencil, db, use_db;
 | 
						|
	int depth = pScreenPriv->screen->fb[0].depth;
 | 
						|
	int bpp = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	if (depth != 16 && (depth != 24 || bpp != 32))
 | 
						|
		ErrorF("DRI GLX unsupported at %d/%d depth/bpp\n", depth, bpp);
 | 
						|
 | 
						|
	if (atis->depthOffset != 0)
 | 
						|
		use_db = 1;
 | 
						|
	else
 | 
						|
		use_db = 0;
 | 
						|
 | 
						|
	numConfigs = 4;
 | 
						|
	if (use_db)
 | 
						|
		numConfigs *= 2;
 | 
						|
 | 
						|
	pConfigs = xcalloc(sizeof(__GLXvisualConfig), numConfigs);
 | 
						|
	pATIConfigs = xcalloc(sizeof(ATIConfigPrivRec), numConfigs);
 | 
						|
	pATIConfigPtrs = xcalloc(sizeof(ATIConfigPrivPtr), numConfigs);
 | 
						|
	if (pConfigs == NULL || pATIConfigs == NULL || pATIConfigPtrs == NULL) {
 | 
						|
		xfree(pConfigs);
 | 
						|
		xfree(pATIConfigs);
 | 
						|
		xfree(pATIConfigPtrs);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	i = 0;
 | 
						|
	for (db = 0; db <= use_db; db++) {
 | 
						|
	  for (accum = 0; accum <= 1; accum++) {
 | 
						|
	    for (stencil = 0; stencil <= 1; stencil++) {
 | 
						|
		pATIConfigPtrs[i] = &pATIConfigs[i];
 | 
						|
 | 
						|
		pConfigs[i].vid                = (VisualID)(-1);
 | 
						|
		pConfigs[i].class              = -1;
 | 
						|
		pConfigs[i].rgba               = TRUE;
 | 
						|
		if (depth == 16) {
 | 
						|
			pConfigs[i].redSize            = 5;
 | 
						|
			pConfigs[i].greenSize          = 6;
 | 
						|
			pConfigs[i].blueSize           = 5;
 | 
						|
			pConfigs[i].alphaSize          = 0;
 | 
						|
			pConfigs[i].redMask            = 0x0000F800;
 | 
						|
			pConfigs[i].greenMask          = 0x000007E0;
 | 
						|
			pConfigs[i].blueMask           = 0x0000001F;
 | 
						|
			pConfigs[i].alphaMask          = 0x00000000;
 | 
						|
		} else {
 | 
						|
			pConfigs[i].redSize            = 8;
 | 
						|
			pConfigs[i].greenSize          = 8;
 | 
						|
			pConfigs[i].blueSize           = 8;
 | 
						|
			pConfigs[i].alphaSize          = 8;
 | 
						|
			pConfigs[i].redMask            = 0x00FF0000;
 | 
						|
			pConfigs[i].greenMask          = 0x0000FF00;
 | 
						|
			pConfigs[i].blueMask           = 0x000000FF;
 | 
						|
			pConfigs[i].alphaMask          = 0xFF000000;
 | 
						|
		}
 | 
						|
		if (accum) { /* Simulated in software */
 | 
						|
			pConfigs[i].accumRedSize   = 16;
 | 
						|
			pConfigs[i].accumGreenSize = 16;
 | 
						|
			pConfigs[i].accumBlueSize  = 16;
 | 
						|
			if (depth == 16)
 | 
						|
				pConfigs[i].accumAlphaSize = 0;
 | 
						|
			else
 | 
						|
				pConfigs[i].accumAlphaSize = 16;
 | 
						|
		} else {
 | 
						|
		    pConfigs[i].accumRedSize   = 0;
 | 
						|
		    pConfigs[i].accumGreenSize = 0;
 | 
						|
		    pConfigs[i].accumBlueSize  = 0;
 | 
						|
		    pConfigs[i].accumAlphaSize = 0;
 | 
						|
		}
 | 
						|
		if (db)
 | 
						|
		    pConfigs[i].doubleBuffer   = TRUE;
 | 
						|
		else
 | 
						|
		    pConfigs[i].doubleBuffer   = FALSE;
 | 
						|
		pConfigs[i].stereo             = FALSE;
 | 
						|
		if (depth == 16) {
 | 
						|
			pConfigs[i].bufferSize         = 16;
 | 
						|
			pConfigs[i].depthSize          = 16;
 | 
						|
			if (stencil)
 | 
						|
			    pConfigs[i].stencilSize    = 8;
 | 
						|
			else
 | 
						|
			    pConfigs[i].stencilSize    = 0;
 | 
						|
		} else {
 | 
						|
			pConfigs[i].bufferSize         = 32;
 | 
						|
			if (stencil) {
 | 
						|
			    pConfigs[i].depthSize      = 24;
 | 
						|
			    pConfigs[i].stencilSize    = 8;
 | 
						|
			} else {
 | 
						|
			    pConfigs[i].depthSize      = 24;
 | 
						|
			    pConfigs[i].stencilSize    = 0;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		pConfigs[i].auxBuffers         = 0;
 | 
						|
		pConfigs[i].level              = 0;
 | 
						|
		if (accum) {
 | 
						|
		   pConfigs[i].visualRating    = GLX_SLOW_CONFIG;
 | 
						|
		} else {
 | 
						|
		   pConfigs[i].visualRating    = GLX_NONE;
 | 
						|
		}
 | 
						|
		pConfigs[i].transparentPixel   = GLX_NONE;
 | 
						|
		pConfigs[i].transparentRed     = 0;
 | 
						|
		pConfigs[i].transparentGreen   = 0;
 | 
						|
		pConfigs[i].transparentBlue    = 0;
 | 
						|
		pConfigs[i].transparentAlpha   = 0;
 | 
						|
		pConfigs[i].transparentIndex   = 0;
 | 
						|
		i++;
 | 
						|
	    }
 | 
						|
	  }
 | 
						|
	}
 | 
						|
 | 
						|
	atis->numVisualConfigs = numConfigs;
 | 
						|
	atis->pVisualConfigs = pConfigs;
 | 
						|
	atis->pVisualConfigsPriv = pATIConfigs;
 | 
						|
	GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pATIConfigPtrs);
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
#endif /* GLXEXT */
 | 
						|
 | 
						|
static void
 | 
						|
ATIDRIInitGARTValues(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	int s, l;
 | 
						|
 | 
						|
	atis->gartOffset = 0;
 | 
						|
 | 
						|
	/* Initialize the ring buffer data */
 | 
						|
	atis->ringStart       = atis->gartOffset;
 | 
						|
	atis->ringMapSize     = atis->ringSize * 1024 * 1024 + DRM_PAGE_SIZE;
 | 
						|
 | 
						|
	atis->ringReadOffset  = atis->ringStart + atis->ringMapSize;
 | 
						|
	atis->ringReadMapSize = DRM_PAGE_SIZE;
 | 
						|
 | 
						|
	/* Reserve space for vertex/indirect buffers */
 | 
						|
	atis->bufStart        = atis->ringReadOffset + atis->ringReadMapSize;
 | 
						|
	atis->bufMapSize      = atis->bufSize * 1024 * 1024;
 | 
						|
 | 
						|
	/* Reserve the rest for GART textures */
 | 
						|
	atis->gartTexStart     = atis->bufStart + atis->bufMapSize;
 | 
						|
	s = (atis->gartSize * 1024 * 1024 - atis->gartTexStart);
 | 
						|
	l = ATILog2((s-1) / ATI_NR_TEX_REGIONS);
 | 
						|
	if (l < ATI_LOG_TEX_GRANULARITY) l = ATI_LOG_TEX_GRANULARITY;
 | 
						|
	atis->gartTexMapSize   = (s >> l) << l;
 | 
						|
	atis->log2GARTTexGran  = l;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ATIDRIAddAndMap(int fd, drmHandle offset, drmSize size,
 | 
						|
    drmMapType type, drmMapFlags flags, drmHandlePtr handle,
 | 
						|
    drmAddressPtr address, char *desc)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
 | 
						|
	name = (type == DRM_AGP) ? "agp" : "pci";
 | 
						|
 | 
						|
	if (drmAddMap(fd, offset, size, type, flags, handle) < 0) {
 | 
						|
		ErrorF("[%s] Could not add %s mapping\n", name, desc);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[%s] %s handle = 0x%08lx\n", name, desc, *handle);
 | 
						|
 | 
						|
	if (drmMap(fd, *handle, size, address) < 0) {
 | 
						|
		ErrorF("[%s] Could not map %s\n", name, desc);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[%s] %s mapped at 0x%08lx\n", name, desc, *address);
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* Initialize the AGP state.  Request memory for use in AGP space, and
 | 
						|
   initialize the Rage 128 registers to point to that memory. */
 | 
						|
static Bool
 | 
						|
ATIDRIAgpInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	unsigned char *mmio = atic->reg_base;
 | 
						|
	unsigned long mode;
 | 
						|
	int           ret;
 | 
						|
	CARD32        cntl, chunk;
 | 
						|
 | 
						|
	if (drmAgpAcquire(atic->drmFd) < 0) {
 | 
						|
		ErrorF("[agp] AGP not available\n");
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	ATIDRIInitGARTValues(pScreen);
 | 
						|
 | 
						|
	mode = drmAgpGetMode(atic->drmFd);
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		mode &= ~RADEON_AGP_MODE_MASK;
 | 
						|
		mode |= RADEON_AGP_1X_MODE;
 | 
						|
	} else {
 | 
						|
		mode &= ~R128_AGP_MODE_MASK;
 | 
						|
		mode |= R128_AGP_1X_MODE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (drmAgpEnable(atic->drmFd, mode) < 0) {
 | 
						|
		ErrorF("[agp] AGP not enabled\n");
 | 
						|
		drmAgpRelease(atic->drmFd);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[agp] Mode 0x%08x selected\n", drmAgpGetMode(atic->drmFd));
 | 
						|
 | 
						|
	if ((ret = drmAgpAlloc(atic->drmFd, atis->gartSize * 1024 * 1024, 0,
 | 
						|
	    NULL, &atis->agpMemHandle)) < 0) {
 | 
						|
		ErrorF("[agp] Out of memory (%d)\n", ret);
 | 
						|
		drmAgpRelease(atic->drmFd);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[agp] %d kB allocated with handle 0x%08lx\n",
 | 
						|
	    atis->gartSize * 1024, (long)atis->agpMemHandle);
 | 
						|
 | 
						|
	if (drmAgpBind(atic->drmFd, atis->agpMemHandle, atis->gartOffset) < 0) {
 | 
						|
		ErrorF("[agp] Could not bind\n");
 | 
						|
		drmAgpFree(atic->drmFd, atis->agpMemHandle);
 | 
						|
		drmAgpRelease(atic->drmFd);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->ringStart, atis->ringMapSize,
 | 
						|
	    DRM_AGP, DRM_READ_ONLY, &atis->ringHandle,
 | 
						|
	    (drmAddressPtr)&atis->ring, "ring"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->ringReadOffset,
 | 
						|
	    atis->ringReadMapSize, DRM_AGP, DRM_READ_ONLY,
 | 
						|
	    &atis->ringReadPtrHandle, (drmAddressPtr)&atis->ringReadPtr,
 | 
						|
	    "ring read ptr"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->bufStart, atis->bufMapSize,
 | 
						|
	    DRM_AGP, 0, &atis->bufHandle, (drmAddressPtr)&atis->buf,
 | 
						|
	    "vertex/indirect buffers"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->gartTexStart,
 | 
						|
	    atis->gartTexMapSize, DRM_AGP, 0, &atis->gartTexHandle,
 | 
						|
	    (drmAddressPtr)&atis->gartTex, "AGP texture map"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (atic->is_r100) {
 | 
						|
		/* Workaround for some hardware bugs */
 | 
						|
		cntl = MMIO_IN32(mmio, ATI_REG_AGP_CNTL);
 | 
						|
		MMIO_OUT32(mmio, ATI_REG_AGP_CNTL, cntl |
 | 
						|
		    RADEON_PENDING_SLOTS_VAL | RADEON_PENDING_SLOTS_SEL);
 | 
						|
	} else if (!atic->is_radeon) {
 | 
						|
		cntl = MMIO_IN32(mmio, ATI_REG_AGP_CNTL);
 | 
						|
		cntl &= ~R128_AGP_APER_SIZE_MASK;
 | 
						|
		switch (atis->gartSize) {
 | 
						|
		case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
 | 
						|
		case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
 | 
						|
		case  64: cntl |= R128_AGP_APER_SIZE_64MB;  break;
 | 
						|
		case  32: cntl |= R128_AGP_APER_SIZE_32MB;  break;
 | 
						|
		case  16: cntl |= R128_AGP_APER_SIZE_16MB;  break;
 | 
						|
		case   8: cntl |= R128_AGP_APER_SIZE_8MB;   break;
 | 
						|
		case   4: cntl |= R128_AGP_APER_SIZE_4MB;   break;
 | 
						|
		default:
 | 
						|
			ErrorF("[agp] Illegal aperture size %d kB\n", atis->gartSize *
 | 
						|
			    1024);
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
		MMIO_OUT32(mmio, ATI_REG_AGP_CNTL, cntl);
 | 
						|
 | 
						|
		/* Disable Rage 128 PCIGART registers */
 | 
						|
		chunk = MMIO_IN32(mmio, R128_REG_BM_CHUNK_0_VAL);
 | 
						|
		chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
 | 
						|
		    R128_BM_PM4_RD_FORCE_TO_PCI |
 | 
						|
		    R128_BM_GLOBAL_FORCE_TO_PCI);
 | 
						|
		MMIO_OUT32(mmio, R128_REG_BM_CHUNK_0_VAL, chunk);
 | 
						|
 | 
						|
		/* Ensure AGP GART is used (for now) */
 | 
						|
		MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 1);
 | 
						|
	}
 | 
						|
 | 
						|
	MMIO_OUT32(mmio, ATI_REG_AGP_BASE, drmAgpBase(atic->drmFd)); 
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
ATIDRIPciInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	unsigned char *mmio = atic->reg_base;
 | 
						|
	CARD32 chunk;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	ATIDRIInitGARTValues(pScreen);
 | 
						|
 | 
						|
	ret = drmScatterGatherAlloc(atic->drmFd, atis->gartSize * 1024 * 1024,
 | 
						|
	    &atis->pciMemHandle);
 | 
						|
	if (ret < 0) {
 | 
						|
		ErrorF("[pci] Out of memory (%d)\n", ret);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[pci] %d kB allocated with handle 0x%08lx\n",
 | 
						|
	    atis->gartSize * 1024, (long)atis->pciMemHandle);
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->ringStart, atis->ringMapSize,
 | 
						|
	    DRM_SCATTER_GATHER, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
 | 
						|
	    &atis->ringHandle, (drmAddressPtr)&atis->ring, "ring"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->ringReadOffset,
 | 
						|
	    atis->ringReadMapSize, DRM_SCATTER_GATHER,
 | 
						|
	    DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
 | 
						|
	    &atis->ringReadPtrHandle, (drmAddressPtr)&atis->ringReadPtr,
 | 
						|
	    "ring read ptr"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->bufStart, atis->bufMapSize,
 | 
						|
	    DRM_SCATTER_GATHER, 0, &atis->bufHandle, (drmAddressPtr)&atis->buf,
 | 
						|
	    "vertex/indirect buffers"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!ATIDRIAddAndMap(atic->drmFd, atis->gartTexStart,
 | 
						|
	    atis->gartTexMapSize, DRM_SCATTER_GATHER, 0, &atis->gartTexHandle,
 | 
						|
	    (drmAddressPtr)&atis->gartTex, "PCI texture map"))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	if (!atic->is_radeon) {
 | 
						|
		/* Force PCI GART mode */
 | 
						|
		chunk = MMIO_IN32(mmio, R128_REG_BM_CHUNK_0_VAL);
 | 
						|
		chunk |= (R128_BM_PTR_FORCE_TO_PCI |
 | 
						|
		    R128_BM_PM4_RD_FORCE_TO_PCI | R128_BM_GLOBAL_FORCE_TO_PCI);
 | 
						|
		MMIO_OUT32(mmio, R128_REG_BM_CHUNK_0_VAL, chunk);
 | 
						|
		/* Ensure PCI GART is used */
 | 
						|
		MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 0);
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Initialize the kernel data structures. */
 | 
						|
static int
 | 
						|
R128DRIKernelInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	drmR128Init drmInfo;
 | 
						|
	int bpp = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	memset(&drmInfo, 0, sizeof(drmR128Init) );
 | 
						|
 | 
						|
	drmInfo.func                = DRM_R128_INIT_CCE;
 | 
						|
	drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
 | 
						|
	drmInfo.is_pci              = !atis->using_agp;
 | 
						|
	drmInfo.cce_mode            = R128_PM4_64BM_64VCBM_64INDBM;
 | 
						|
	drmInfo.cce_secure          = TRUE;
 | 
						|
	drmInfo.ring_size           = atis->ringSize * 1024 * 1024;
 | 
						|
	drmInfo.usec_timeout        = atis->DMAusecTimeout;
 | 
						|
 | 
						|
	drmInfo.front_offset        = atis->frontOffset;
 | 
						|
	drmInfo.front_pitch         = atis->frontPitch / (bpp / 8);
 | 
						|
	drmInfo.back_offset         = atis->backOffset;
 | 
						|
	drmInfo.back_pitch          = atis->backPitch / (bpp / 8);
 | 
						|
	drmInfo.fb_bpp              = bpp;
 | 
						|
 | 
						|
	drmInfo.depth_offset        = atis->depthOffset;
 | 
						|
	drmInfo.depth_pitch         = atis->depthPitch / (bpp / 8);
 | 
						|
	drmInfo.depth_bpp           = bpp;
 | 
						|
 | 
						|
	drmInfo.span_offset         = atis->spanOffset;
 | 
						|
 | 
						|
	drmInfo.fb_offset           = atis->fbHandle;
 | 
						|
	drmInfo.mmio_offset         = atis->registerHandle;
 | 
						|
	drmInfo.ring_offset         = atis->ringHandle;
 | 
						|
	drmInfo.ring_rptr_offset    = atis->ringReadPtrHandle;
 | 
						|
	drmInfo.buffers_offset      = atis->bufHandle;
 | 
						|
	drmInfo.agp_textures_offset = atis->gartTexHandle;
 | 
						|
 | 
						|
	if (drmCommandWrite(atic->drmFd, DRM_R128_INIT, &drmInfo,
 | 
						|
	    sizeof(drmR128Init)) < 0)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* Initialize the kernel data structures */
 | 
						|
static int
 | 
						|
RadeonDRIKernelInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	drmRadeonInit drmInfo;
 | 
						|
 | 
						|
	memset(&drmInfo, 0, sizeof(drmRadeonInit));
 | 
						|
 | 
						|
	if (atic->is_r200)
 | 
						|
	    drmInfo.func             = DRM_RADEON_INIT_R200_CP;
 | 
						|
	else
 | 
						|
	    drmInfo.func             = DRM_RADEON_INIT_CP;
 | 
						|
 | 
						|
	drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
 | 
						|
	drmInfo.is_pci              = !atis->using_agp;
 | 
						|
	drmInfo.cp_mode             = RADEON_CSQ_PRIBM_INDBM;
 | 
						|
	drmInfo.gart_size           = atis->gartSize * 1024 * 1024;
 | 
						|
	drmInfo.ring_size           = atis->ringSize * 1024 * 1024;
 | 
						|
	drmInfo.usec_timeout        = atis->DMAusecTimeout;
 | 
						|
 | 
						|
	drmInfo.front_offset        = atis->frontOffset;
 | 
						|
	drmInfo.front_pitch         = atis->frontPitch;
 | 
						|
	drmInfo.back_offset         = atis->backOffset;
 | 
						|
	drmInfo.back_pitch          = atis->backPitch;
 | 
						|
	drmInfo.fb_bpp              = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
	drmInfo.depth_offset        = atis->depthOffset;
 | 
						|
	drmInfo.depth_pitch         = atis->depthPitch;
 | 
						|
	drmInfo.depth_bpp           = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	drmInfo.fb_offset           = atis->fbHandle;
 | 
						|
	drmInfo.mmio_offset         = atis->registerHandle;
 | 
						|
	drmInfo.ring_offset         = atis->ringHandle;
 | 
						|
	drmInfo.ring_rptr_offset    = atis->ringReadPtrHandle;
 | 
						|
	drmInfo.buffers_offset      = atis->bufHandle;
 | 
						|
	drmInfo.gart_textures_offset = atis->gartTexHandle;
 | 
						|
 | 
						|
	if (drmCommandWrite(atic->drmFd, DRM_RADEON_CP_INIT,
 | 
						|
	    &drmInfo, sizeof(drmRadeonInit)) < 0)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* Add a map for the vertex buffers that will be accessed by any
 | 
						|
   DRI-based clients. */
 | 
						|
static Bool
 | 
						|
ATIDRIBufInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	int type, size;
 | 
						|
 | 
						|
	if (atic->is_radeon)
 | 
						|
		size = RADEON_BUFFER_SIZE;
 | 
						|
	else
 | 
						|
		size = R128_BUFFER_SIZE;
 | 
						|
 | 
						|
	if (atis->using_agp)
 | 
						|
		type = DRM_AGP_BUFFER;
 | 
						|
	else
 | 
						|
		type = DRM_SG_BUFFER;
 | 
						|
 | 
						|
	/* Initialize vertex buffers */
 | 
						|
	atis->bufNumBufs = drmAddBufs(atic->drmFd, atis->bufMapSize / size,
 | 
						|
	    size, type, atis->bufStart);
 | 
						|
 | 
						|
	if (atis->bufNumBufs <= 0) {
 | 
						|
		ErrorF("[drm] Could not create vertex/indirect buffers list\n");
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[drm] Added %d %d byte vertex/indirect buffers\n",
 | 
						|
	    atis->bufNumBufs, size);
 | 
						|
 | 
						|
	atis->buffers = drmMapBufs(atic->drmFd);
 | 
						|
	if (atis->buffers == NULL) {
 | 
						|
		ErrorF("[drm] Failed to map vertex/indirect buffers list\n");
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[drm] Mapped %d vertex/indirect buffers\n",
 | 
						|
	    atis->buffers->count);
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static int 
 | 
						|
ATIDRIIrqInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
 | 
						|
	if (atis->irqEnabled)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	atis->irqEnabled = drmCtlInstHandler(atic->drmFd, 0);
 | 
						|
 | 
						|
	if (!atis->irqEnabled)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void ATIDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
 | 
						|
    DRIContextType oldContextType, void *oldContext,
 | 
						|
    DRIContextType newContextType, void *newContext)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
 | 
						|
	if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
 | 
						|
	    (newContextType==DRI_2D_CONTEXT)) {
 | 
						|
		/* Entering from Wakeup */
 | 
						|
		KdMarkSync(pScreen);
 | 
						|
	}
 | 
						|
	if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
 | 
						|
	    (newContextType==DRI_2D_CONTEXT)) {
 | 
						|
		/* Exiting from Block Handler */
 | 
						|
		if (atis->dma_started)
 | 
						|
			ATIFlushIndirect(atis, 1);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static Bool ATIDRIFinishScreenInit(ScreenPtr pScreen);
 | 
						|
 | 
						|
/* Initialize the screen-specific data structures for the Radeon or
 | 
						|
   Rage 128.  This is the main entry point to the device-specific
 | 
						|
   initialization code.  It calls device-independent DRI functions to
 | 
						|
   create the DRI data structures and initialize the DRI state. */
 | 
						|
Bool
 | 
						|
ATIDRIScreenInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	void *scratch_ptr;
 | 
						|
	int scratch_int;
 | 
						|
	DRIInfoPtr pDRIInfo;
 | 
						|
	int devSareaSize;
 | 
						|
	drmSetVersion sv;
 | 
						|
 | 
						|
	if (pScreenPriv->screen->fb[0].depth < 16 ||
 | 
						|
	    pScreenPriv->screen->fb[0].bitsPerPixel == 24) {
 | 
						|
		ErrorF("DRI unsupported at this depth/bpp, disabling.\n");
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	atis->agpMode = 1;
 | 
						|
	atis->gartSize = 8;
 | 
						|
	atis->ringSize = 1;
 | 
						|
	atis->bufSize = 2;
 | 
						|
	atis->gartTexSize = 1;
 | 
						|
	atis->DMAusecTimeout = 10000;
 | 
						|
 | 
						|
	if (atic->drmFd < 0)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	sv.drm_di_major = -1;
 | 
						|
	sv.drm_dd_major = -1;
 | 
						|
	drmSetInterfaceVersion(atic->drmFd, &sv);
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		if (sv.drm_dd_major != 1 || sv.drm_dd_minor < 6) {
 | 
						|
			ErrorF("[dri] radeon kernel module version is %d.%d "
 | 
						|
			    "but version 1.6 or greater is needed.\n",
 | 
						|
			    sv.drm_dd_major, sv.drm_dd_minor);
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (sv.drm_dd_major != 2 || sv.drm_dd_minor < 2) {
 | 
						|
			ErrorF("[dri] r128 kernel module version is %d.%d "
 | 
						|
			    "but version 2.2 or greater is needed.\n",
 | 
						|
			    sv.drm_dd_major, sv.drm_dd_minor);
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Create the DRI data structure, and fill it in before calling the
 | 
						|
	 * DRIScreenInit().
 | 
						|
	 */
 | 
						|
	pDRIInfo = DRICreateInfoRec();
 | 
						|
	if (pDRIInfo == NULL)
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	atis->pDRIInfo = pDRIInfo;
 | 
						|
	pDRIInfo->busIdString = atic->busid;
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		pDRIInfo->drmDriverName = "radeon";
 | 
						|
		if (atic->is_r100)
 | 
						|
			pDRIInfo->clientDriverName = "radeon";
 | 
						|
		else
 | 
						|
			pDRIInfo->clientDriverName = "r200";
 | 
						|
	} else {
 | 
						|
		pDRIInfo->drmDriverName = "r128";
 | 
						|
		pDRIInfo->clientDriverName = "r128";
 | 
						|
	}
 | 
						|
	pDRIInfo->ddxDriverMajorVersion = 4;
 | 
						|
	pDRIInfo->ddxDriverMinorVersion = 0;
 | 
						|
	pDRIInfo->ddxDriverPatchVersion = 0;
 | 
						|
	pDRIInfo->frameBufferPhysicalAddress =
 | 
						|
	    pScreenPriv->card->attr.address[0] & 0xfc000000;
 | 
						|
	pDRIInfo->frameBufferSize = pScreenPriv->screen->memory_size;
 | 
						|
	pDRIInfo->frameBufferStride = pScreenPriv->screen->fb[0].byteStride;
 | 
						|
	pDRIInfo->ddxDrawableTableEntry = SAREA_MAX_DRAWABLES;
 | 
						|
	pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
 | 
						|
 | 
						|
	/* For now the mapping works by using a fixed size defined
 | 
						|
	 * in the SAREA header
 | 
						|
	 */
 | 
						|
	pDRIInfo->SAREASize = SAREA_MAX;
 | 
						|
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		pDRIInfo->devPrivateSize = sizeof(RADEONDRIRec);
 | 
						|
		devSareaSize = sizeof(RADEONSAREAPriv);
 | 
						|
	} else {
 | 
						|
		pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
 | 
						|
		devSareaSize = sizeof(R128SAREAPriv);
 | 
						|
	}
 | 
						|
 | 
						|
	if (sizeof(XF86DRISAREARec) + devSareaSize > SAREA_MAX) {
 | 
						|
		ErrorF("[dri] Data does not fit in SAREA.  Disabling DRI.\n");
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	pDRIInfo->devPrivate = xcalloc(pDRIInfo->devPrivateSize, 1);
 | 
						|
	if (pDRIInfo->devPrivate == NULL) {
 | 
						|
		DRIDestroyInfoRec(atis->pDRIInfo);
 | 
						|
		atis->pDRIInfo = NULL;
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	pDRIInfo->contextSize    = sizeof(ATIDRIContextRec);
 | 
						|
 | 
						|
	pDRIInfo->SwapContext    = ATIDRISwapContext;
 | 
						|
	/*pDRIInfo->InitBuffers    = R128DRIInitBuffers;*/ /* XXX Appears unnecessary */
 | 
						|
	/*pDRIInfo->MoveBuffers    = R128DRIMoveBuffers;*/ /* XXX Badness */
 | 
						|
	pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 | 
						|
	/*pDRIInfo->TransitionTo2d = R128DRITransitionTo2d;
 | 
						|
	pDRIInfo->TransitionTo3d = R128DRITransitionTo3d;
 | 
						|
	pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d;
 | 
						|
	pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d;*/
 | 
						|
 | 
						|
	pDRIInfo->createDummyCtx     = TRUE;
 | 
						|
	pDRIInfo->createDummyCtxPriv = FALSE;
 | 
						|
 | 
						|
	if (!DRIScreenInit(pScreen, pDRIInfo, &atic->drmFd)) {
 | 
						|
		ErrorF("[dri] DRIScreenInit failed.  Disabling DRI.\n");
 | 
						|
		xfree(pDRIInfo->devPrivate);
 | 
						|
		pDRIInfo->devPrivate = NULL;
 | 
						|
		DRIDestroyInfoRec(pDRIInfo);
 | 
						|
		pDRIInfo = NULL;
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Add a map for the MMIO registers that will be accessed by any
 | 
						|
	 * DRI-based clients.
 | 
						|
	 */
 | 
						|
	atis->registerSize = ATI_REG_SIZE(pScreenPriv->screen->card);
 | 
						|
	if (drmAddMap(atic->drmFd, ATI_REG_BASE(pScreenPriv->screen->card),
 | 
						|
	    atis->registerSize, DRM_REGISTERS, DRM_READ_ONLY,
 | 
						|
	    &atis->registerHandle) < 0) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[drm] register handle = 0x%08lx\n", atis->registerHandle);
 | 
						|
 | 
						|
	/* DRIScreenInit adds the frame buffer map, but we need it as well */
 | 
						|
	DRIGetDeviceInfo(pScreen, &atis->fbHandle, &scratch_int, &scratch_int,
 | 
						|
	    &scratch_int, &scratch_int, &scratch_ptr);
 | 
						|
 | 
						|
	/* Initialize AGP */
 | 
						|
	atis->using_agp = atic->is_agp;
 | 
						|
	if (atic->is_agp && !ATIDRIAgpInit(pScreen)) {
 | 
						|
		atis->using_agp = FALSE;
 | 
						|
		ErrorF("[agp] AGP failed to initialize; falling back to PCI mode.\n");
 | 
						|
		ErrorF("[agp] Make sure your kernel's AGP support is loaded and functioning.\n");
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize PCIGART */
 | 
						|
	if (!atis->using_agp && !ATIDRIPciInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef GLXEXT
 | 
						|
	if (!ATIInitVisualConfigs(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	ErrorF("[dri] Visual configs initialized\n");
 | 
						|
#endif
 | 
						|
 | 
						|
	atis->serverContext = DRIGetContext(pScreen);
 | 
						|
 | 
						|
	return ATIDRIFinishScreenInit(pScreen);
 | 
						|
}
 | 
						|
 | 
						|
/* Finish initializing the device-dependent DRI state, and call
 | 
						|
   DRIFinishScreenInit() to complete the device-independent DRI
 | 
						|
   initialization. */
 | 
						|
static Bool
 | 
						|
R128DRIFinishScreenInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	R128SAREAPrivPtr pSAREAPriv;
 | 
						|
	R128DRIPtr       pR128DRI;
 | 
						|
	int bpp = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	/* Initialize the kernel data structures */
 | 
						|
	if (!R128DRIKernelInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize the vertex buffers list */
 | 
						|
	if (!ATIDRIBufInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize IRQ */
 | 
						|
	ATIDRIIrqInit(pScreen);
 | 
						|
 | 
						|
	pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
 | 
						|
	memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
 | 
						|
 | 
						|
	pR128DRI                    = (R128DRIPtr)atis->pDRIInfo->devPrivate;
 | 
						|
 | 
						|
	pR128DRI->deviceID          = pScreenPriv->screen->card->attr.deviceID;
 | 
						|
	pR128DRI->width             = pScreenPriv->screen->width;
 | 
						|
	pR128DRI->height            = pScreenPriv->screen->height;
 | 
						|
	pR128DRI->depth             = pScreenPriv->screen->fb[0].depth;
 | 
						|
	pR128DRI->bpp               = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	pR128DRI->IsPCI             = !atis->using_agp;
 | 
						|
	pR128DRI->AGPMode           = atis->agpMode;
 | 
						|
 | 
						|
	pR128DRI->frontOffset       = atis->frontOffset;
 | 
						|
	pR128DRI->frontPitch        = atis->frontPitch / (bpp / 8);
 | 
						|
	pR128DRI->backOffset        = atis->backOffset;
 | 
						|
	pR128DRI->backPitch         = atis->backPitch / (bpp / 8);
 | 
						|
	pR128DRI->depthOffset       = atis->depthOffset;
 | 
						|
	pR128DRI->depthPitch        = atis->depthPitch / (bpp / 8);
 | 
						|
	pR128DRI->spanOffset        = atis->spanOffset;
 | 
						|
	pR128DRI->textureOffset     = atis->textureOffset;
 | 
						|
	pR128DRI->textureSize       = atis->textureSize;
 | 
						|
	pR128DRI->log2TexGran       = atis->log2TexGran;
 | 
						|
 | 
						|
	pR128DRI->registerHandle    = atis->registerHandle;
 | 
						|
	pR128DRI->registerSize      = atis->registerSize;
 | 
						|
 | 
						|
	pR128DRI->gartTexHandle     = atis->gartTexHandle;
 | 
						|
	pR128DRI->gartTexMapSize    = atis->gartTexMapSize;
 | 
						|
	pR128DRI->log2AGPTexGran    = atis->log2GARTTexGran;
 | 
						|
	pR128DRI->gartTexOffset     = atis->gartTexStart;
 | 
						|
	pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* Finish initializing the device-dependent DRI state, and call
 | 
						|
 * DRIFinishScreenInit() to complete the device-independent DRI
 | 
						|
 * initialization.
 | 
						|
 */
 | 
						|
static Bool
 | 
						|
RadeonDRIFinishScreenInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	RADEONSAREAPrivPtr  pSAREAPriv;
 | 
						|
	RADEONDRIPtr        pRADEONDRI;
 | 
						|
	drmRadeonMemInitHeap drmHeap;
 | 
						|
 | 
						|
	/* Initialize the kernel data structures */
 | 
						|
	if (!RadeonDRIKernelInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize the vertex buffers list */
 | 
						|
	if (!ATIDRIBufInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize IRQ */
 | 
						|
	ATIDRIIrqInit(pScreen);
 | 
						|
 | 
						|
	drmHeap.region = RADEON_MEM_REGION_GART;
 | 
						|
	drmHeap.start  = 0;
 | 
						|
	drmHeap.size   = atis->gartTexMapSize;
 | 
						|
 | 
						|
	if (drmCommandWrite(atic->drmFd, DRM_RADEON_INIT_HEAP, &drmHeap,
 | 
						|
	    sizeof(drmHeap))) {
 | 
						|
		ErrorF("[drm] Failed to initialize GART heap manager\n");
 | 
						|
	}
 | 
						|
 | 
						|
	/* Initialize the SAREA private data structure */
 | 
						|
	pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
 | 
						|
	memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
 | 
						|
 | 
						|
	pRADEONDRI = (RADEONDRIPtr)atis->pDRIInfo->devPrivate;
 | 
						|
 | 
						|
	pRADEONDRI->deviceID          = pScreenPriv->screen->card->attr.deviceID;
 | 
						|
	pRADEONDRI->width             = pScreenPriv->screen->width;
 | 
						|
	pRADEONDRI->height            = pScreenPriv->screen->height;
 | 
						|
	pRADEONDRI->depth             = pScreenPriv->screen->fb[0].depth;
 | 
						|
	pRADEONDRI->bpp               = pScreenPriv->screen->fb[0].bitsPerPixel;
 | 
						|
 | 
						|
	pRADEONDRI->IsPCI             = !atis->using_agp;
 | 
						|
	pRADEONDRI->AGPMode           = atis->agpMode;
 | 
						|
 | 
						|
	pRADEONDRI->frontOffset       = atis->frontOffset;
 | 
						|
	pRADEONDRI->frontPitch        = atis->frontPitch;
 | 
						|
	pRADEONDRI->backOffset        = atis->backOffset;
 | 
						|
	pRADEONDRI->backPitch         = atis->backPitch;
 | 
						|
	pRADEONDRI->depthOffset       = atis->depthOffset;
 | 
						|
	pRADEONDRI->depthPitch        = atis->depthPitch;
 | 
						|
	pRADEONDRI->textureOffset     = atis->textureOffset;
 | 
						|
	pRADEONDRI->textureSize       = atis->textureSize;
 | 
						|
	pRADEONDRI->log2TexGran       = atis->log2TexGran;
 | 
						|
 | 
						|
	pRADEONDRI->registerHandle    = atis->registerHandle;
 | 
						|
	pRADEONDRI->registerSize      = atis->registerSize;
 | 
						|
 | 
						|
	pRADEONDRI->statusHandle      = atis->ringReadPtrHandle;
 | 
						|
	pRADEONDRI->statusSize        = atis->ringReadMapSize;
 | 
						|
 | 
						|
	pRADEONDRI->gartTexHandle     = atis->gartTexHandle;
 | 
						|
	pRADEONDRI->gartTexMapSize    = atis->gartTexMapSize;
 | 
						|
	pRADEONDRI->log2GARTTexGran   = atis->log2GARTTexGran;
 | 
						|
	pRADEONDRI->gartTexOffset     = atis->gartTexStart;
 | 
						|
 | 
						|
	pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
ATIDRIFinishScreenInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv(pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo (pScreenPriv);
 | 
						|
 | 
						|
	atis->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
 | 
						|
 | 
						|
	/* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
 | 
						|
	 * because *DRIKernelInit requires that the hardware lock is held by
 | 
						|
	 * the X server, and the first time the hardware lock is grabbed is
 | 
						|
	 * in DRIFinishScreenInit.
 | 
						|
	 */
 | 
						|
	if (!DRIFinishScreenInit(pScreen)) {
 | 
						|
		ATIDRICloseScreen(pScreen);
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		if (!RadeonDRIFinishScreenInit(pScreen)) {
 | 
						|
			ATIDRICloseScreen(pScreen);
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (!R128DRIFinishScreenInit(pScreen)) {
 | 
						|
			ATIDRICloseScreen(pScreen);
 | 
						|
			return FALSE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* The screen is being closed, so clean up any state and free any
 | 
						|
   resources used by the DRI. */
 | 
						|
void
 | 
						|
ATIDRICloseScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
	KdScreenPriv (pScreen);
 | 
						|
	ATIScreenInfo (pScreenPriv);
 | 
						|
	ATICardInfo (pScreenPriv);
 | 
						|
	drmR128Init drmR128Info;
 | 
						|
	drmRadeonInit drmRadeonInfo;
 | 
						|
 | 
						|
	if (atis->indirectBuffer != NULL) {
 | 
						|
		/* Flush any remaining commands and free indirect buffers.
 | 
						|
		 * Two steps are used because ATIFlushIndirect gets a
 | 
						|
		 * new buffer after discarding.
 | 
						|
		 */
 | 
						|
		ATIFlushIndirect(atis, 1);
 | 
						|
		ATIDRIDispatchIndirect(atis, 1);
 | 
						|
		xfree(atis->indirectBuffer);
 | 
						|
		atis->indirectBuffer = NULL;
 | 
						|
		atis->indirectStart = 0;
 | 
						|
	}
 | 
						|
	ATIDRIDMAStop(atis);
 | 
						|
 | 
						|
	if (atis->irqEnabled) {
 | 
						|
		drmCtlUninstHandler(atic->drmFd);
 | 
						|
		atis->irqEnabled = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* De-allocate vertex buffers */
 | 
						|
	if (atis->buffers) {
 | 
						|
		drmUnmapBufs(atis->buffers);
 | 
						|
		atis->buffers = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* De-allocate all kernel resources */
 | 
						|
	if (!atic->is_radeon) {
 | 
						|
		memset(&drmR128Info, 0, sizeof(drmR128Init));
 | 
						|
		drmR128Info.func = DRM_R128_CLEANUP_CCE;
 | 
						|
		drmCommandWrite(atic->drmFd, DRM_R128_INIT, &drmR128Info,
 | 
						|
		    sizeof(drmR128Init));
 | 
						|
	} else {
 | 
						|
		memset(&drmRadeonInfo, 0, sizeof(drmRadeonInfo));
 | 
						|
		drmRadeonInfo.func = DRM_RADEON_CLEANUP_CP;
 | 
						|
		drmCommandWrite(atic->drmFd, DRM_RADEON_CP_INIT, &drmRadeonInfo,
 | 
						|
		    sizeof(drmR128Init));
 | 
						|
	}
 | 
						|
 | 
						|
	/* De-allocate all AGP resources */
 | 
						|
	if (atis->gartTex) {
 | 
						|
		drmUnmap(atis->gartTex, atis->gartTexMapSize);
 | 
						|
		atis->gartTex = NULL;
 | 
						|
	}
 | 
						|
	if (atis->buf) {
 | 
						|
		drmUnmap(atis->buf, atis->bufMapSize);
 | 
						|
		atis->buf = NULL;
 | 
						|
	}
 | 
						|
	if (atis->ringReadPtr) {
 | 
						|
		drmUnmap(atis->ringReadPtr, atis->ringReadMapSize);
 | 
						|
		atis->ringReadPtr = NULL;
 | 
						|
	}
 | 
						|
	if (atis->ring) {
 | 
						|
		drmUnmap(atis->ring, atis->ringMapSize);
 | 
						|
		atis->ring = NULL;
 | 
						|
	}
 | 
						|
	if (atis->agpMemHandle != DRM_AGP_NO_HANDLE) {
 | 
						|
		drmAgpUnbind(atic->drmFd, atis->agpMemHandle);
 | 
						|
		drmAgpFree(atic->drmFd, atis->agpMemHandle);
 | 
						|
		atis->agpMemHandle = DRM_AGP_NO_HANDLE;
 | 
						|
		drmAgpRelease(atic->drmFd);
 | 
						|
	}
 | 
						|
	if (atis->pciMemHandle) {
 | 
						|
		drmScatterGatherFree(atic->drmFd, atis->pciMemHandle);
 | 
						|
		atis->pciMemHandle = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* De-allocate all DRI resources */
 | 
						|
	DRICloseScreen(pScreen);
 | 
						|
 | 
						|
	/* De-allocate all DRI data structures */
 | 
						|
	if (atis->pDRIInfo) {
 | 
						|
		if (atis->pDRIInfo->devPrivate) {
 | 
						|
			xfree(atis->pDRIInfo->devPrivate);
 | 
						|
			atis->pDRIInfo->devPrivate = NULL;
 | 
						|
		}
 | 
						|
		DRIDestroyInfoRec(atis->pDRIInfo);
 | 
						|
		atis->pDRIInfo = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef GLXEXT
 | 
						|
	if (atis->pVisualConfigs) {
 | 
						|
		xfree(atis->pVisualConfigs);
 | 
						|
		atis->pVisualConfigs = NULL;
 | 
						|
	}
 | 
						|
	if (atis->pVisualConfigsPriv) {
 | 
						|
		xfree(atis->pVisualConfigsPriv);
 | 
						|
		atis->pVisualConfigsPriv = NULL;
 | 
						|
	}
 | 
						|
#endif /* GLXEXT */
 | 
						|
	atic->drmFd = -1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ATIDRIDMAStart(ATIScreenInfo *atis)
 | 
						|
{
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (atic->is_radeon)
 | 
						|
		ret = drmCommandNone(atic->drmFd, DRM_RADEON_CP_START);
 | 
						|
	else
 | 
						|
		ret = drmCommandNone(atic->drmFd, DRM_R128_CCE_START);
 | 
						|
 | 
						|
	if (ret == 0)
 | 
						|
		atis->dma_started = TRUE;
 | 
						|
	else
 | 
						|
		FatalError("%s: DMA start returned %d\n", __FUNCTION__, ret);
 | 
						|
}
 | 
						|
 | 
						|
/* Attempts to idle the DMA engine and stops it.  Note that the ioctl is the
 | 
						|
 * same for both R128 and Radeon, so we can just use the name of one of them.
 | 
						|
 */
 | 
						|
void
 | 
						|
ATIDRIDMAStop(ATIScreenInfo *atis)
 | 
						|
{
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	drmRadeonCPStop stop;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	stop.flush = 1;
 | 
						|
	stop.idle  = 1;
 | 
						|
	ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop, 
 | 
						|
	    sizeof(drmRadeonCPStop));
 | 
						|
 | 
						|
	if (ret != 0 && errno == EBUSY) {
 | 
						|
		ErrorF("Failed to idle the DMA engine\n");
 | 
						|
 | 
						|
		stop.idle = 0;
 | 
						|
		ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop,
 | 
						|
		    sizeof(drmRadeonCPStop));
 | 
						|
	}
 | 
						|
	atis->dma_started = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
ATIDRIDMAReset(ATIScreenInfo *atis)
 | 
						|
{
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	ret = drmCommandNone(atic->drmFd, atic->is_radeon ?
 | 
						|
	    DRM_RADEON_CP_RESET : DRM_R128_CCE_RESET);
 | 
						|
 | 
						|
	if (ret != 0)
 | 
						|
		FatalError("Failed to reset CCE/CP\n");
 | 
						|
 | 
						|
	atis->dma_started = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/* The R128 and Radeon Indirect ioctls differ only in the ioctl number */
 | 
						|
void
 | 
						|
ATIDRIDispatchIndirect(ATIScreenInfo *atis, Bool discard)
 | 
						|
{
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	drmBufPtr buffer = atis->indirectBuffer->drmBuf;
 | 
						|
	drmR128Indirect indirect;
 | 
						|
	int cmd;
 | 
						|
 | 
						|
	indirect.idx = buffer->idx;
 | 
						|
	indirect.start = atis->indirectStart;
 | 
						|
	indirect.end = buffer->used;
 | 
						|
	indirect.discard = discard;
 | 
						|
	cmd = atic->is_radeon ? DRM_RADEON_INDIRECT : DRM_R128_INDIRECT;
 | 
						|
	drmCommandWriteRead(atic->drmFd, cmd, &indirect,
 | 
						|
	    sizeof(drmR128Indirect));
 | 
						|
}
 | 
						|
 | 
						|
/* Get an indirect buffer for the DMA 2D acceleration commands  */
 | 
						|
drmBufPtr
 | 
						|
ATIDRIGetBuffer(ATIScreenInfo *atis)
 | 
						|
{
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	drmDMAReq dma;
 | 
						|
	drmBufPtr buf = NULL;
 | 
						|
	int indx = 0, size = 0, ret = 0;
 | 
						|
	TIMEOUT_LOCALS;
 | 
						|
 | 
						|
	dma.context = atis->serverContext;
 | 
						|
	dma.send_count = 0;
 | 
						|
	dma.send_list = NULL;
 | 
						|
	dma.send_sizes = NULL;
 | 
						|
	dma.flags = 0;
 | 
						|
	dma.request_count = 1;
 | 
						|
	if (atic->is_radeon)
 | 
						|
		dma.request_size = RADEON_BUFFER_SIZE;
 | 
						|
	else
 | 
						|
		dma.request_size = R128_BUFFER_SIZE;
 | 
						|
	dma.request_list = &indx;
 | 
						|
	dma.request_sizes = &size;
 | 
						|
	dma.granted_count = 0;
 | 
						|
 | 
						|
	WHILE_NOT_TIMEOUT(.2) {
 | 
						|
		ret = drmDMA(atic->drmFd, &dma);
 | 
						|
		if (ret != -EBUSY)
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	if (TIMEDOUT())
 | 
						|
		FatalError("Timeout fetching DMA buffer (card hung)\n");
 | 
						|
	if (ret != 0)
 | 
						|
		FatalError("Error fetching DMA buffer: %d\n", ret);
 | 
						|
 | 
						|
	buf = &atis->buffers->list[indx];
 | 
						|
	buf->used = 0;
 | 
						|
	return buf;
 | 
						|
}
 |