176888252Smrg/*
276888252Smrg * Copyright 2000 by Egbert Eich
376888252Smrg *
476888252Smrg * Permission to use, copy, modify, distribute, and sell this software and its
576888252Smrg * documentation for any purpose is hereby granted without fee, provided that
676888252Smrg * the above copyright notice appear in all copies and that both that
776888252Smrg * copyright notice and this permission notice appear in supporting
876888252Smrg * documentation, and that the name of Alan Hourihane not be used in
976888252Smrg * advertising or publicity pertaining to distribution of the software without
1076888252Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1176888252Smrg * about the suitability of this software for any purpose.  It is provided
1276888252Smrg * "as is" without express or implied warranty.
1376888252Smrg *
1476888252Smrg * EGBERT EICH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1576888252Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1676888252Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1776888252Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1876888252Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1976888252Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2076888252Smrg * PERFORMANCE OF THIS SOFTWARE.
2176888252Smrg *
2276888252Smrg * Authors:  Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
2376888252Smrg *           by: Egbert Eich
2476888252Smrg */
2576888252Smrg
2676888252Smrg#ifdef HAVE_CONFIG_H
2776888252Smrg#include "config.h"
2876888252Smrg#endif
2976888252Smrg
3076888252Smrg#include "xf86.h"
3176888252Smrg#include "xf86_OSproc.h"
3276888252Smrg#include "xf86Pci.h"
3363847c39Smrg#ifdef HAVE_XAA_H
3476888252Smrg#include "xaa.h"
3576888252Smrg#include "xaalocal.h"
3663847c39Smrg#endif
3776888252Smrg#include "vgaHW.h"
3876888252Smrg#include "cir.h"
3976888252Smrg#include "dgaproc.h"
4076888252Smrg
4176888252Smrgstatic Bool Cir_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
4276888252Smrg				  int *, int *, int *);
4376888252Smrgstatic Bool Cir_SetMode(ScrnInfoPtr, DGAModePtr);
4476888252Smrgstatic int  Cir_GetViewport(ScrnInfoPtr);
4576888252Smrgstatic void Cir_SetViewport(ScrnInfoPtr, int, int, int);
4663847c39Smrg#ifdef HAVE_XAA_H
4763847c39Smrgstatic void Cir_Sync(ScrnInfoPtr);
4876888252Smrgstatic void Cir_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
4976888252Smrgstatic void Cir_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
5076888252Smrg/*
5176888252Smrgstatic void Cir_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
5276888252Smrg                                unsigned long);
5376888252Smrg*/
5463847c39Smrg#endif
5576888252Smrg
5676888252Smrgstatic
5776888252SmrgDGAFunctionRec CirDGAFuncs = {
5876888252Smrg   Cir_OpenFramebuffer,
5976888252Smrg   NULL, /* Cir_CloseFramebuffer */
6076888252Smrg   Cir_SetMode,
6176888252Smrg   Cir_SetViewport,
6276888252Smrg   Cir_GetViewport,
6363847c39Smrg#ifdef HAVE_XAA_H
6476888252Smrg   Cir_Sync,
6576888252Smrg   Cir_FillRect,
6676888252Smrg   Cir_BlitRect,
6763847c39Smrg#else
6863847c39Smrg   NULL, NULL, NULL,
6963847c39Smrg#endif
7076888252Smrg   NULL  /* Cir_BlitTransRect */
7176888252Smrg};
7276888252Smrg
7376888252Smrg
7476888252Smrg
7576888252Smrg
761ae1b5e8Smrg_X_EXPORT Bool
7776888252SmrgCirDGAInit(ScreenPtr pScreen)
7876888252Smrg{
7963847c39Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
8076888252Smrg  CirPtr pCir = CIRPTR(pScrn);
8176888252Smrg  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
8276888252Smrg  DisplayModePtr pMode, firstMode;
8376888252Smrg  int Bpp = pScrn->bitsPerPixel >> 3;
8476888252Smrg  int num = 0;
8576888252Smrg  int imlines =  (pScrn->videoRam * 1024) /
8676888252Smrg       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
8776888252Smrg
8876888252Smrg
8976888252Smrg  if (!pCir->DGAnumModes) {
9076888252Smrg    pMode = firstMode = pScrn->modes;
9176888252Smrg    while (pMode) {
9263847c39Smrg      newmodes = realloc(modes, (num + 1) * sizeof (DGAModeRec));
9376888252Smrg      if (!newmodes) {
9463847c39Smrg	free(modes);
9576888252Smrg	return FALSE;
9676888252Smrg      }
9776888252Smrg      modes = newmodes;
9876888252Smrg      currentMode = modes + num;
9976888252Smrg      num++;
10076888252Smrg      (void)memset(currentMode, 1, sizeof(DGAModeRec));
10176888252Smrg      currentMode->mode = pMode;
10276888252Smrg      currentMode->flags = DGA_PIXMAP_AVAILABLE
10376888252Smrg	  | ((!pCir->NoAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
10476888252Smrg      if (pMode->Flags & V_DBLSCAN)
10576888252Smrg	currentMode->flags |= DGA_DOUBLESCAN;
10676888252Smrg      if(pMode->Flags & V_INTERLACE)
10776888252Smrg	currentMode->flags |= DGA_INTERLACED;
10876888252Smrg      currentMode->byteOrder        = pScrn->imageByteOrder;
10976888252Smrg      currentMode->depth            = pScrn->depth;
11076888252Smrg      currentMode->bitsPerPixel     = pScrn->bitsPerPixel;
11176888252Smrg      currentMode->red_mask         = pScrn->mask.red;
11276888252Smrg      currentMode->green_mask       = pScrn->mask.green;
11376888252Smrg      currentMode->blue_mask        = pScrn->mask.blue;
11476888252Smrg      currentMode->visualClass      = (Bpp == 1) ? PseudoColor : TrueColor;
11576888252Smrg      currentMode->viewportWidth    = pMode->HDisplay;
11676888252Smrg      currentMode->viewportHeight   = pMode->VDisplay;
11776888252Smrg      currentMode->xViewportStep    = 1; /*  The granularity of x and y pos. */
11876888252Smrg      currentMode->yViewportStep    = 1;
11976888252Smrg      currentMode->viewportFlags    = 0 /*DGA_FLIP_RETRACE*/;
12076888252Smrg      currentMode->offset           = 0;
12176888252Smrg      currentMode->address          = pCir->FbBase;
12276888252Smrg      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
12376888252Smrg      currentMode->pixmapWidth      = currentMode->imageWidth
12476888252Smrg	                               = pScrn->displayWidth;
12576888252Smrg      currentMode->pixmapHeight     = currentMode->imageHeight = imlines;
12676888252Smrg      currentMode->maxViewportX     = currentMode->imageWidth -
12776888252Smrg                                      currentMode->viewportWidth;
12876888252Smrg      /* this might need to get clamped to some maximum */
12976888252Smrg      currentMode->maxViewportY     = currentMode->imageHeight -
13076888252Smrg                                      currentMode->viewportHeight;
13176888252Smrg
13276888252Smrg      pMode = pMode->next;
13376888252Smrg      if(pMode == firstMode)
13476888252Smrg	break;
13576888252Smrg    }
13676888252Smrg    pCir->DGAnumModes = num;
13776888252Smrg    pCir->DGAModes = modes;
13876888252Smrg  }
13976888252Smrg  return DGAInit(pScreen, &CirDGAFuncs, pCir->DGAModes, pCir->DGAnumModes);
14076888252Smrg}
14176888252Smrg
14276888252Smrgstatic Bool
14376888252SmrgCir_OpenFramebuffer(
14476888252Smrg   ScrnInfoPtr pScrn,
14576888252Smrg   char **name,
14676888252Smrg   unsigned char **mem,
14776888252Smrg   int *size,
14876888252Smrg   int *offset,
14976888252Smrg   int *flags
15076888252Smrg){
15176888252Smrg    CirPtr pCir = CIRPTR(pScrn);
15276888252Smrg
15376888252Smrg    *name = NULL; 		/* no special device */
15476888252Smrg    *mem = (unsigned char*)(long)pCir->FbAddress;
15576888252Smrg    *size = pCir->FbMapSize;
15676888252Smrg    *offset = 0;                /* Always */
15776888252Smrg    *flags = 0;                 /* Root permissions OS-dependent */
15876888252Smrg
15976888252Smrg    return TRUE;
16076888252Smrg}
16176888252Smrg
16276888252Smrg
16376888252Smrgstatic Bool
16476888252SmrgCir_SetMode(
16576888252Smrg   ScrnInfoPtr pScrn,
16676888252Smrg   DGAModePtr pMode
16776888252Smrg){
16876888252Smrg   CirPtr pCir = CIRPTR(pScrn);
16976888252Smrg   static int OldDisplayWidth[MAXSCREENS];
17076888252Smrg   int index = pScrn->pScreen->myNum;
17176888252Smrg   Bool ret = FALSE;
17276888252Smrg
17376888252Smrg   if(!pMode) { /* restore the original mode */
17476888252Smrg	/* put the ScreenParameters back */
17576888252Smrg	pScrn->displayWidth = OldDisplayWidth[index];
17676888252Smrg	ret = pCir->DGAModeInit(xf86Screens[index], pScrn->currentMode);
17776888252Smrg	pCir->DGAactive = FALSE;
17876888252Smrg   } else {
17976888252Smrg	if(!pCir->DGAactive) {  /* save the old parameters */
18076888252Smrg	    OldDisplayWidth[index] = pScrn->displayWidth;
18176888252Smrg
18276888252Smrg	    pCir->DGAactive = TRUE;
18376888252Smrg	}
18476888252Smrg	pScrn->displayWidth = pMode->bytesPerScanline /
18576888252Smrg			      (pMode->bitsPerPixel >> 3);
18676888252Smrg
18776888252Smrg	ret = pCir->DGAModeInit(xf86Screens[index], pMode->mode);
18876888252Smrg   }
18976888252Smrg   return ret;
19076888252Smrg}
19176888252Smrg
19276888252Smrgstatic void
19376888252SmrgCir_SetViewport(
19476888252Smrg   ScrnInfoPtr pScrn,
19576888252Smrg   int x, int y,
19676888252Smrg   int flags
19776888252Smrg){
19876888252Smrg   CirPtr pCir = CIRPTR(pScrn);
19976888252Smrg   vgaHWPtr hwp = VGAHWPTR(pScrn);
20076888252Smrg
20163847c39Smrg   pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
20276888252Smrg
20376888252Smrg   while((hwp->readST01(hwp) & 0x08));
20476888252Smrg   while(!(hwp->readST01(hwp) & 0x08));
20576888252Smrg
20676888252Smrg   pCir->DGAViewportStatus = 0;  /* AdjustFrame loops until finished */
20776888252Smrg}
20876888252Smrg
20976888252Smrgstatic int
21076888252SmrgCir_GetViewport(
21176888252Smrg  ScrnInfoPtr pScrn
21276888252Smrg){
21376888252Smrg    CirPtr pCir = CIRPTR(pScrn);
21476888252Smrg
21576888252Smrg    return pCir->DGAViewportStatus;
21676888252Smrg}
21776888252Smrg
21863847c39Smrg#ifdef HAVE_XAA_H
21976888252Smrgstatic void
22076888252SmrgCir_Sync(
22176888252Smrg   ScrnInfoPtr pScrn
22276888252Smrg){
22376888252Smrg    CirPtr pCir = CIRPTR(pScrn);
22476888252Smrg    if(pCir->AccelInfoRec) {
22576888252Smrg	(*pCir->AccelInfoRec->Sync)(pScrn);
22676888252Smrg    }
22776888252Smrg}
22876888252Smrg
22976888252Smrgstatic void
23076888252SmrgCir_FillRect (
23176888252Smrg   ScrnInfoPtr pScrn,
23276888252Smrg   int x, int y, int w, int h,
23376888252Smrg   unsigned long color
23476888252Smrg){
23576888252Smrg    CirPtr pCir = CIRPTR(pScrn);
23676888252Smrg
23776888252Smrg    if(pCir->AccelInfoRec) {
23876888252Smrg	(*pCir->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
23976888252Smrg	(*pCir->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
24076888252Smrg	SET_SYNC_FLAG(pCir->AccelInfoRec);
24176888252Smrg    }
24276888252Smrg}
24376888252Smrg
24476888252Smrgstatic void
24576888252SmrgCir_BlitRect(
24676888252Smrg   ScrnInfoPtr pScrn,
24776888252Smrg   int srcx, int srcy,
24876888252Smrg   int w, int h,
24976888252Smrg   int dstx, int dsty
25076888252Smrg){
25176888252Smrg    CirPtr pCir = CIRPTR(pScrn);
25276888252Smrg
25376888252Smrg    if(pCir->AccelInfoRec) {
25476888252Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
25576888252Smrg	int ydir = (srcy < dsty) ? -1 : 1;
25676888252Smrg
25776888252Smrg	(*pCir->AccelInfoRec->SetupForScreenToScreenCopy)(
25876888252Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
25976888252Smrg	(*pCir->AccelInfoRec->SubsequentScreenToScreenCopy)(
26076888252Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
26176888252Smrg	SET_SYNC_FLAG(pCir->AccelInfoRec);
26276888252Smrg    }
26376888252Smrg}
26463847c39Smrg#endif
265