s3v_dga.c revision 1d54945d
11d54945dSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_dga.c,v 1.7 2002/01/14 18:02:58 dawes Exp $ */
21d54945dSmrg
31d54945dSmrg/*
41d54945dSmrgCopyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
51d54945dSmrg
61d54945dSmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
71d54945dSmrgthis software and associated documentation files (the "Software"), to deal in
81d54945dSmrgthe Software without restriction, including without limitation the rights to
91d54945dSmrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
101d54945dSmrgof the Software, and to permit persons to whom the Software is furnished to do
111d54945dSmrgso, subject to the following conditions:
121d54945dSmrg
131d54945dSmrgThe above copyright notice and this permission notice shall be included in all
141d54945dSmrgcopies or substantial portions of the Software.
151d54945dSmrg
161d54945dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171d54945dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
181d54945dSmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
191d54945dSmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
201d54945dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
211d54945dSmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
221d54945dSmrg
231d54945dSmrgExcept as contained in this notice, the name of the XFree86 Project shall not
241d54945dSmrgbe used in advertising or otherwise to promote the sale, use or other dealings
251d54945dSmrgin this Software without prior written authorization from the XFree86 Project.
261d54945dSmrg*/
271d54945dSmrg
281d54945dSmrg/*
291d54945dSmrgCopyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
301d54945dSmrg
311d54945dSmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
321d54945dSmrgthis software and associated documentation files (the "Software"), to deal in
331d54945dSmrgthe Software without restriction, including without limitation the rights to
341d54945dSmrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
351d54945dSmrgof the Software, and to permit persons to whom the Software is furnished to do
361d54945dSmrgso, subject to the following conditions:
371d54945dSmrg
381d54945dSmrgThe above copyright notice and this permission notice shall be included in all
391d54945dSmrgcopies or substantial portions of the Software.
401d54945dSmrg
411d54945dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
421d54945dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
431d54945dSmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
441d54945dSmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
451d54945dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
461d54945dSmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
471d54945dSmrg
481d54945dSmrgExcept as contained in this notice, the name of the XFree86 Project shall not
491d54945dSmrgbe used in advertising or otherwise to promote the sale, use or other dealings
501d54945dSmrgin this Software without prior written authorization from the XFree86 Project.
511d54945dSmrg*/
521d54945dSmrg
531d54945dSmrg/*
541d54945dSmrg * file: s3v_dga.c
551d54945dSmrg * ported from mga
561d54945dSmrg *
571d54945dSmrg */
581d54945dSmrg
591d54945dSmrg#ifdef HAVE_CONFIG_H
601d54945dSmrg#include "config.h"
611d54945dSmrg#endif
621d54945dSmrg
631d54945dSmrg#include "xf86.h"
641d54945dSmrg#include "xf86_OSproc.h"
651d54945dSmrg#include "xf86Pci.h"
661d54945dSmrg#include "xf86PciInfo.h"
671d54945dSmrg#include "xaa.h"
681d54945dSmrg#include "xaalocal.h"
691d54945dSmrg#include "s3v.h"
701d54945dSmrg#if 0
711d54945dSmrg#include "mga_bios.h"
721d54945dSmrg#include "mga.h"
731d54945dSmrg#include "mga_reg.h"
741d54945dSmrg#include "mga_macros.h"
751d54945dSmrg#endif
761d54945dSmrg#include "dgaproc.h"
771d54945dSmrg
781d54945dSmrg
791d54945dSmrgstatic Bool S3V_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
801d54945dSmrg					int *, int *, int *);
811d54945dSmrgstatic Bool S3V_SetMode(ScrnInfoPtr, DGAModePtr);
821d54945dSmrgstatic int  S3V_GetViewport(ScrnInfoPtr);
831d54945dSmrgstatic void S3V_SetViewport(ScrnInfoPtr, int, int, int);
841d54945dSmrgstatic void S3V_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
851d54945dSmrgstatic void S3V_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
861d54945dSmrg/* dummy... */
871d54945dSmrg#if 0
881d54945dSmrgstatic void MGA_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
891d54945dSmrg					unsigned long);
901d54945dSmrg#endif
911d54945dSmrg
921d54945dSmrgstatic
931d54945dSmrgDGAFunctionRec S3V_DGAFuncs = {
941d54945dSmrg   S3V_OpenFramebuffer,
951d54945dSmrg   NULL,
961d54945dSmrg   S3V_SetMode,
971d54945dSmrg   S3V_SetViewport,
981d54945dSmrg   S3V_GetViewport,
991d54945dSmrg   S3VAccelSync,
1001d54945dSmrg   S3V_FillRect,
1011d54945dSmrg   S3V_BlitRect,
1021d54945dSmrg   NULL
1031d54945dSmrg   /* dummy... MGA_BlitTransRect */
1041d54945dSmrg};
1051d54945dSmrg
1061d54945dSmrg
1071d54945dSmrgBool
1081d54945dSmrgS3VDGAInit(ScreenPtr pScreen)
1091d54945dSmrg{
1101d54945dSmrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1111d54945dSmrg   S3VPtr ps3v = S3VPTR(pScrn);
1121d54945dSmrg   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
1131d54945dSmrg   DisplayModePtr pMode, firstMode;
1141d54945dSmrg   int Bpp = pScrn->bitsPerPixel >> 3;
1151d54945dSmrg   int num = 0;
1161d54945dSmrg   Bool oneMore;
1171d54945dSmrg
1181d54945dSmrg   PVERB5("	S3VDGAInit\n");
1191d54945dSmrg
1201d54945dSmrg   pMode = firstMode = pScrn->modes;
1211d54945dSmrg
1221d54945dSmrg   while(pMode) {
1231d54945dSmrg	/* The MGA driver wasn't designed with switching depths in
1241d54945dSmrg	   mind.  Subsequently, large chunks of it will probably need
1251d54945dSmrg	   to be rewritten to accommodate depth changes in DGA mode */
1261d54945dSmrg
1271d54945dSmrg	if(0 /*pScrn->displayWidth != pMode->HDisplay*/) {
1281d54945dSmrg	    newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec));
1291d54945dSmrg	    oneMore = TRUE;
1301d54945dSmrg	} else {
1311d54945dSmrg	    newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
1321d54945dSmrg	    oneMore = FALSE;
1331d54945dSmrg	}
1341d54945dSmrg
1351d54945dSmrg	if(!newmodes) {
1361d54945dSmrg	   xfree(modes);
1371d54945dSmrg	   return FALSE;
1381d54945dSmrg	}
1391d54945dSmrg	modes = newmodes;
1401d54945dSmrg
1411d54945dSmrgSECOND_PASS:
1421d54945dSmrg
1431d54945dSmrg	currentMode = modes + num;
1441d54945dSmrg	num++;
1451d54945dSmrg
1461d54945dSmrg	currentMode->mode = pMode;
1471d54945dSmrg	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1481d54945dSmrg	if(!ps3v->NoAccel)
1491d54945dSmrg	   currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
1501d54945dSmrg	if(pMode->Flags & V_DBLSCAN)
1511d54945dSmrg	   currentMode->flags |= DGA_DOUBLESCAN;
1521d54945dSmrg	if(pMode->Flags & V_INTERLACE)
1531d54945dSmrg	   currentMode->flags |= DGA_INTERLACED;
1541d54945dSmrg	currentMode->byteOrder = pScrn->imageByteOrder;
1551d54945dSmrg	currentMode->depth = pScrn->depth;
1561d54945dSmrg	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
1571d54945dSmrg	currentMode->red_mask = pScrn->mask.red;
1581d54945dSmrg	currentMode->green_mask = pScrn->mask.green;
1591d54945dSmrg	currentMode->blue_mask = pScrn->mask.blue;
1601d54945dSmrg	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
1611d54945dSmrg	currentMode->viewportWidth = pMode->HDisplay;
1621d54945dSmrg	currentMode->viewportHeight = pMode->VDisplay;
1631d54945dSmrg	/* currentMode->xViewportStep = (3 - ps3v->BppShift); */
1641d54945dSmrg				/* always 1 on ViRGE ? */
1651d54945dSmrg	currentMode->xViewportStep = 1;
1661d54945dSmrg	currentMode->yViewportStep = 1;
1671d54945dSmrg	currentMode->viewportFlags = DGA_FLIP_RETRACE;
1681d54945dSmrg	/* currentMode->offset = ps3v->YDstOrg * (pScrn->bitsPerPixel / 8);
1691d54945dSmrg	 * MGA, 0 for ViRGE */
1701d54945dSmrg	currentMode->offset = 0;
1711d54945dSmrg	/* currentMode->address = pMga->FbStart;   MGA */
1721d54945dSmrg	currentMode->address = ps3v->FBBase;
1731d54945dSmrg/*cep*/
1741d54945dSmrg  xf86ErrorFVerb(VERBLEV,
1751d54945dSmrg	"	S3VDGAInit firstone vpWid=%d, vpHgt=%d, Bpp=%d, mdbitsPP=%d\n",
1761d54945dSmrg		currentMode->viewportWidth,
1771d54945dSmrg		currentMode->viewportHeight,
1781d54945dSmrg		Bpp,
1791d54945dSmrg		currentMode->bitsPerPixel
1801d54945dSmrg		 );
1811d54945dSmrg
1821d54945dSmrg
1831d54945dSmrg	if(oneMore) { /* first one is narrow width */
1841d54945dSmrg	    currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L;
1851d54945dSmrg	    currentMode->imageWidth = pMode->HDisplay;
1861d54945dSmrg	    /* currentMode->imageHeight =  pMga->FbUsableSize /
1871d54945dSmrg					currentMode->bytesPerScanline;
1881d54945dSmrg					MGA above */
1891d54945dSmrg	    currentMode->imageHeight =  pMode->VDisplay;
1901d54945dSmrg	    currentMode->pixmapWidth = currentMode->imageWidth;
1911d54945dSmrg	    currentMode->pixmapHeight = currentMode->imageHeight;
1921d54945dSmrg	    currentMode->maxViewportX = currentMode->imageWidth -
1931d54945dSmrg					currentMode->viewportWidth;
1941d54945dSmrg	    /* this might need to get clamped to some maximum */
1951d54945dSmrg	    currentMode->maxViewportY = currentMode->imageHeight -
1961d54945dSmrg					currentMode->viewportHeight;
1971d54945dSmrg	    oneMore = FALSE;
1981d54945dSmrg
1991d54945dSmrg/*cep*/
2001d54945dSmrg  xf86ErrorFVerb(VERBLEV,
2011d54945dSmrg	"	S3VDGAInit imgHgt=%d, ram=%d, bytesPerScanl=%d\n",
2021d54945dSmrg		currentMode->imageHeight,
2031d54945dSmrg		ps3v->videoRambytes,
2041d54945dSmrg		currentMode->bytesPerScanline );
2051d54945dSmrg
2061d54945dSmrg	    goto SECOND_PASS;
2071d54945dSmrg	} else {
2081d54945dSmrg	    currentMode->bytesPerScanline =
2091d54945dSmrg			((pScrn->displayWidth * Bpp) + 3) & ~3L;
2101d54945dSmrg	    currentMode->imageWidth = pScrn->displayWidth;
2111d54945dSmrg	    /* currentMode->imageHeight =  pMga->FbUsableSize /
2121d54945dSmrg					currentMode->bytesPerScanline;
2131d54945dSmrg					*/
2141d54945dSmrg	    currentMode->imageHeight =  ps3v->videoRambytes /
2151d54945dSmrg	    			currentMode->bytesPerScanline;
2161d54945dSmrg	    currentMode->pixmapWidth = currentMode->imageWidth;
2171d54945dSmrg	    currentMode->pixmapHeight = currentMode->imageHeight;
2181d54945dSmrg	    currentMode->maxViewportX = currentMode->imageWidth -
2191d54945dSmrg					currentMode->viewportWidth;
2201d54945dSmrg	    /* this might need to get clamped to some maximum */
2211d54945dSmrg	    currentMode->maxViewportY = currentMode->imageHeight -
2221d54945dSmrg					currentMode->viewportHeight;
2231d54945dSmrg	}
2241d54945dSmrg
2251d54945dSmrg	pMode = pMode->next;
2261d54945dSmrg	if(pMode == firstMode)
2271d54945dSmrg	   break;
2281d54945dSmrg   }
2291d54945dSmrg
2301d54945dSmrg   ps3v->numDGAModes = num;
2311d54945dSmrg   ps3v->DGAModes = modes;
2321d54945dSmrg
2331d54945dSmrg   return DGAInit(pScreen, &S3V_DGAFuncs, modes, num);
2341d54945dSmrg}
2351d54945dSmrg
2361d54945dSmrg
2371d54945dSmrgstatic Bool
2381d54945dSmrgS3V_SetMode(
2391d54945dSmrg   ScrnInfoPtr pScrn,
2401d54945dSmrg   DGAModePtr pMode
2411d54945dSmrg){
2421d54945dSmrg   static int OldDisplayWidth[MAXSCREENS];
2431d54945dSmrg   int index = pScrn->pScreen->myNum;
2441d54945dSmrg
2451d54945dSmrg   S3VPtr ps3v = S3VPTR(pScrn);
2461d54945dSmrg
2471d54945dSmrg   if(!pMode) { /* restore the original mode */
2481d54945dSmrg	/* put the ScreenParameters back */
2491d54945dSmrg
2501d54945dSmrg	pScrn->displayWidth = OldDisplayWidth[index];
2511d54945dSmrg
2521d54945dSmrg        S3VSwitchMode(index, pScrn->currentMode, 0);
2531d54945dSmrg	ps3v->DGAactive = FALSE;
2541d54945dSmrg   } else {
2551d54945dSmrg	if(!ps3v->DGAactive) {  /* save the old parameters */
2561d54945dSmrg	    OldDisplayWidth[index] = pScrn->displayWidth;
2571d54945dSmrg
2581d54945dSmrg	    ps3v->DGAactive = TRUE;
2591d54945dSmrg	}
2601d54945dSmrg
2611d54945dSmrg	pScrn->displayWidth = pMode->bytesPerScanline /
2621d54945dSmrg			      (pMode->bitsPerPixel >> 3);
2631d54945dSmrg
2641d54945dSmrg        S3VSwitchMode(index, pMode->mode, 0);
2651d54945dSmrg   }
2661d54945dSmrg
2671d54945dSmrg   return TRUE;
2681d54945dSmrg}
2691d54945dSmrg
2701d54945dSmrg
2711d54945dSmrg
2721d54945dSmrgstatic int
2731d54945dSmrgS3V_GetViewport(
2741d54945dSmrg  ScrnInfoPtr pScrn
2751d54945dSmrg){
2761d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
2771d54945dSmrg
2781d54945dSmrg    return ps3v->DGAViewportStatus;
2791d54945dSmrg}
2801d54945dSmrg
2811d54945dSmrgstatic void
2821d54945dSmrgS3V_SetViewport(
2831d54945dSmrg   ScrnInfoPtr pScrn,
2841d54945dSmrg   int x, int y,
2851d54945dSmrg   int flags
2861d54945dSmrg){
2871d54945dSmrg   S3VPtr ps3v = S3VPTR(pScrn);
2881d54945dSmrg
2891d54945dSmrg   S3VAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
2901d54945dSmrg   ps3v->DGAViewportStatus = 0;  /* MGAAdjustFrame loops until finished */
2911d54945dSmrg}
2921d54945dSmrg
2931d54945dSmrgstatic void
2941d54945dSmrgS3V_FillRect (
2951d54945dSmrg   ScrnInfoPtr pScrn,
2961d54945dSmrg   int x, int y, int w, int h,
2971d54945dSmrg   unsigned long color
2981d54945dSmrg){
2991d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
3001d54945dSmrg
3011d54945dSmrg    if(ps3v->AccelInfoRec) {
3021d54945dSmrg	(*ps3v->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
3031d54945dSmrg	(*ps3v->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
3041d54945dSmrg	SET_SYNC_FLAG(ps3v->AccelInfoRec);
3051d54945dSmrg    }
3061d54945dSmrg}
3071d54945dSmrg
3081d54945dSmrgstatic void
3091d54945dSmrgS3V_BlitRect(
3101d54945dSmrg   ScrnInfoPtr pScrn,
3111d54945dSmrg   int srcx, int srcy,
3121d54945dSmrg   int w, int h,
3131d54945dSmrg   int dstx, int dsty
3141d54945dSmrg){
3151d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
3161d54945dSmrg
3171d54945dSmrg    if(ps3v->AccelInfoRec) {
3181d54945dSmrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
3191d54945dSmrg	int ydir = (srcy < dsty) ? -1 : 1;
3201d54945dSmrg
3211d54945dSmrg	(*ps3v->AccelInfoRec->SetupForScreenToScreenCopy)(
3221d54945dSmrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
3231d54945dSmrg	(*ps3v->AccelInfoRec->SubsequentScreenToScreenCopy)(
3241d54945dSmrg		pScrn, srcx, srcy, dstx, dsty, w, h);
3251d54945dSmrg	SET_SYNC_FLAG(ps3v->AccelInfoRec);
3261d54945dSmrg    }
3271d54945dSmrg}
3281d54945dSmrg
3291d54945dSmrg#if 0
3301d54945dSmrgstatic void
3311d54945dSmrgMGA_BlitTransRect(
3321d54945dSmrg   ScrnInfoPtr pScrn,
3331d54945dSmrg   int srcx, int srcy,
3341d54945dSmrg   int w, int h,
3351d54945dSmrg   int dstx, int dsty,
3361d54945dSmrg   unsigned long color
3371d54945dSmrg){
3381d54945dSmrg  /* this one should be separate since the XAA function would
3391d54945dSmrg     prohibit usage of ~0 as the key */
3401d54945dSmrg}
3411d54945dSmrg#endif
3421d54945dSmrg
3431d54945dSmrgstatic Bool
3441d54945dSmrgS3V_OpenFramebuffer(
3451d54945dSmrg   ScrnInfoPtr pScrn,
3461d54945dSmrg   char **name,
3471d54945dSmrg   unsigned char **mem,
3481d54945dSmrg   int *size,
3491d54945dSmrg   int *offset,
3501d54945dSmrg   int *flags
3511d54945dSmrg){
3521d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
3531d54945dSmrg
3541d54945dSmrg    *name = NULL; 		/* no special device */
3551d54945dSmrg    *mem = (unsigned char*)ps3v->PciInfo->memBase[0];
3561d54945dSmrg    *size = ps3v->videoRambytes;
3571d54945dSmrg    *offset = 0;
3581d54945dSmrg    *flags = DGA_NEED_ROOT;
3591d54945dSmrg
3601d54945dSmrg    return TRUE;
3611d54945dSmrg}
362