/*
 * ATIDGABlitTransRect --
 *
 * This function calls XAA screen-to-screen copy primitives to transparently
 * copy a rectangle.
 */
static void
ATIDGABlitTransRect
(
    ScrnInfoPtr   pScreenInfo,
    int           xSrc,
    int           ySrc,
    int           w,
    int           h,
    int           xDst,
    int           yDst,
    unsigned long colour
)
{
    ATIPtr        pATI     = ATIPTR(pScreenInfo);
/*FIXME : use EXA if available */
#ifdef USE_XAA
    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
    int           xdir     = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1;
    int           ydir     = (ySrc < yDst) ? -1 : 1;

    pATI->XAAForceTransBlit = TRUE;

    (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo,
        xdir, ydir, GXcopy, (CARD32)(~0), (int)colour);

    pATI->XAAForceTransBlit = FALSE;

    (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
        xSrc, ySrc, xDst, yDst, w, h);

    if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
        SET_SYNC_FLAG(pXAAInfo);
#endif
}
/*
 * ATIMach64SubsequentSolidFillRect --
 *
 * This function performs a solid rectangle fill.
 */
static void
ATIMach64SubsequentSolidFillRect
(
    ScrnInfoPtr pScreenInfo,
    int         x,
    int         y,
    int         w,
    int         h
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    if (pATI->XModifier != 1)
    {
        x *= pATI->XModifier;
        w *= pATI->XModifier;

        outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
            (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
    }

    /* Disable clipping if it gets in the way */
    ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);

    ATIMach64WaitForFIFO(pATI, 2);
    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
    outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
}
示例#3
0
/*
 * ATIXVInitializeAdaptor --
 *
 * This is called by the server's XVideo support layer to initialise an XVideo
 * adapter.
 */
static int
ATIXVInitializeAdaptor
(
    ScrnInfoPtr         pScreenInfo,
    XF86VideoAdaptorPtr **pppAdaptor
)
{
    ScreenPtr           pScreen    = screenInfo.screens[pScreenInfo->scrnIndex];
    ATIPtr              pATI       = ATIPTR(pScreenInfo);
    XF86VideoAdaptorPtr *ppAdaptor = NULL;
    int                 nAdaptor;

    switch (pATI->Adapter)
    {
        case ATI_ADAPTER_MACH64:
            nAdaptor = ATIMach64XVInitialiseAdaptor(pScreen, pScreenInfo, pATI,
                &ppAdaptor);
            break;

        default:
            nAdaptor = 0;
            break;
    }

    if (pppAdaptor)
        *pppAdaptor = ppAdaptor;
    else
        ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor);

    return nAdaptor;
}
/*
 * ATIMach64SetupForSolidLine --
 *
 * This function sets up the draw engine for a series of solid lines.  It is
 * not used for 24bpp because the engine doesn't support it.
 */
static void
ATIMach64SetupForSolidLine
(
    ScrnInfoPtr  pScreenInfo,
    int          colour,
    int          rop,
    unsigned int planemask
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 5);
    outf(DP_WRITE_MASK, planemask);
    outf(DP_SRC, DP_MONO_SRC_ALLONES |
        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
    outf(DP_FRGD_CLR, colour);
    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));

    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);

    ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right,
        pATI->NewHW.sc_top, pATI->NewHW.sc_bottom);
}
/*
 * ATIMach64SetupForSolidFill --
 *
 * This function sets up the draw engine for a series of solid fills.
 */
static void
ATIMach64SetupForSolidFill
(
    ScrnInfoPtr  pScreenInfo,
    int          colour,
    int          rop,
    unsigned int planemask
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 5);
    outf(DP_WRITE_MASK, planemask);
    outf(DP_SRC, DP_MONO_SRC_ALLONES |
        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
    outf(DP_FRGD_CLR, colour);
    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));

    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);

    if (pATI->XModifier == 1)
        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
示例#6
0
/*
 * ATIScreenInit --
 *
 * This function is called by DIX to initialise the screen.
 */
