smi_exa.c revision 09885543
109885543Smrg/*
209885543SmrgCopyright (C) 2006 Dennis De Winter  All Rights Reserved.
309885543SmrgCopyright (C) 2007 Alex Deucher  All Rights Reserved.
409885543Smrg
509885543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
609885543Smrgthis software and associated documentation files (the "Software"), to deal in
709885543Smrgthe Software without restriction, including without limitation the rights to
809885543Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
909885543Smrgof the Software, and to permit persons to whom the Software is furnished to do
1009885543Smrgso, subject to the following conditions:
1109885543Smrg
1209885543SmrgThe above copyright notice and this permission notice shall be included in all
1309885543Smrgcopies or substantial portions of the Software.
1409885543Smrg
1509885543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1609885543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
1709885543SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1809885543SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1909885543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2009885543SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2109885543Smrg
2209885543Smrg*/
2309885543Smrg
2409885543Smrg#ifdef HAVE_CONFIG_H
2509885543Smrg#include "config.h"
2609885543Smrg#endif
2709885543Smrg
2809885543Smrg#include "smi.h"
2909885543Smrg
3009885543Smrg
3109885543Smrgstatic void
3209885543SmrgSMI_EXASync(ScreenPtr pScreen, int marker);
3309885543Smrg
3409885543Smrgstatic Bool
3509885543SmrgSMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
3609885543Smrg		int xdir, int ydir, int alu, Pixel planemask);
3709885543Smrg
3809885543Smrgstatic void
3909885543SmrgSMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height);
4009885543Smrg
4109885543Smrgstatic void
4209885543SmrgSMI_DoneCopy(PixmapPtr pDstPixmap);
4309885543Smrg
4409885543Smrgstatic Bool
4509885543SmrgSMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg);
4609885543Smrg
4709885543Smrgstatic void
4809885543SmrgSMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
4909885543Smrg
5009885543Smrgstatic void
5109885543SmrgSMI_DoneSolid(PixmapPtr pPixmap);
5209885543Smrg
5309885543SmrgBool
5409885543SmrgSMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch);
5509885543Smrg
5609885543SmrgBool
5709885543SmrgSMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch);
5809885543Smrg
5909885543SmrgBool
6009885543SmrgSMI_EXAInit(ScreenPtr pScreen)
6109885543Smrg{
6209885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
6309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
6409885543Smrg
6509885543Smrg    ENTER_PROC("SMI_EXAInit");
6609885543Smrg
6709885543Smrg    if (!(pSmi->EXADriverPtr = exaDriverAlloc())) {
6809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate EXADriverRec.\n");
6909885543Smrg	LEAVE_PROC("SMI_EXAInit");
7009885543Smrg	return FALSE;
7109885543Smrg    }
7209885543Smrg
7309885543Smrg    pSmi->EXADriverPtr->exa_major = 2;
7409885543Smrg    pSmi->EXADriverPtr->exa_minor = 0;
7509885543Smrg
7609885543Smrg    SMI_EngineReset(pScrn);
7709885543Smrg
7809885543Smrg    /* Memory Manager */
7909885543Smrg    pSmi->EXADriverPtr->memoryBase = pSmi->FBBase + pSmi->FBOffset;
8009885543Smrg    pSmi->EXADriverPtr->memorySize = pSmi->FBReserved - 1024;
8109885543Smrg    pSmi->EXADriverPtr->offScreenBase = pSmi->width * pSmi->height * pSmi->Bpp + 1024;
8209885543Smrg
8309885543Smrg    /* Flags */
8409885543Smrg    pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS;
8509885543Smrg    if (pSmi->EXADriverPtr->memorySize > pSmi->EXADriverPtr->offScreenBase) {
8609885543Smrg	/* Offscreen Pixmaps */
8709885543Smrg	pSmi->EXADriverPtr->flags |= EXA_OFFSCREEN_PIXMAPS;
8809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8909885543Smrg			"EXA offscreen memory manager enabled.\n");
9009885543Smrg    } else {
9109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
9209885543Smrg		   "Not enough video RAM for EXA offscreen memory manager.\n");
9309885543Smrg    }
9409885543Smrg
9509885543Smrg    /* 12 bit coordinates */
9609885543Smrg    pSmi->EXADriverPtr->maxX = 4096;
9709885543Smrg    pSmi->EXADriverPtr->maxY = 4096;
9809885543Smrg
9909885543Smrg    pSmi->EXADriverPtr->pixmapPitchAlign  = 16;
10009885543Smrg    pSmi->EXADriverPtr->pixmapOffsetAlign = 8;
10109885543Smrg
10209885543Smrg    /* Sync */
10309885543Smrg    pSmi->EXADriverPtr->WaitMarker = SMI_EXASync;
10409885543Smrg
10509885543Smrg    /* Copy */
10609885543Smrg    pSmi->EXADriverPtr->PrepareCopy = SMI_PrepareCopy;
10709885543Smrg    pSmi->EXADriverPtr->Copy = SMI_Copy;
10809885543Smrg    pSmi->EXADriverPtr->DoneCopy = SMI_DoneCopy;
10909885543Smrg
11009885543Smrg    /* Solid */
11109885543Smrg    pSmi->EXADriverPtr->PrepareSolid = SMI_PrepareSolid;
11209885543Smrg    pSmi->EXADriverPtr->Solid = SMI_Solid;
11309885543Smrg    pSmi->EXADriverPtr->DoneSolid = SMI_DoneSolid;
11409885543Smrg
11509885543Smrg    /* DFS & UTS */
11609885543Smrg#if 0
11709885543Smrg    pSmi->EXADriverPtr->UploadToScreen = SMI_UploadToScreen;
11809885543Smrg    pSmi->EXADriverPtr->DownloadFromScreen = SMI_DownloadFromScreen;
11909885543Smrg#endif
12009885543Smrg
12109885543Smrg    if(!exaDriverInit(pScreen, pSmi->EXADriverPtr)) {
12209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "exaDriverInit failed.\n");
12309885543Smrg	LEAVE_PROC("SMI_EXAInit");
12409885543Smrg	return FALSE;
12509885543Smrg    } else {
12609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n");
12709885543Smrg	LEAVE_PROC("SMI_EXAInit");
12809885543Smrg	return TRUE;
12909885543Smrg    }
13009885543Smrg}
13109885543Smrg
13209885543Smrgstatic void
13309885543SmrgSMI_EXASync(ScreenPtr pScreen, int marker)
13409885543Smrg{
13509885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
13609885543Smrg    SMIPtr pSmi = SMIPTR(xf86Screens[pScreen->myNum]);
13709885543Smrg
13809885543Smrg    ENTER_PROC("SMI_EXASync");
13909885543Smrg
14009885543Smrg    WaitIdleEmpty();
14109885543Smrg
14209885543Smrg    LEAVE_PROC("SMI_EXASync");
14309885543Smrg}
14409885543Smrg
14509885543Smrgstatic CARD32
14609885543SmrgSMI_DEDataFormat(PixmapPtr pPixmap) {
14709885543Smrg    CARD32 DEDataFormat = 0;
14809885543Smrg
14909885543Smrg    switch (pPixmap->drawable.bitsPerPixel) {
15009885543Smrg    case 8:
15109885543Smrg	DEDataFormat = 0x00000000;
15209885543Smrg	break;
15309885543Smrg    case 16:
15409885543Smrg	DEDataFormat = 0x00100000;
15509885543Smrg	break;
15609885543Smrg    case 24:
15709885543Smrg	DEDataFormat = 0x00300000;
15809885543Smrg	break;
15909885543Smrg    case 32:
16009885543Smrg	DEDataFormat = 0x00200000;
16109885543Smrg	break;
16209885543Smrg    }
16309885543Smrg    return DEDataFormat;
16409885543Smrg}
16509885543Smrg
16609885543Smrg/* ----------------------------------------------------- EXA Copy ---------------------------------------------- */
16709885543Smrg
16809885543SmrgCARD8 SMI_BltRop[16] =	/* table stolen from KAA */
16909885543Smrg{
17009885543Smrg    /* GXclear      */      0x00,         /* 0 */
17109885543Smrg    /* GXand        */      0x88,         /* src AND dst */
17209885543Smrg    /* GXandReverse */      0x44,         /* src AND NOT dst */
17309885543Smrg    /* GXcopy       */      0xCC,         /* src */
17409885543Smrg    /* GXandInverted*/      0x22,         /* NOT src AND dst */
17509885543Smrg    /* GXnoop       */      0xAA,         /* dst */
17609885543Smrg    /* GXxor        */      0x66,         /* src XOR dst */
17709885543Smrg    /* GXor         */      0xEE,         /* src OR dst */
17809885543Smrg    /* GXnor        */      0x11,         /* NOT src AND NOT dst */
17909885543Smrg    /* GXequiv      */      0x99,         /* NOT src XOR dst */
18009885543Smrg    /* GXinvert     */      0x55,         /* NOT dst */
18109885543Smrg    /* GXorReverse  */      0xDD,         /* src OR NOT dst */
18209885543Smrg    /* GXcopyInverted*/     0x33,         /* NOT src */
18309885543Smrg    /* GXorInverted */      0xBB,         /* NOT src OR dst */
18409885543Smrg    /* GXnand       */      0x77,         /* NOT src OR NOT dst */
18509885543Smrg    /* GXset        */      0xFF,         /* 1 */
18609885543Smrg};
18709885543Smrg
18809885543Smrgstatic Bool
18909885543SmrgSMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
19009885543Smrg		int alu, Pixel planemask)
19109885543Smrg{
19209885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
19309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
19409885543Smrg    int src_pitch, dst_pitch;
19509885543Smrg    unsigned long src_offset, dst_offset;
19609885543Smrg
19709885543Smrg    ENTER_PROC("SMI_PrepareCopy");
19809885543Smrg    DEBUG((VERBLEV, "xdir=%d ydir=%d alu=%02X", xdir, ydir, alu));
19909885543Smrg
20009885543Smrg    /* Bit Mask not supported > 16 bpp */
20109885543Smrg    if ((pSrcPixmap->drawable.bitsPerPixel > 16) &&
20209885543Smrg	(!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))) {
20309885543Smrg	LEAVE_PROC("SMI_PrepareCopy");
20409885543Smrg	return FALSE;
20509885543Smrg    }
20609885543Smrg
20709885543Smrg    /* calculate pitch in pixel unit */
20809885543Smrg    src_pitch  = exaGetPixmapPitch(pSrcPixmap) / (pSrcPixmap->drawable.bitsPerPixel >> 3);
20909885543Smrg    dst_pitch  = exaGetPixmapPitch(pDstPixmap) / (pDstPixmap->drawable.bitsPerPixel >> 3);
21009885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
21109885543Smrg    src_offset = exaGetPixmapOffset(pSrcPixmap) >> 3;
21209885543Smrg    dst_offset = exaGetPixmapOffset(pDstPixmap) >> 3;
21309885543Smrg
21409885543Smrg    pSmi->AccelCmd = SMI_BltRop[alu]
21509885543Smrg		   | SMI_BITBLT
21609885543Smrg		   | SMI_QUICK_START;
21709885543Smrg
21809885543Smrg    if (xdir < 0 || (ydir < 0)) {
21909885543Smrg	pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
22009885543Smrg    }
22109885543Smrg
22209885543Smrg    WaitQueue(7);
22309885543Smrg    /* Destination and Source Window Widths */
22409885543Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF));
22509885543Smrg
22609885543Smrg    if (pDstPixmap->drawable.bitsPerPixel == 24) {
22709885543Smrg	src_pitch *= 3;
22809885543Smrg	dst_pitch *= 3;
22909885543Smrg    }
23009885543Smrg
23109885543Smrg    /* Bit Mask (planemask) - 16 bit only */
23209885543Smrg    if (pSrcPixmap->drawable.bitsPerPixel == 16) {
23309885543Smrg	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
23409885543Smrg    } else {
23509885543Smrg	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
23609885543Smrg    }
23709885543Smrg
23809885543Smrg    /* Destination and Source Row Pitch */
23909885543Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF));
24009885543Smrg    /* Drawing engine data format */
24109885543Smrg    WRITE_DPR(pSmi, 0x1C, SMI_DEDataFormat(pDstPixmap));
24209885543Smrg    /* Destination and Source Base Address (offset) */
24309885543Smrg    WRITE_DPR(pSmi, 0x40, src_offset);
24409885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
24509885543Smrg
24609885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
24709885543Smrg
24809885543Smrg    LEAVE_PROC("SMI_PrepareCopy");
24909885543Smrg    return TRUE;
25009885543Smrg}
25109885543Smrg
25209885543Smrgstatic void
25309885543SmrgSMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX,
25409885543Smrg	 int dstY, int width, int height)
25509885543Smrg{
25609885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
25709885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
25809885543Smrg
25909885543Smrg    ENTER_PROC("SMI_Copy");
26009885543Smrg    DEBUG((VERBLEV, "srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n",
26109885543Smrg	   srcX, srcY, dstX, dstY, width, height));
26209885543Smrg
26309885543Smrg    if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
26409885543Smrg	srcX += width  - 1;
26509885543Smrg	srcY += height - 1;
26609885543Smrg	dstX += width  - 1;
26709885543Smrg	dstY += height - 1;
26809885543Smrg    }
26909885543Smrg
27009885543Smrg    if (pDstPixmap->drawable.bitsPerPixel == 24) {
27109885543Smrg	srcX  *= 3;
27209885543Smrg	dstX  *= 3;
27309885543Smrg	width *= 3;
27409885543Smrg
27509885543Smrg    	if (pSmi->Chipset == SMI_LYNX) {
27609885543Smrg	    srcY *= 3;
27709885543Smrg	    dstY *= 3;
27809885543Smrg        }
27909885543Smrg
28009885543Smrg	if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
28109885543Smrg	    srcX += 2;
28209885543Smrg	    dstX += 2;
28309885543Smrg	}
28409885543Smrg    }
28509885543Smrg
28609885543Smrg    WaitQueue(3);
28709885543Smrg    WRITE_DPR(pSmi, 0x00, (srcX  << 16) + (srcY & 0xFFFF));
28809885543Smrg    WRITE_DPR(pSmi, 0x04, (dstX  << 16) + (dstY & 0xFFFF));
28909885543Smrg    WRITE_DPR(pSmi, 0x08, (width << 16) + (height & 0xFFFF));
29009885543Smrg
29109885543Smrg    LEAVE_PROC("SMI_Copy");
29209885543Smrg}
29309885543Smrg
29409885543Smrgstatic void
29509885543SmrgSMI_DoneCopy(PixmapPtr pDstPixmap)
29609885543Smrg{
29709885543Smrg    ENTER_PROC("SMI_DoneCopy");
29809885543Smrg
29909885543Smrg    LEAVE_PROC("SMI_DoneCopy");
30009885543Smrg}
30109885543Smrg
30209885543Smrg/* ----------------------------------------------------- EXA Solid --------------------------------------------- */
30309885543Smrg
30409885543SmrgCARD8 SMI_SolidRop[16] =	/* table stolen from KAA */
30509885543Smrg{
30609885543Smrg    /* GXclear      */      0x00,         /* 0 */
30709885543Smrg    /* GXand        */      0xA0,         /* src AND dst */
30809885543Smrg    /* GXandReverse */      0x50,         /* src AND NOT dst */
30909885543Smrg    /* GXcopy       */      0xF0,         /* src */
31009885543Smrg    /* GXandInverted*/      0x0A,         /* NOT src AND dst */
31109885543Smrg    /* GXnoop       */      0xAA,         /* dst */
31209885543Smrg    /* GXxor        */      0x5A,         /* src XOR dst */
31309885543Smrg    /* GXor         */      0xFA,         /* src OR dst */
31409885543Smrg    /* GXnor        */      0x05,         /* NOT src AND NOT dst */
31509885543Smrg    /* GXequiv      */      0xA5,         /* NOT src XOR dst */
31609885543Smrg    /* GXinvert     */      0x55,         /* NOT dst */
31709885543Smrg    /* GXorReverse  */      0xF5,         /* src OR NOT dst */
31809885543Smrg    /* GXcopyInverted*/     0x0F,         /* NOT src */
31909885543Smrg    /* GXorInverted */      0xAF,         /* NOT src OR dst */
32009885543Smrg    /* GXnand       */      0x5F,         /* NOT src OR NOT dst */
32109885543Smrg    /* GXset        */      0xFF,         /* 1 */
32209885543Smrg};
32309885543Smrg
32409885543Smrgstatic Bool
32509885543SmrgSMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
32609885543Smrg{
32709885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
32809885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
32909885543Smrg    int dst_pitch;
33009885543Smrg    unsigned long dst_offset;
33109885543Smrg
33209885543Smrg    ENTER_PROC("SMI_PrepareSolid");
33309885543Smrg    DEBUG((VERBLEV, "alu=%02X\n", alu));
33409885543Smrg
33509885543Smrg    /* HW ignores alpha */
33609885543Smrg    if (pPixmap->drawable.bitsPerPixel == 32)
33709885543Smrg	return FALSE;
33809885543Smrg
33909885543Smrg    /* Bit Mask not supported > 16 bpp */
34009885543Smrg    if ((pPixmap->drawable.bitsPerPixel > 16) &&
34109885543Smrg	(!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))) {
34209885543Smrg	LEAVE_PROC("SMI_PrepareCopy");
34309885543Smrg	return FALSE;
34409885543Smrg    }
34509885543Smrg
34609885543Smrg    /* calculate pitch in pixel unit */
34709885543Smrg    dst_pitch  = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel >> 3);
34809885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
34909885543Smrg    dst_offset = exaGetPixmapOffset(pPixmap) >> 3;
35009885543Smrg
35109885543Smrg    pSmi->AccelCmd = SMI_SolidRop[alu]
35209885543Smrg		   | SMI_BITBLT
35309885543Smrg		   | SMI_QUICK_START;
35409885543Smrg
35509885543Smrg    WaitQueue(10);
35609885543Smrg    /* Destination Window Width */
35709885543Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
35809885543Smrg
35909885543Smrg    if (pPixmap->drawable.bitsPerPixel == 24) {
36009885543Smrg	dst_pitch *= 3;
36109885543Smrg    }
36209885543Smrg
36309885543Smrg    /* Bit Mask (planemask) - 16 bit only */
36409885543Smrg    if (pPixmap->drawable.bitsPerPixel == 16) {
36509885543Smrg	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
36609885543Smrg    } else {
36709885543Smrg	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
36809885543Smrg    }
36909885543Smrg
37009885543Smrg    /* Destination Row Pitch */
37109885543Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
37209885543Smrg    /* Drawing engine data format */
37309885543Smrg    WRITE_DPR(pSmi, 0x1C, SMI_DEDataFormat(pPixmap));
37409885543Smrg    /* Source and Destination Base Address (offset) */
37509885543Smrg    WRITE_DPR(pSmi, 0x40, dst_offset);
37609885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
37709885543Smrg    /* Foreground Color */
37809885543Smrg    WRITE_DPR(pSmi, 0x14, fg);
37909885543Smrg    /* Mono Pattern High and Low */
38009885543Smrg    WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
38109885543Smrg    WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);
38209885543Smrg
38309885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
38409885543Smrg
38509885543Smrg    LEAVE_PROC("SMI_PrepareSolid");
38609885543Smrg    return TRUE;
38709885543Smrg}
38809885543Smrg
38909885543Smrgstatic void
39009885543SmrgSMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
39109885543Smrg{
39209885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
39309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
39409885543Smrg    int w, h;
39509885543Smrg
39609885543Smrg    ENTER_PROC("SMI_Solid");
39709885543Smrg    DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d\n", x1, y1, x2, y2));
39809885543Smrg
39909885543Smrg    w = (x2 - x1);
40009885543Smrg    h = (y2 - y1);
40109885543Smrg
40209885543Smrg    if (pPixmap->drawable.bitsPerPixel == 24) {
40309885543Smrg	x1 *= 3;
40409885543Smrg	w  *= 3;
40509885543Smrg
40609885543Smrg	if (pSmi->Chipset == SMI_LYNX) {
40709885543Smrg	    y1 *= 3;
40809885543Smrg	}
40909885543Smrg    }
41009885543Smrg
41109885543Smrg    WaitQueue(2);
41209885543Smrg    WRITE_DPR(pSmi, 0x04, (x1 << 16) | (y1 & 0xFFFF));
41309885543Smrg    WRITE_DPR(pSmi, 0x08, (w  << 16) | (h  & 0xFFFF));
41409885543Smrg
41509885543Smrg    LEAVE_PROC("SMI_Solid");
41609885543Smrg}
41709885543Smrg
41809885543Smrgstatic void
41909885543SmrgSMI_DoneSolid(PixmapPtr pPixmap)
42009885543Smrg{
42109885543Smrg    ENTER_PROC("SMI_DoneSolid");
42209885543Smrg
42309885543Smrg    LEAVE_PROC("SMI_DoneSolid");
42409885543Smrg}
42509885543Smrg
42609885543Smrg/* --------------------------------------- EXA DFS & UTS ---------------------------------------- */
42709885543Smrg
42809885543SmrgBool
42909885543SmrgSMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
43009885543Smrg		       char *dst, int dst_pitch)
43109885543Smrg{
43209885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
43309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
43409885543Smrg
43509885543Smrg    ENTER_PROC("SMI_DownloadFromScreen");
43609885543Smrg    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d dst=%d dst_pitch=%d\n",
43709885543Smrg	   x, y, w, h, dst, dst_pitch));
43809885543Smrg
43909885543Smrg    unsigned char *src = pSrc->devPrivate.ptr;
44009885543Smrg    int src_pitch = exaGetPixmapPitch(pSrc);
44109885543Smrg
44209885543Smrg    exaWaitSync(pSrc->drawable.pScreen);
44309885543Smrg
44409885543Smrg    src += (y * src_pitch) + (x * pSmi->Bpp);
44509885543Smrg    w   *= pSmi->Bpp;
44609885543Smrg
44709885543Smrg    while (h--) {
44809885543Smrg	memcpy(dst, src, w);
44909885543Smrg	src += src_pitch;
45009885543Smrg	dst += dst_pitch;
45109885543Smrg    }
45209885543Smrg
45309885543Smrg    return TRUE;
45409885543Smrg    LEAVE_PROC("SMI_DownloadFromScreen");
45509885543Smrg}
45609885543Smrg
45709885543SmrgBool
45809885543SmrgSMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
45909885543Smrg		   char *src, int src_pitch)
46009885543Smrg{
46109885543Smrg    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
46209885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
46309885543Smrg    int i, j, dwords, Bpp, queue, dst_pitch;
46409885543Smrg    CARD32 *srcp, *dataport;
46509885543Smrg    unsigned long dst_offset;
46609885543Smrg
46709885543Smrg    ENTER_PROC("SMI_UploadToScreen");
46809885543Smrg    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d src=%d src_pitch=%d\n",
46909885543Smrg	   x, y, w, h, src, src_pitch));
47009885543Smrg
47109885543Smrg    /* calculate pitch in pixel unit */
47209885543Smrg    dst_pitch  = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3);
47309885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
47409885543Smrg    dst_offset = exaGetPixmapOffset(pDst) >> 3;
47509885543Smrg
47609885543Smrg    Bpp = pDst->drawable.bitsPerPixel / 8;
47709885543Smrg    dwords = (((w * Bpp) + 3) >> 2) * h;
47809885543Smrg
47909885543Smrg    pSmi->AccelCmd = 0xCC /* GXcopy */
48009885543Smrg		   | SMI_HOSTBLT_WRITE
48109885543Smrg		   | SMI_QUICK_START;
48209885543Smrg
48309885543Smrg
48409885543Smrg    WaitQueue(1);
48509885543Smrg    /* Destination Window Width */
48609885543Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16));
48709885543Smrg
48809885543Smrg    if (pDst->drawable.bitsPerPixel == 24) {
48909885543Smrg	x *= 3;
49009885543Smrg	w *= 3;
49109885543Smrg	dst_pitch *= 3;
49209885543Smrg	if (pSmi->Chipset == SMI_LYNX) {
49309885543Smrg	    y *= 3;
49409885543Smrg	}
49509885543Smrg    }
49609885543Smrg
49709885543Smrg    WaitQueue(9);
49809885543Smrg    /* Destination Row Pitch */
49909885543Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16));
50009885543Smrg    /* Drawing engine data format */
50109885543Smrg    WRITE_DPR(pSmi, 0x1C, SMI_DEDataFormat(pDst));
50209885543Smrg    /* Destination Base Address (offset) */
50309885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
50409885543Smrg
50509885543Smrg    /* set l/r clipping */
50609885543Smrg    WRITE_DPR(pSmi, 0x2C, (0xFFFF0000 | x | 0x2000));
50709885543Smrg    WRITE_DPR(pSmi, 0x30, (0xFFFF0000 | (x + w)));
50809885543Smrg
50909885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
51009885543Smrg    WRITE_DPR(pSmi, 0x00, 0);
51109885543Smrg    WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF));
51209885543Smrg    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
51309885543Smrg
51409885543Smrg
51509885543Smrg    srcp = (CARD32 *)src;
51609885543Smrg    dataport = (CARD32 *)pSmi->DataPortBase;
51709885543Smrg    queue = pSmi->DataPortSize;
51809885543Smrg    while (dwords) {
51909885543Smrg	if (queue < 4) {
52009885543Smrg	    /* XXX: check if the hw is ok with this */
52109885543Smrg	    dataport = (CARD32 *)pSmi->DataPortBase;
52209885543Smrg	    queue = pSmi->DataPortSize;
52309885543Smrg	}
52409885543Smrg	memcpy(dataport, srcp, 4);
52509885543Smrg	queue -= 4;
52609885543Smrg	dwords--;
52709885543Smrg	srcp++;
52809885543Smrg	dataport++;
52909885543Smrg    }
53009885543Smrg
53109885543Smrg    WaitQueue(1);
53209885543Smrg    /* disable clipping */
53309885543Smrg    WRITE_DPR(pSmi, 0x2C, 0);
53409885543Smrg
53509885543Smrg    exaWaitSync(pDst->drawable.pScreen);
53609885543Smrg
53709885543Smrg    LEAVE_PROC("SMI_UploadToScreen");
53809885543Smrg
53909885543Smrg    return TRUE;
54009885543Smrg}
54109885543Smrg
542