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