Bool
ATIScreenInit
(
    int       iScreen,
    ScreenPtr pScreen,
    int       argc,
    char      **argv
)
{
    ScrnInfoPtr  pScreenInfo = xf86Screens[iScreen];
    ATIPtr       pATI        = ATIPTR(pScreenInfo);
    pointer      pFB;
    int          VisualMask;
#ifdef XF86DRI_DEVEL
    BoxRec       ScreenArea;
#endif

    /* Set video hardware state */
    if (!ATIEnterGraphics(pScreen, pScreenInfo, pATI))
        return FALSE;

    /* Re-initialise mi's visual list */
    miClearVisualTypes();

    if ((pATI->depth > 8) && (pATI->DAC == ATI_DAC_INTERNAL))
        VisualMask = TrueColorMask;
    else
        VisualMask = miGetDefaultVisualMask(pATI->depth);

    if (!miSetVisualTypes(pATI->depth, VisualMask, pATI->rgbBits,
                          pScreenInfo->defaultVisual))
        return FALSE;

    if (!miSetPixmapDepths())
        return FALSE;

    pFB = pATI->pMemory;
    pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth);
    if (pATI->OptionShadowFB)
    {
        pATI->FBBytesPerPixel = pATI->bitsPerPixel >> 3;
        pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth);
        if ((pATI->pShadow = xalloc(pATI->FBPitch * pScreenInfo->virtualY)))
        {
            pFB = pATI->pShadow;
        }
        else
        {
            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
                "Insufficient virtual memory for shadow frame buffer.\n");
            pATI->OptionShadowFB = FALSE;
        }
    }
/*
 * ATIMach64SetupForScreenToScreenCopy --
 *
 * This function sets up the draw engine for a series of screen-to-screen copy
 * operations.
 */
static void
ATIMach64SetupForScreenToScreenCopy
(
    ScrnInfoPtr  pScreenInfo,
    int          xdir,
    int          ydir,
    int          rop,
    unsigned int planemask,
    int          TransparencyColour
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 3);
    outf(DP_WRITE_MASK, planemask);
    outf(DP_SRC, DP_MONO_SRC_ALLONES |
        SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));

#ifdef AVOID_DGA

    if (TransparencyColour == -1)

#else /* AVOID_DGA */

    if (!pATI->XAAForceTransBlit && (TransparencyColour == -1))

#endif /* AVOID_DGA */

    {
        outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
    }
    else
    {
        ATIMach64WaitForFIFO(pATI, 2);
        outf(CLR_CMP_CLR, TransparencyColour);
        outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D);
    }

    pATI->dst_cntl = 0;

    if (ydir > 0)
        pATI->dst_cntl |= DST_Y_DIR;
    if (xdir > 0)
        pATI->dst_cntl |= DST_X_DIR;

    if (pATI->XModifier == 1)
        outf(DST_CNTL, pATI->dst_cntl);
    else
        pATI->dst_cntl |= DST_24_ROT_EN;
}
/*
 * ATIDGASetMode --
 *
 * This function sets a graphics mode for a DGA client.
 */
static Bool
ATIDGASetMode
(
    ScrnInfoPtr pScreenInfo,
    DGAModePtr  pDGAMode
)
{
    ATIPtr         pATI    = ATIPTR(pScreenInfo);
    DisplayModePtr pMode;
    int            frameX0, frameY0;

    if (pDGAMode)
    {
        pMode = pDGAMode->mode;
        pATI->depth = pDGAMode->depth;
        pATI->bitsPerPixel = pDGAMode->bitsPerPixel;
        pATI->displayWidth =
            pDGAMode->bytesPerScanline * 8 / pATI->bitsPerPixel;
        pATI->weight.red = BitsSet(pDGAMode->red_mask);
        pATI->weight.green = BitsSet(pDGAMode->green_mask);
        pATI->weight.blue = BitsSet(pDGAMode->blue_mask);
        frameX0 = frameY0 = 0;
        if (!pATI->currentMode)
            pATI->currentMode = pScreenInfo->currentMode;
    }
    else
    {
        if (!(pMode = pATI->currentMode))
            return TRUE;

        pATI->depth = pScreenInfo->depth;
        pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
        pATI->displayWidth = pScreenInfo->displayWidth;
        pATI->weight = pScreenInfo->weight;
        frameX0 = pScreenInfo->frameX0;
        frameY0 = pScreenInfo->frameY0;
    }

    pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
    ATIAdjustPreInit(pATI);
    ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);

    if (!(*pScreenInfo->SwitchMode)(SWITCH_MODE_ARGS(pScreenInfo, pMode)))
        return FALSE;
    if (!pDGAMode)
        pATI->currentMode = NULL;
    (*pScreenInfo->AdjustFrame)(ADJUST_FRAME_ARGS(pScreenInfo, frameX0, frameY0));

    return TRUE;
}
/*
 * ATIMach64SetupForMono8x8PatternFill --
 *
 * This function sets up the draw engine for a series of 8x8 1bpp pattern
 * fills.
 */
