#include "r128.h"
#include "r128_dri.h"
#include "r128_reg.h"
#include "r128_sarea.h"
#include "r128_version.h"
#include "xf86.h"
#include "windowstr.h"
#include "xf86PciInfo.h"
#include "shadowfb.h"
#define _XF86DRI_SERVER_
#include "GL/glxtokens.h"
#include "sarea.h"
#if defined(__alpha__)
# define DRM_PAGE_SIZE 8192
#elif defined(__ia64__)
# define DRM_PAGE_SIZE getpagesize()
#else
# define DRM_PAGE_SIZE 4096
#endif
static void R128DRITransitionTo2d(ScreenPtr pScreen);
static void R128DRITransitionTo3d(ScreenPtr pScreen);
static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen);
static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen);
static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
static Bool R128InitVisualConfigs(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
int numConfigs = 0;
__GLXvisualConfig *pConfigs = 0;
R128ConfigPrivPtr pR128Configs = 0;
R128ConfigPrivPtr *pR128ConfigPtrs = 0;
int i, accum, stencil, db;
switch (info->CurrentLayout.pixel_code) {
case 8:
case 15:
case 24:
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed (depth %d not supported). "
"Disabling DRI.\n", info->CurrentLayout.pixel_code);
return FALSE;
#define R128_USE_ACCUM 1
#define R128_USE_STENCIL 1
#define R128_USE_DB 1
case 16:
numConfigs = 1;
if (R128_USE_ACCUM) numConfigs *= 2;
if (R128_USE_STENCIL) numConfigs *= 2;
if (R128_USE_DB) numConfigs *= 2;
if (!(pConfigs
= (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
numConfigs))) {
return FALSE;
}
if (!(pR128Configs
= (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
numConfigs))) {
xfree(pConfigs);
return FALSE;
}
if (!(pR128ConfigPtrs
= (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
numConfigs))) {
xfree(pConfigs);
xfree(pR128Configs);
return FALSE;
}
i = 0;
for (db = 0; db <= R128_USE_DB; db++) {
for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
pR128ConfigPtrs[i] = &pR128Configs[i];
pConfigs[i].vid = (VisualID)(-1);
pConfigs[i].class = -1;
pConfigs[i].rgba = TRUE;
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;
if (accum) {
pConfigs[i].accumRedSize = 16;
pConfigs[i].accumGreenSize = 16;
pConfigs[i].accumBlueSize = 16;
pConfigs[i].accumAlphaSize = 0;
} 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;
pConfigs[i].bufferSize = 16;
pConfigs[i].depthSize = 16;
if (stencil)
pConfigs[i].stencilSize = 8;
else
pConfigs[i].stencilSize = 0;
pConfigs[i].auxBuffers = 0;
pConfigs[i].level = 0;
if (accum || stencil) {
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++;
}
}
}
break;
case 32:
numConfigs = 1;
if (R128_USE_ACCUM) numConfigs *= 2;
if (R128_USE_STENCIL) numConfigs *= 2;
if (R128_USE_DB) numConfigs *= 2;
if (!(pConfigs
= (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
numConfigs))) {
return FALSE;
}
if (!(pR128Configs
= (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
numConfigs))) {
xfree(pConfigs);
return FALSE;
}
if (!(pR128ConfigPtrs
= (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
numConfigs))) {
xfree(pConfigs);
xfree(pR128Configs);
return FALSE;
}
i = 0;
for (db = 0; db <= R128_USE_DB; db++) {
for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
pR128ConfigPtrs[i] = &pR128Configs[i];
pConfigs[i].vid = (VisualID)(-1);
pConfigs[i].class = -1;
pConfigs[i].rgba = TRUE;
pConfigs[i].redSize = 8;
pConfigs[i].greenSize = 8;
pConfigs[i].blueSize = 8;
pConfigs[i].alphaSize = 0;
pConfigs[i].redMask = 0x00FF0000;
pConfigs[i].greenMask = 0x0000FF00;
pConfigs[i].blueMask = 0x000000FF;
pConfigs[i].alphaMask = 0x00000000;
if (accum) {
pConfigs[i].accumRedSize = 16;
pConfigs[i].accumGreenSize = 16;
pConfigs[i].accumBlueSize = 16;
pConfigs[i].accumAlphaSize = 0;
} 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;
pConfigs[i].bufferSize = 24;
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 || stencil) {
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++;
}
}
}
break;
}
info->numVisualConfigs = numConfigs;
info->pVisualConfigs = pConfigs;
info->pVisualConfigsPriv = pR128Configs;
GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs);
return TRUE;
}
static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual,
drmContext hwContext, void *pVisualConfigPriv,
DRIContextType contextStore)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
info->drmCtx = hwContext;
return TRUE;
}
static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext,
DRIContextType contextStore)
{
}
static void R128EnterServer(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
if (info->accel) info->accel->NeedToSync = TRUE;
}
static void R128LeaveServer(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
unsigned char *R128MMIO = info->MMIO;
if (!info->directRenderingEnabled) {
info->sc_left = INREG(R128_SC_LEFT);
info->sc_right = INREG(R128_SC_RIGHT);
info->sc_top = INREG(R128_SC_TOP);
info->sc_bottom = INREG(R128_SC_BOTTOM);
info->aux_sc_cntl = INREG(R128_SC_BOTTOM);
} else if (info->CCEInUse) {
R128CCEReleaseIndirect(pScrn);
info->CCEInUse = FALSE;
}
}
static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
DRIContextType oldContextType, void *oldContext,
DRIContextType newContextType, void *newContext)
{
if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
(newContextType==DRI_2D_CONTEXT)) {
R128EnterServer(pScreen);
}
if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
(newContextType==DRI_2D_CONTEXT)) {
R128LeaveServer(pScreen);
}
}
static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
BoxPtr pbox, pboxSave;
int nbox, nboxSave;
int depth;
if (info->directRenderingEnabled)
return;
switch (pScrn->bitsPerPixel) {
case 8: depth = 0x000000ff; break;
case 16: depth = 0x0000ffff; break;
case 24: depth = 0x00ffffff; break;
case 32: depth = 0xffffffff; break;
default: depth = 0x00000000; break;
}
pboxSave = pbox = REGION_RECTS(prgn);
nboxSave = nbox = REGION_NUM_RECTS(prgn);
(*info->accel->SetupForSolidFill)(pScrn, 0, GXcopy, (CARD32)(-1));
for (; nbox; nbox--, pbox++) {
(*info->accel->SubsequentSolidFillRect)(pScrn,
pbox->x1 + info->fbX,
pbox->y1 + info->fbY,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
(*info->accel->SubsequentSolidFillRect)(pScrn,
pbox->x1 + info->backX,
pbox->y1 + info->backY,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
}
pbox = pboxSave;
nbox = nboxSave;
(*info->accel->SetupForSolidFill)(pScrn, depth, GXcopy, (CARD32)(-1));
for (; nbox; nbox--, pbox++)
(*info->accel->SubsequentSolidFillRect)(pScrn,
pbox->x1 + info->depthX,
pbox->y1 + info->depthY,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
info->accel->NeedToSync = TRUE;
}
static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr prgnSrc, CARD32 indx)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
if (info->directRenderingEnabled)
return;
}
static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen)
{
unsigned char *R128MMIO = info->MMIO;
unsigned long mode;
unsigned int vendor, device;
int ret;
unsigned long cntl, chunk;
int s, l;
int flags;
unsigned long agpBase;
if (drmAgpAcquire(info->drmFD) < 0) {
xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
return FALSE;
}
mode = drmAgpGetMode(info->drmFD);
vendor = drmAgpVendorId(info->drmFD);
device = drmAgpDeviceId(info->drmFD);
mode &= ~R128_AGP_MODE_MASK;
switch (info->agpMode) {
case 4: mode |= R128_AGP_4X_MODE;
case 2: mode |= R128_AGP_2X_MODE;
case 1: default: mode |= R128_AGP_1X_MODE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
mode, vendor, device,
info->PciInfo->vendor,
info->PciInfo->chipType);
if (drmAgpEnable(info->drmFD, mode) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
drmAgpRelease(info->drmFD);
return FALSE;
}
info->agpOffset = 0;
if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL,
&info->agpMemHandle)) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
drmAgpRelease(info->drmFD);
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] %d kB allocated with handle 0x%08lx\n",
info->agpSize*1024, info->agpMemHandle);
if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
drmAgpFree(info->drmFD, info->agpMemHandle);
drmAgpRelease(info->drmFD);
return FALSE;
}
info->ringStart = info->agpOffset;
info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
info->ringReadMapSize = DRM_PAGE_SIZE;
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
info->bufMapSize = info->bufSize*1024*1024;
info->agpTexStart = info->bufStart + info->bufMapSize;
s = (info->agpSize*1024*1024 - info->agpTexStart);
l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
info->agpTexMapSize = (s >> l) << l;
info->log2AGPTexGran = l;
if (info->CCESecure) flags = DRM_READ_ONLY;
else flags = 0;
if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
DRM_AGP, flags, &info->ringHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add ring mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] ring handle = 0x%08lx\n", info->ringHandle);
if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
(drmAddressPtr)&info->ring) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Ring mapped at 0x%08lx\n",
(unsigned long)info->ring);
if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add ring read ptr mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] ring read ptr handle = 0x%08lx\n",
info->ringReadPtrHandle);
if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
(drmAddressPtr)&info->ringReadPtr) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map ring read ptr\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Ring read ptr mapped at 0x%08lx\n",
(unsigned long)info->ringReadPtr);
if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
DRM_AGP, 0, &info->bufHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add vertex/indirect buffers mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] vertex/indirect buffers handle = 0x%08lx\n",
info->bufHandle);
if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
(drmAddressPtr)&info->buf) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map vertex/indirect buffers\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
(unsigned long)info->buf);
if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize,
DRM_AGP, 0, &info->agpTexHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not add AGP texture map mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] AGP texture map handle = 0x%08lx\n",
info->agpTexHandle);
if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize,
(drmAddressPtr)&info->agpTex) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Could not map AGP texture map\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[agp] AGP Texture map mapped at 0x%08lx\n",
(unsigned long)info->agpTex);
cntl = INREG(R128_AGP_CNTL);
cntl &= ~R128_AGP_APER_SIZE_MASK;
switch (info->agpSize) {
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:
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[agp] Illegal aperture size %d kB\n",
info->agpSize*1024);
return FALSE;
}
agpBase = drmAgpBase(info->drmFD);
OUTREG(R128_AGP_BASE, agpBase);
OUTREG(R128_AGP_CNTL, cntl);
chunk = INREG(R128_BM_CHUNK_0_VAL);
chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
R128_BM_PM4_RD_FORCE_TO_PCI |
R128_BM_GLOBAL_FORCE_TO_PCI);
OUTREG(R128_BM_CHUNK_0_VAL, chunk);
OUTREG(R128_PCI_GART_PAGE, 1);
return TRUE;
}
static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen)
{
unsigned char *R128MMIO = info->MMIO;
CARD32 chunk;
int ret;
int flags;
info->agpOffset = 0;
ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024,
&info->pciMemHandle);
if (ret < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] %d kB allocated with handle 0x%08lx\n",
info->agpSize*1024, info->pciMemHandle);
info->ringStart = info->agpOffset;
info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
info->ringReadMapSize = DRM_PAGE_SIZE;
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
info->bufMapSize = info->bufSize*1024*1024;
flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add ring mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] ring handle = 0x%08lx\n", info->ringHandle);
if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
(drmAddressPtr)&info->ring) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring mapped at 0x%08lx\n",
(unsigned long)info->ring);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring contents 0x%08lx\n",
*(unsigned long *)(pointer)info->ring);
if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add ring read ptr mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] ring read ptr handle = 0x%08lx\n",
info->ringReadPtrHandle);
if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
(drmAddressPtr)&info->ringReadPtr) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not map ring read ptr\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring read ptr mapped at 0x%08lx\n",
(unsigned long)info->ringReadPtr);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Ring read ptr contents 0x%08lx\n",
*(unsigned long *)(pointer)info->ringReadPtr);
if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not add vertex/indirect buffers mapping\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] vertex/indirect buffers handle = 0x%08lx\n",
info->bufHandle);
if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
(drmAddressPtr)&info->buf) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[pci] Could not map vertex/indirect buffers\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
(unsigned long)info->buf);
xf86DrvMsg(pScreen->myNum, X_INFO,
"[pci] Vertex/indirect buffers contents 0x%08lx\n",
*(unsigned long *)(pointer)info->buf);
switch (info->Chipset) {
case PCI_CHIP_RAGE128LE:
case PCI_CHIP_RAGE128RE:
case PCI_CHIP_RAGE128RK:
case PCI_CHIP_RAGE128PD:
case PCI_CHIP_RAGE128PP:
case PCI_CHIP_RAGE128PR:
break;
case PCI_CHIP_RAGE128LF:
case PCI_CHIP_RAGE128MF:
case PCI_CHIP_RAGE128ML:
case PCI_CHIP_RAGE128RF:
case PCI_CHIP_RAGE128RG:
case PCI_CHIP_RAGE128RL:
case PCI_CHIP_RAGE128SM:
case PCI_CHIP_RAGE128PF:
case PCI_CHIP_RAGE128TF:
case PCI_CHIP_RAGE128TL:
case PCI_CHIP_RAGE128TR:
case PCI_CHIP_RAGE128PA:
case PCI_CHIP_RAGE128PB:
case PCI_CHIP_RAGE128PC:
case PCI_CHIP_RAGE128PE:
case PCI_CHIP_RAGE128PG:
case PCI_CHIP_RAGE128PH:
case PCI_CHIP_RAGE128PI:
case PCI_CHIP_RAGE128PJ:
case PCI_CHIP_RAGE128PK:
case PCI_CHIP_RAGE128PL:
case PCI_CHIP_RAGE128PM:
case PCI_CHIP_RAGE128PN:
case PCI_CHIP_RAGE128PO:
case PCI_CHIP_RAGE128PQ:
case PCI_CHIP_RAGE128PS:
case PCI_CHIP_RAGE128PT:
case PCI_CHIP_RAGE128PU:
case PCI_CHIP_RAGE128PV:
case PCI_CHIP_RAGE128PW:
case PCI_CHIP_RAGE128PX:
case PCI_CHIP_RAGE128SE:
case PCI_CHIP_RAGE128SF:
case PCI_CHIP_RAGE128SG:
case PCI_CHIP_RAGE128SH:
case PCI_CHIP_RAGE128SK:
case PCI_CHIP_RAGE128SL:
case PCI_CHIP_RAGE128SN:
case PCI_CHIP_RAGE128TS:
case PCI_CHIP_RAGE128TT:
case PCI_CHIP_RAGE128TU:
default:
chunk = INREG(R128_BM_CHUNK_0_VAL);
chunk |= (R128_BM_PTR_FORCE_TO_PCI |
R128_BM_PM4_RD_FORCE_TO_PCI |
R128_BM_GLOBAL_FORCE_TO_PCI);
OUTREG(R128_BM_CHUNK_0_VAL, chunk);
OUTREG(R128_PCI_GART_PAGE, 0);
break;
}
return TRUE;
}
static Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen)
{
int flags;
if (info->CCESecure) flags = DRM_READ_ONLY;
else flags = 0;
info->registerSize = R128_MMIOSIZE;
if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
DRM_REGISTERS, flags, &info->registerHandle) < 0) {
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] register handle = 0x%08lx\n", info->registerHandle);
return TRUE;
}
static int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen)
{
drmR128Init drmInfo;
memset( &drmInfo, 0, sizeof(drmR128Init) );
drmInfo.func = DRM_R128_INIT_CCE;
drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
drmInfo.is_pci = info->IsPCI;
drmInfo.cce_mode = info->CCEMode;
drmInfo.cce_secure = info->CCESecure;
drmInfo.ring_size = info->ringSize*1024*1024;
drmInfo.usec_timeout = info->CCEusecTimeout;
drmInfo.fb_bpp = info->CurrentLayout.pixel_code;
drmInfo.depth_bpp = info->CurrentLayout.pixel_code;
drmInfo.front_offset = info->frontOffset;
drmInfo.front_pitch = info->frontPitch;
drmInfo.back_offset = info->backOffset;
drmInfo.back_pitch = info->backPitch;
drmInfo.depth_offset = info->depthOffset;
drmInfo.depth_pitch = info->depthPitch;
drmInfo.span_offset = info->spanOffset;
drmInfo.fb_offset = info->fbHandle;
drmInfo.mmio_offset = info->registerHandle;
drmInfo.ring_offset = info->ringHandle;
drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
drmInfo.buffers_offset = info->bufHandle;
drmInfo.agp_textures_offset = info->agpTexHandle;
if (drmCommandWrite(info->drmFD, DRM_R128_INIT,
&drmInfo, sizeof(drmR128Init)) < 0)
return FALSE;
return TRUE;
}
static Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen)
{
if (info->IsPCI) {
info->bufNumBufs = drmAddBufs(info->drmFD,
info->bufMapSize / R128_BUFFER_SIZE,
R128_BUFFER_SIZE,
DRM_SG_BUFFER,
info->bufStart);
} else {
info->bufNumBufs = drmAddBufs(info->drmFD,
info->bufMapSize / R128_BUFFER_SIZE,
R128_BUFFER_SIZE,
DRM_AGP_BUFFER,
info->bufStart);
}
if (info->bufNumBufs <= 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] Could not create vertex/indirect buffers list\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Added %d %d byte vertex/indirect buffers\n",
info->bufNumBufs, R128_BUFFER_SIZE);
if (!(info->buffers = drmMapBufs(info->drmFD))) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[drm] Failed to map vertex/indirect buffers list\n");
return FALSE;
}
xf86DrvMsg(pScreen->myNum, X_INFO,
"[drm] Mapped %d vertex/indirect buffers\n",
info->buffers->count);
return TRUE;
}
static void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
if (!info->irq) {
info->irq = drmGetInterruptFromBusID(
info->drmFD,
((pciConfigPtr)info->PciInfo->thisCard)->busnum,
((pciConfigPtr)info->PciInfo->thisCard)->devnum,
((pciConfigPtr)info->PciInfo->thisCard)->funcnum);
if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] failure adding irq handler, "
"there is a device already using that irq\n"
"[drm] falling back to irq-free operation\n");
info->irq = 0;
} else {
unsigned char *R128MMIO = info->MMIO;
info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
}
}
if (info->irq)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"[drm] dma control initialized, using IRQ %d\n",
info->irq);
}
static void R128DRICCEInit(ScrnInfoPtr pScrn)
{
R128InfoPtr info = R128PTR(pScrn);
info->BusCntl &= ~R128_BUS_MASTER_DIS;
switch (info->CCEMode) {
case R128_PM4_NONPM4: info->CCEFifoSize = 0; break;
case R128_PM4_192PIO: info->CCEFifoSize = 192; break;
case R128_PM4_192BM: info->CCEFifoSize = 192; break;
case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break;
case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break;
case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break;
case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break;
case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break;
}
if (info->directRenderingEnabled) {
R128CCE_START(pScrn, info);
} else {
R128CCE_STOP(pScrn, info);
}
}
Bool R128DRIScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
DRIInfoPtr pDRIInfo;
R128DRIPtr pR128DRI;
int major, minor, patch;
drmVersionPtr version;
if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed (libdri.a too old)\n");
return FALSE;
}
DRIQueryVersion(&major, &minor, &patch);
if (major != 4 || minor < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
"[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n"
"[dri] Disabling the DRI.\n",
major, minor, patch);
return FALSE;
}
switch (info->CurrentLayout.pixel_code) {
case 8:
case 15:
case 24:
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed (depth %d not supported). "
"[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code);
return FALSE;
case 16:
case 32:
break;
}
if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
info->pDRIInfo = pDRIInfo;
pDRIInfo->drmDriverName = R128_DRIVER_NAME;
pDRIInfo->clientDriverName = R128_DRIVER_NAME;
pDRIInfo->busIdString = xalloc(64);
sprintf(pDRIInfo->busIdString,
"PCI:%d:%d:%d",
info->PciInfo->bus,
info->PciInfo->device,
info->PciInfo->func);
pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR;
pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR;
pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH;
pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr;
pDRIInfo->frameBufferSize = info->FbMapSize;
pDRIInfo->frameBufferStride = (pScrn->displayWidth *
info->CurrentLayout.pixel_bytes);
pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES;
pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES
< R128_MAX_DRAWABLES
? SAREA_MAX_DRAWABLES
: R128_MAX_DRAWABLES);
#ifdef NOT_DONE
pDRIInfo->SAREASize =
((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000);
#else
if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] Data does not fit in SAREA. Disabling DRI.\n");
return FALSE;
}
pDRIInfo->SAREASize = SAREA_MAX;
#endif
if (!(pR128DRI = (R128DRIPtr)xcalloc(sizeof(R128DRIRec),1))) {
DRIDestroyInfoRec(info->pDRIInfo);
info->pDRIInfo = NULL;
return FALSE;
}
pDRIInfo->devPrivate = pR128DRI;
pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
pDRIInfo->contextSize = sizeof(R128DRIContextRec);
pDRIInfo->CreateContext = R128CreateContext;
pDRIInfo->DestroyContext = R128DestroyContext;
pDRIInfo->SwapContext = R128DRISwapContext;
pDRIInfo->InitBuffers = R128DRIInitBuffers;
pDRIInfo->MoveBuffers = R128DRIMoveBuffers;
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, &info->drmFD)) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] DRIScreenInit failed. Disabling DRI.\n");
xfree(pDRIInfo->devPrivate);
pDRIInfo->devPrivate = NULL;
DRIDestroyInfoRec(pDRIInfo);
pDRIInfo = NULL;
return FALSE;
}
if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
version = drmGetLibVersion(info->drmFD);
}
else {
version = drmGetVersion(info->drmFD);
version->version_major = 1;
version->version_minor = 0;
version->version_patchlevel = 0;
}
if (version) {
if (version->version_major != 1 ||
version->version_minor < 1) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
"[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
"[dri] Disabling DRI.\n",
version->version_major,
version->version_minor,
version->version_patchlevel);
drmFreeVersion(version);
R128DRICloseScreen(pScreen);
return FALSE;
}
drmFreeVersion(version);
}
version = drmGetVersion(info->drmFD);
if (version) {
if (version->version_major != 2 ||
version->version_minor < 2) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
"[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
"[dri] Disabling the DRI.\n",
version->version_major,
version->version_minor,
version->version_patchlevel);
drmFreeVersion(version);
R128DRICloseScreen(pScreen);
return FALSE;
}
info->drmMinor = version->version_minor;
drmFreeVersion(version);
}
if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) {
info->IsPCI = TRUE;
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[agp] AGP failed to initialize -- falling back to PCI mode.\n");
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[agp] Make sure you have the agpgart kernel module loaded.\n");
}
if (info->IsPCI && !R128DRIPciInit(info, pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
if (!R128DRIMapInit(info, pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
{
void *scratch_ptr;
int scratch_int;
DRIGetDeviceInfo(pScreen, &info->fbHandle,
&scratch_int, &scratch_int,
&scratch_int, &scratch_int,
&scratch_ptr);
}
if (!R128InitVisualConfigs(pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
return TRUE;
}
Bool R128DRIFinishScreenInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
R128SAREAPrivPtr pSAREAPriv;
R128DRIPtr pR128DRI;
info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
if (!DRIFinishScreenInit(pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
if (!R128DRIKernelInit(info, pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
if (!R128DRIBufInit(info, pScreen)) {
R128DRICloseScreen(pScreen);
return FALSE;
}
R128DRIIrqInit(info, pScreen);
R128DRICCEInit(pScrn);
pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
pR128DRI = (R128DRIPtr)info->pDRIInfo->devPrivate;
pR128DRI->deviceID = info->Chipset;
pR128DRI->width = pScrn->virtualX;
pR128DRI->height = pScrn->virtualY;
pR128DRI->depth = pScrn->depth;
pR128DRI->bpp = pScrn->bitsPerPixel;
pR128DRI->IsPCI = info->IsPCI;
pR128DRI->AGPMode = info->agpMode;
pR128DRI->frontOffset = info->frontOffset;
pR128DRI->frontPitch = info->frontPitch;
pR128DRI->backOffset = info->backOffset;
pR128DRI->backPitch = info->backPitch;
pR128DRI->depthOffset = info->depthOffset;
pR128DRI->depthPitch = info->depthPitch;
pR128DRI->spanOffset = info->spanOffset;
pR128DRI->textureOffset = info->textureOffset;
pR128DRI->textureSize = info->textureSize;
pR128DRI->log2TexGran = info->log2TexGran;
pR128DRI->registerHandle = info->registerHandle;
pR128DRI->registerSize = info->registerSize;
pR128DRI->agpTexHandle = info->agpTexHandle;
pR128DRI->agpTexMapSize = info->agpTexMapSize;
pR128DRI->log2AGPTexGran = info->log2AGPTexGran;
pR128DRI->agpTexOffset = info->agpTexStart;
pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
if (info->allowPageFlip && info->drmMinor >= 5 ) {
ShadowFBInit( pScreen, R128DRIRefreshArea );
} else if (info->allowPageFlip) {
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n");
info->allowPageFlip = 0;
}
return TRUE;
}
void R128DRICloseScreen(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
drmR128Init drmInfo;
if (info->directRenderingEnabled) {
R128CCE_STOP(pScrn, info);
}
if (info->irq) {
drmCtlUninstHandler(info->drmFD);
info->irq = 0;
}
if (info->buffers) {
drmUnmapBufs(info->buffers);
info->buffers = NULL;
}
memset(&drmInfo, 0, sizeof(drmR128Init));
drmInfo.func = DRM_R128_CLEANUP_CCE;
drmCommandWrite(info->drmFD, DRM_R128_INIT,
&drmInfo, sizeof(drmR128Init));
if (info->agpTex) {
drmUnmap(info->agpTex, info->agpTexMapSize);
info->agpTex = NULL;
}
if (info->buf) {
drmUnmap(info->buf, info->bufMapSize);
info->buf = NULL;
}
if (info->ringReadPtr) {
drmUnmap(info->ringReadPtr, info->ringReadMapSize);
info->ringReadPtr = NULL;
}
if (info->ring) {
drmUnmap(info->ring, info->ringMapSize);
info->ring = NULL;
}
if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
drmAgpUnbind(info->drmFD, info->agpMemHandle);
drmAgpFree(info->drmFD, info->agpMemHandle);
info->agpMemHandle = DRM_AGP_NO_HANDLE;
drmAgpRelease(info->drmFD);
}
if (info->pciMemHandle) {
drmScatterGatherFree(info->drmFD, info->pciMemHandle);
info->pciMemHandle = 0;
}
DRICloseScreen(pScreen);
if (info->pDRIInfo) {
if (info->pDRIInfo->devPrivate) {
xfree(info->pDRIInfo->devPrivate);
info->pDRIInfo->devPrivate = NULL;
}
DRIDestroyInfoRec(info->pDRIInfo);
info->pDRIInfo = NULL;
}
if (info->pVisualConfigs) {
xfree(info->pVisualConfigs);
info->pVisualConfigs = NULL;
}
if (info->pVisualConfigsPriv) {
xfree(info->pVisualConfigsPriv);
info->pVisualConfigsPriv = NULL;
}
}
static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
R128InfoPtr info = R128PTR(pScrn);
int i;
R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
return;
(*info->accel->SetupForScreenToScreenCopy)(pScrn,
1, 1, GXcopy,
(CARD32)(-1), -1);
for (i = 0 ; i < num ; i++, pbox++) {
int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1);
int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1);
if (xa <= xb && ya <= yb) {
(*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya,
xa + info->backX,
ya + info->backY,
xb - xa + 1,
yb - ya + 1);
}
}
}
static void R128EnablePageFlip(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
if (info->allowPageFlip) {
(*info->accel->SetupForScreenToScreenCopy)(pScrn,
1, 1, GXcopy,
(CARD32)(-1), -1);
(*info->accel->SubsequentScreenToScreenCopy)(pScrn,
0,
0,
info->backX,
info->backY,
pScrn->virtualX,
pScrn->virtualY);
pSAREAPriv->pfAllowPageFlip = 1;
}
}
static void R128DisablePageFlip(ScreenPtr pScreen)
{
R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
pSAREAPriv->pfAllowPageFlip = 0;
}
static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen)
{
R128DisablePageFlip(pScreen);
}
static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen)
{
R128EnablePageFlip(pScreen);
}
static void R128DRITransitionTo3d(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
R128EnablePageFlip(pScreen);
info->have3DWindows = 1;
if (info->cursor_start)
xf86ForceHWCursor(pScreen, TRUE);
}
static void R128DRITransitionTo2d(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
R128InfoPtr info = R128PTR(pScrn);
R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
if (pSAREAPriv->pfCurrentPage == 0) {
R128DisablePageFlip(pScreen);
} else {
xf86DrvMsg(pScreen->myNum, X_WARNING,
"[dri] R128DRITransitionTo2d: "
"kernel failed to unflip buffers.\n");
}
info->have3DWindows = 0;
if (info->cursor_start)
xf86ForceHWCursor(pScreen, FALSE);
}