static void
ATIMach64SetupForMono8x8PatternFill
(
    ScrnInfoPtr  pScreenInfo,
    int          patx,
    int          paty,
    int          fg,
    int          bg,
    int          rop,
    unsigned int planemask
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 3);
    outf(DP_WRITE_MASK, planemask);
    outf(DP_SRC, DP_MONO_SRC_PATTERN |
        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
    outf(DP_FRGD_CLR, fg);

    if (bg == -1)
    {
        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
            SetBits(MIX_DST, DP_BKGD_MIX));
    }
    else
    {
        ATIMach64WaitForFIFO(pATI, 2);
        outf(DP_BKGD_CLR, bg);
        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
            SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
    }

    ATIMach64WaitForFIFO(pATI, 4);
    outf(PAT_REG0, patx);
    outf(PAT_REG1, paty);
    outf(PAT_CNTL, PAT_MONO_EN);

    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);

    if (pATI->XModifier == 1)
        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
/*
 * ATIMach64SubsequentScreenToScreenCopy --
 *
 * This function performs a screen-to-screen copy operation.
 */
static void
ATIMach64SubsequentScreenToScreenCopy
(
    ScrnInfoPtr pScreenInfo,
    int         xSrc,
    int         ySrc,
    int         xDst,
    int         yDst,
    int         w,
    int         h
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    xSrc *= pATI->XModifier;
    xDst *= pATI->XModifier;
    w    *= pATI->XModifier;

    ATIDRISync(pScreenInfo);

    /* Disable clipping if it gets in the way */
    ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1);

    if (!(pATI->dst_cntl & DST_X_DIR))
    {
        xSrc += w - 1;
        xDst += w - 1;
    }

    if (!(pATI->dst_cntl & DST_Y_DIR))
    {
        ySrc += h - 1;
        yDst += h - 1;
    }

    if (pATI->XModifier != 1)
        outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT));

    ATIMach64WaitForFIFO(pATI, 4);
    outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0));
    outf(SRC_WIDTH1, w);
    outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0));
    outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
}
/*
 * ATIDGAOpenFramebuffer --
 *
 * This function returns various framebuffer attributes to a DGA client.
 */
static Bool
ATIDGAOpenFramebuffer
(
    ScrnInfoPtr   pScreenInfo,
    char          **DeviceName,
    unsigned char **ApertureBase,
    int           *ApertureSize,
    int           *ApertureOffset,
    int           *flags
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    *DeviceName = NULL;         /* No special device */
    *ApertureBase = (unsigned char *)(pATI->LinearBase);
    *ApertureSize = pScreenInfo->videoRam * 1024;
    *ApertureOffset = 0;        /* Always */
    *flags = 0;                 /* Root premissions OS-dependent */

    return TRUE;
}
/*
 * ATIMach64SetupForScanlineCPUToScreenColorExpandFill --
 *
 * This function sets up the engine for a series of colour expansion fills.
 */
static void
ATIMach64SetupForScanlineCPUToScreenColorExpandFill
(
    ScrnInfoPtr  pScreenInfo,
    int          fg,
    int          bg,
    int          rop,
    unsigned int planemask
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 3);
    outf(DP_WRITE_MASK, planemask);
    outf(DP_SRC, DP_MONO_SRC_HOST |
        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
    outf(DP_FRGD_CLR, fg);

    if (bg == -1)
    {
        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
            SetBits(MIX_DST, DP_BKGD_MIX));
    }
    else
    {
        ATIMach64WaitForFIFO(pATI, 2);
        outf(DP_BKGD_CLR, bg);
        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
            SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
    }

    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);

    if (pATI->XModifier == 1)
        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
/*
 * ATIMach64SubsequentSolidHorVertLine --
 *
 * This is called to draw a solid horizontal or vertical line.  This does a
 * one-pixel wide solid fill.
 */
static void
ATIMach64SubsequentSolidHorVertLine
(
    ScrnInfoPtr pScreenInfo,
    int         x,
    int         y,
    int         len,
    int         dir
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    ATIMach64WaitForFIFO(pATI, 3);
    outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));

    if (dir == DEGREES_0)
        outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0));
    else /* if (dir == DEGREES_270) */
        outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0));
}
/*
 * ATIMach64SubsequentScanlineCPUToScreenColorExpandFill --
 *
 * This function sets up the engine for a single colour expansion fill.
 */
static void
ATIMach64SubsequentScanlineCPUToScreenColorExpandFill
(
    ScrnInfoPtr pScreenInfo,
    int         x,
    int         y,
    int         w,
    int         h,
    int         skipleft
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

    ATIDRISync(pScreenInfo);

    if (pATI->XModifier != 1)
    {
        x *= pATI->XModifier;
        w *= pATI->XModifier;
        skipleft *= pATI->XModifier;

        outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
            (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
    }

    pATI->ExpansionBitmapWidth = (w + 31) / 32;

    ATIMach64WaitForFIFO(pATI, 3);
    pATI->sc_left = x + skipleft;
    pATI->sc_right = x + w - 1;
    outf(SC_LEFT_RIGHT,
        SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0));
    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
    outf(DST_HEIGHT_WIDTH,
        SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0));
}
/*
 * ATIDGAFillRect --
 *
 * This function calls XAA solid fill primitives to fill a rectangle.
 */
static void
ATIDGAFillRect
(
    ScrnInfoPtr   pScreenInfo,
    int           x,
    int           y,
    int           w,
    int           h,
    unsigned long colour
)
{
    ATIPtr        pATI     = ATIPTR(pScreenInfo);
/*FIXME : use EXA if available */
#ifdef USE_XAA
    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;

    (*pXAAInfo->SetupForSolidFill)(pScreenInfo, (int)colour, GXcopy,
                                   (CARD32)(~0));
    (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, x, y, w, h);

    if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
        SET_SYNC_FLAG(pXAAInfo);
#endif
}
/*
 * Memory layour for XAA with DRI (no local_textures):
 * | front  | pixmaps, xv | back   | depth  | textures | c |
 *
 * 1024x768@16bpp with 8 MB:
 * | 1.5 MB | ~3.5 MB     | 1.5 MB | 1.5 MB | 0        | c |
 *
 * 1024x768@32bpp with 8 MB:
 * | 3.0 MB | ~0.5 MB     | 3.0 MB | 1.5 MB | 0        | c |
 *
 * "c" is the hw cursor which occupies 1KB
 */
static Bool
ATIMach64SetupMemXAA
(
    ScrnInfoPtr pScreenInfo,
    ScreenPtr pScreen
)
{
    ATIPtr       pATI        = ATIPTR(pScreenInfo);

    ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
    int cpp = pATI->bitsPerPixel >> 3;
    int widthBytes = pScreenInfo->displayWidth * cpp;
    int zWidthBytes = pScreenInfo->displayWidth * 2; /* always 16-bit z-buffer */
    int fbSize = pScreenInfo->videoRam * 1024;
    int bufferSize = pScreenInfo->virtualY * widthBytes;
    int zBufferSize = pScreenInfo->virtualY * zWidthBytes;
    int offscreenBytes, total, scanlines;

    pATIDRIServer->fbX = 0;
    pATIDRIServer->fbY = 0;
    pATIDRIServer->frontOffset = 0;
    pATIDRIServer->frontPitch = pScreenInfo->displayWidth;

    /* Calculate memory remaining for pixcache and textures after
     * front, back, and depth buffers
     */
    offscreenBytes = fbSize - ( 2 * bufferSize + zBufferSize );

    if ( !pATIDRIServer->IsPCI && !pATI->OptionLocalTextures ) {
        /* Don't allocate a local texture heap for AGP unless requested */
        pATIDRIServer->textureSize = 0;
    } else {
        int l, maxPixcache;

#ifdef XvExtension

        int xvBytes;

        /* Try for enough pixmap cache for DVD and a full viewport
         */
        xvBytes = 720*480*cpp; /* enough for single-buffered DVD */
        maxPixcache = xvBytes > bufferSize ? xvBytes : bufferSize;

#else /* XvExtension */

        /* Try for one viewport */
        maxPixcache = bufferSize;

#endif /* XvExtension */

        pATIDRIServer->textureSize = offscreenBytes - maxPixcache;

        /* If that gives us less than half the offscreen mem available for textures, split
         * the available mem between textures and pixmap cache
         */
        if (pATIDRIServer->textureSize < (offscreenBytes/2)) {
            pATIDRIServer->textureSize = offscreenBytes/2;
        }

        if (pATIDRIServer->textureSize <= 0)
            pATIDRIServer->textureSize = 0;

        l = ATIMinBits((pATIDRIServer->textureSize-1) / MACH64_NR_TEX_REGIONS);
        if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;

        /* Round the texture size up to the nearest whole number of
         * texture regions.  Again, be greedy about this, don't round
         * down.
         */
        pATIDRIServer->logTextureGranularity = l;
        pATIDRIServer->textureSize =
            (pATIDRIServer->textureSize >> l) << l;
    }

    total = fbSize - pATIDRIServer->textureSize;
    scanlines = total / widthBytes;
    if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;

    /* Recalculate the texture offset and size to accomodate any
     * rounding to a whole number of scanlines.
     * FIXME: Is this actually needed?
     */
    pATIDRIServer->textureOffset = scanlines * widthBytes;
    pATIDRIServer->textureSize = fbSize - pATIDRIServer->textureOffset;

    /* Set a minimum usable local texture heap size.  This will fit
     * two 256x256 textures.  We check this after any rounding of
     * the texture area.
     */
    if (pATIDRIServer->textureSize < 256*256 * cpp * 2) {
        pATIDRIServer->textureOffset = 0;
        pATIDRIServer->textureSize = 0;
        scanlines = fbSize / widthBytes;
        if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;
    }

    pATIDRIServer->depthOffset = scanlines * widthBytes - zBufferSize;
    pATIDRIServer->depthPitch = pScreenInfo->displayWidth;
    pATIDRIServer->depthY = pATIDRIServer->depthOffset/widthBytes;
    pATIDRIServer->depthX =  (pATIDRIServer->depthOffset -
                              (pATIDRIServer->depthY * widthBytes)) / cpp;

    pATIDRIServer->backOffset = pATIDRIServer->depthOffset - bufferSize;
    pATIDRIServer->backPitch = pScreenInfo->displayWidth;
    pATIDRIServer->backY = pATIDRIServer->backOffset/widthBytes;
    pATIDRIServer->backX =  (pATIDRIServer->backOffset -
                             (pATIDRIServer->backY * widthBytes)) / cpp;

    scanlines = fbSize / widthBytes;
    if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;

    if ( pATIDRIServer->IsPCI && pATIDRIServer->textureSize == 0 ) {
        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
                   "Not enough memory for local textures, disabling DRI\n");
        ATIDRICloseScreen(pScreen);
        pATI->directRenderingEnabled = FALSE;
    } else {
        BoxRec ScreenArea;

        ScreenArea.x1 = 0;
        ScreenArea.y1 = 0;
        ScreenArea.x2 = pATI->displayWidth;
        ScreenArea.y2 = scanlines;

        if (!xf86InitFBManager(pScreen, &ScreenArea)) {
            xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
                       "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
                       ScreenArea.x1, ScreenArea.y1,
                       ScreenArea.x2, ScreenArea.y2);
            return FALSE;
        } else {
            int width, height;

            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
                       "Memory manager initialized to (%d,%d) (%d,%d)\n",
                       ScreenArea.x1, ScreenArea.y1, ScreenArea.x2, ScreenArea.y2);

            if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) {
                xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
                           "Largest offscreen area available: %d x %d\n",
                           width, height);

                /* lines in offscreen area needed for depth buffer and textures */
                pATI->depthTexLines = scanlines
                                      - pATIDRIServer->depthOffset / widthBytes;
                pATI->backLines     = scanlines
                                      - pATIDRIServer->backOffset / widthBytes
                                      - pATI->depthTexLines;
                pATI->depthTexArea  = NULL;
                pATI->backArea      = NULL;
            } else {
                xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
                           "Unable to determine largest offscreen area available\n");
                return FALSE;
            }

        }

        xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Will use %d kB of offscreen memory for XAA\n",
                   (offscreenBytes - pATIDRIServer->textureSize)/1024);

        xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Will use back buffer at offset 0x%x\n",
                   pATIDRIServer->backOffset);

        xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Will use depth buffer at offset 0x%x\n",
                   pATIDRIServer->depthOffset);

        if (pATIDRIServer->textureSize > 0) {
            xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
                       "Will use %d kB for local textures at offset 0x%x\n",
                       pATIDRIServer->textureSize/1024,
                       pATIDRIServer->textureOffset);
        }
    }

    return TRUE;
}
/*
 * ATIMach64SubsequentColorExpandScanline --
 *
 * This function feeds a bitmap scanline to the engine for a colour expansion
 * fill.  This is written to do burst transfers for those platforms that can do
 * them, and to improve CPU/engine concurrency.
 */
static void
ATIMach64SubsequentColorExpandScanline
(
    ScrnInfoPtr pScreenInfo,
    int         iBuffer
)
{
    ATIPtr          pATI         = ATIPTR(pScreenInfo);
    CARD32          *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer];
    int             w            = pATI->ExpansionBitmapWidth;
    int             nDWord;

    ATIDRISync(pScreenInfo);

    while (w > 0)
    {
        /*
         * Transfers are done in chunks of up to 64 bytes in length (32 on
         * earlier controllers).
         */
        nDWord = w;
        if (nDWord > pATI->nHostFIFOEntries)
            nDWord = pATI->nHostFIFOEntries;

        /* Make enough FIFO slots available */
        ATIMach64WaitForFIFO(pATI, nDWord);

        /*
         * Always start transfers on a chuck-sized boundary.  Note that
         * HOST_DATA_0 is actually on a 512-byte boundary, but *pBitmapData can
         * only be guaranteed to be on a chunk-sized boundary.
         *
         * Transfer current chunk.  With any luck, the compiler won't mangle
         * this too badly...
         */

#       if defined(ATIMove32)

        {
            ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord);
        }

#       else

        {
            volatile CARD32 *pDst;
            CARD32          *pSrc;
            unsigned int    iDWord;

            iDWord = 16 - nDWord;
            pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord;
            pSrc = pBitmapData - iDWord;

            switch (iDWord)
            {
                case  0:  MMIO_MOVE32(pDst +  0, 0, *(pSrc +  0));
                case  1:  MMIO_MOVE32(pDst +  1, 0, *(pSrc +  1));
                case  2:  MMIO_MOVE32(pDst +  2, 0, *(pSrc +  2));
                case  3:  MMIO_MOVE32(pDst +  3, 0, *(pSrc +  3));
                case  4:  MMIO_MOVE32(pDst +  4, 0, *(pSrc +  4));
                case  5:  MMIO_MOVE32(pDst +  5, 0, *(pSrc +  5));
                case  6:  MMIO_MOVE32(pDst +  6, 0, *(pSrc +  6));
                case  7:  MMIO_MOVE32(pDst +  7, 0, *(pSrc +  7));
                case  8:  MMIO_MOVE32(pDst +  8, 0, *(pSrc +  8));
                case  9:  MMIO_MOVE32(pDst +  9, 0, *(pSrc +  9));
                case 10:  MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10));
                case 11:  MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11));
                case 12:  MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12));
                case 13:  MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13));
                case 14:  MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14));
                case 15:  MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15));

                default:    /* Muffle compiler */
                    break;
            }
        }

#       endif

        /* Step to next chunk */
        pBitmapData += nDWord;
        w -= nDWord;
        pATI->nAvailableFIFOEntries -= nDWord;
    }

    pATI->EngineIsBusy = TRUE;
}
/*
 * ATIMach64Sync --
 *
 * This is called to wait for the draw engine to become idle.
 */
void
ATIMach64Sync
(
    ScrnInfoPtr pScreenInfo
)
{
    ATIPtr pATI = ATIPTR(pScreenInfo);

#ifdef XF86DRI_DEVEL

    if ( pATI->directRenderingEnabled && pATI->NeedDRISync )
    {
	ATIHWPtr pATIHW = &pATI->NewHW;

	if (pATI->OptionMMIOCache) {
	    /* "Invalidate" the MMIO cache so the cache slots get updated */
	    UncacheRegister(SRC_CNTL);
	    UncacheRegister(HOST_CNTL);
	    UncacheRegister(PAT_CNTL);
	    UncacheRegister(SC_LEFT_RIGHT);
	    UncacheRegister(SC_TOP_BOTTOM);
	    UncacheRegister(DP_BKGD_CLR);
	    UncacheRegister(DP_FRGD_CLR);
	    UncacheRegister(DP_WRITE_MASK);
	    UncacheRegister(DP_MIX);
	    UncacheRegister(CLR_CMP_CNTL);
	}

	ATIDRIWaitForIdle(pATI);

	outr( BUS_CNTL, pATIHW->bus_cntl );

	/* DRI uses GUI_TRAJ_CNTL, which is a composite of 
	 * src_cntl, dst_cntl, pat_cntl, and host_cntl
	 */
	outf( SRC_CNTL, pATIHW->src_cntl );
	outf( DST_CNTL, pATIHW->dst_cntl );
	outf( PAT_CNTL, pATIHW->pat_cntl );
	outf( HOST_CNTL, pATIHW->host_cntl );

	outf( DST_OFF_PITCH, pATIHW->dst_off_pitch );
	outf( SRC_OFF_PITCH, pATIHW->src_off_pitch );
	outf( DP_SRC, pATIHW->dp_src );
	outf( DP_MIX, pATIHW->dp_mix );
	outf( DP_FRGD_CLR,  pATIHW->dp_frgd_clr );
	outf( DP_WRITE_MASK, pATIHW->dp_write_mask );
	
	outf( DP_PIX_WIDTH, pATIHW->dp_pix_width );
	outf( CLR_CMP_CNTL, pATIHW->clr_cmp_cntl );
	outf( ALPHA_TST_CNTL, 0 );
	outf( Z_CNTL, 0 );
	outf( SCALE_3D_CNTL, 0 );

	ATIMach64WaitForFIFO(pATI, 2);
	outf( SC_LEFT_RIGHT,
	      SetWord(pATIHW->sc_right, 1) | SetWord(pATIHW->sc_left, 0) );
	outf( SC_TOP_BOTTOM,
	      SetWord(pATIHW->sc_bottom, 1) | SetWord(pATIHW->sc_top, 0) );

	if (pATI->OptionMMIOCache) {
	    /* Now that the cache slots reflect the register state, re-enable MMIO cache */
	    CacheRegister(SRC_CNTL);
	    CacheRegister(HOST_CNTL);
	    CacheRegister(PAT_CNTL);
	    CacheRegister(SC_LEFT_RIGHT);
	    CacheRegister(SC_TOP_BOTTOM);
	    CacheRegister(DP_BKGD_CLR);
	    CacheRegister(DP_FRGD_CLR);
	    CacheRegister(DP_WRITE_MASK);
	    CacheRegister(DP_MIX);
	    CacheRegister(CLR_CMP_CNTL);
	}

	ATIMach64WaitForIdle(pATI);

	if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) {
	  
	    /* Only check registers we didn't restore */
	    TestRegisterCaching(PAT_REG0);
            TestRegisterCaching(PAT_REG1);

            TestRegisterCaching(CLR_CMP_CLR);
            TestRegisterCaching(CLR_CMP_MSK);

	    if (pATI->Block1Base)
            {
                TestRegisterCaching(OVERLAY_Y_X_START);
                TestRegisterCaching(OVERLAY_Y_X_END);

                TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR);
                TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK);

                TestRegisterCaching(OVERLAY_KEY_CNTL);

                TestRegisterCaching(OVERLAY_SCALE_INC);
                TestRegisterCaching(OVERLAY_SCALE_CNTL);

                TestRegisterCaching(SCALER_HEIGHT_WIDTH);

                TestRegisterCaching(SCALER_TEST);

                TestRegisterCaching(VIDEO_FORMAT);
   
                if (pATI->Chip < ATI_CHIP_264VTB)
                {
                    TestRegisterCaching(BUF0_OFFSET);
                    TestRegisterCaching(BUF0_PITCH);
                    TestRegisterCaching(BUF1_OFFSET);
                    TestRegisterCaching(BUF1_PITCH);
                }
                else
                {
                    TestRegisterCaching(SCALER_BUF0_OFFSET);
                    TestRegisterCaching(SCALER_BUF1_OFFSET);
                    TestRegisterCaching(SCALER_BUF_PITCH);

                    TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ);
                    TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT);
  
                    if (pATI->Chip >= ATI_CHIP_264GTPRO)
                    {
                        TestRegisterCaching(SCALER_COLOUR_CNTL);
  
                        TestRegisterCaching(SCALER_H_COEFF0);
                        TestRegisterCaching(SCALER_H_COEFF1);
                        TestRegisterCaching(SCALER_H_COEFF2);
                        TestRegisterCaching(SCALER_H_COEFF3);
                        TestRegisterCaching(SCALER_H_COEFF4);

                        TestRegisterCaching(SCALER_BUF0_OFFSET_U);
                        TestRegisterCaching(SCALER_BUF0_OFFSET_V);
                        TestRegisterCaching(SCALER_BUF1_OFFSET_U);
                        TestRegisterCaching(SCALER_BUF1_OFFSET_V);
                    }
                }
    	    }
         }
	pATI->NeedDRISync = FALSE;

    }
    else

#endif /* XF86DRI_DEVEL */
    {
      ATIMach64WaitForIdle(pATI);
      
      if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache)
      {
        /*
         * For debugging purposes, attempt to verify that each cached register
         * should actually be cached.
         */
        TestRegisterCaching(SRC_CNTL);

        TestRegisterCaching(HOST_CNTL);

        TestRegisterCaching(PAT_REG0);
        TestRegisterCaching(PAT_REG1);
        TestRegisterCaching(PAT_CNTL);

        if (RegisterIsCached(SC_LEFT_RIGHT) &&  /* Special case */
            (CacheSlot(SC_LEFT_RIGHT) !=
             (SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0))))
        {
            UncacheRegister(SC_LEFT_RIGHT);
            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
                "SC_LEFT_RIGHT write cache disabled!\n");
        }

        if (RegisterIsCached(SC_TOP_BOTTOM) &&  /* Special case */
            (CacheSlot(SC_TOP_BOTTOM) !=
             (SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0))))
        {
            UncacheRegister(SC_TOP_BOTTOM);
            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
                "SC_TOP_BOTTOM write cache disabled!\n");
        }

        TestRegisterCaching(DP_BKGD_CLR);
        TestRegisterCaching(DP_FRGD_CLR);
        TestRegisterCaching(DP_WRITE_MASK);
        TestRegisterCaching(DP_MIX);

        TestRegisterCaching(CLR_CMP_CLR);
        TestRegisterCaching(CLR_CMP_MSK);
        TestRegisterCaching(CLR_CMP_CNTL);

        if (pATI->Block1Base)
        {
            TestRegisterCaching(OVERLAY_Y_X_START);
            TestRegisterCaching(OVERLAY_Y_X_END);

            TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR);
            TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK);

            TestRegisterCaching(OVERLAY_KEY_CNTL);

            TestRegisterCaching(OVERLAY_SCALE_INC);
            TestRegisterCaching(OVERLAY_SCALE_CNTL);

            TestRegisterCaching(SCALER_HEIGHT_WIDTH);

            TestRegisterCaching(SCALER_TEST);

            TestRegisterCaching(VIDEO_FORMAT);

            if (pATI->Chip < ATI_CHIP_264VTB)
            {
                TestRegisterCaching(BUF0_OFFSET);
                TestRegisterCaching(BUF0_PITCH);
                TestRegisterCaching(BUF1_OFFSET);
                TestRegisterCaching(BUF1_PITCH);
            }
            else
            {
                TestRegisterCaching(SCALER_BUF0_OFFSET);
                TestRegisterCaching(SCALER_BUF1_OFFSET);
                TestRegisterCaching(SCALER_BUF_PITCH);

                TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ);
                TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT);

                if (pATI->Chip >= ATI_CHIP_264GTPRO)
                {
                    TestRegisterCaching(SCALER_COLOUR_CNTL);

                    TestRegisterCaching(SCALER_H_COEFF0);
                    TestRegisterCaching(SCALER_H_COEFF1);
                    TestRegisterCaching(SCALER_H_COEFF2);
                    TestRegisterCaching(SCALER_H_COEFF3);
                    TestRegisterCaching(SCALER_H_COEFF4);

                    TestRegisterCaching(SCALER_BUF0_OFFSET_U);
                    TestRegisterCaching(SCALER_BUF0_OFFSET_V);
                    TestRegisterCaching(SCALER_BUF1_OFFSET_U);
                    TestRegisterCaching(SCALER_BUF1_OFFSET_V);
                }
            }
        }
      }
    }

    /*
     * For VTB's and later, the first CPU read of the framebuffer will return
     * zeroes, so do it here.  This appears to be due to some kind of engine
     * caching of framebuffer data I haven't found any way of disabling, or
     * otherwise circumventing.  Thanks to Mark Vojkovich for the suggestion.
     */
    if (pATI->pXAAInfo)
      pATI->pXAAInfo->NeedToSync = FALSE;

    pATI = *(volatile ATIPtr *)pATI->pMemory;
}