1/*
2 * Copyright 2000 by Egbert Eich
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * EGBERT EICH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors:  Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *           by: Egbert Eich
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "xf86.h"
31#include "xf86_OSproc.h"
32#include "xf86Pci.h"
33#ifdef HAVE_XAA_H
34#include "xaa.h"
35#include "xaalocal.h"
36#endif
37#include "vgaHW.h"
38#include "cir.h"
39#include "dgaproc.h"
40
41static Bool Cir_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
42				  int *, int *, int *);
43static Bool Cir_SetMode(ScrnInfoPtr, DGAModePtr);
44static int  Cir_GetViewport(ScrnInfoPtr);
45static void Cir_SetViewport(ScrnInfoPtr, int, int, int);
46#ifdef HAVE_XAA_H
47static void Cir_Sync(ScrnInfoPtr);
48static void Cir_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
49static void Cir_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
50/*
51static void Cir_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
52                                unsigned long);
53*/
54#endif
55
56static
57DGAFunctionRec CirDGAFuncs = {
58   Cir_OpenFramebuffer,
59   NULL, /* Cir_CloseFramebuffer */
60   Cir_SetMode,
61   Cir_SetViewport,
62   Cir_GetViewport,
63#ifdef HAVE_XAA_H
64   Cir_Sync,
65   Cir_FillRect,
66   Cir_BlitRect,
67#else
68   NULL, NULL, NULL,
69#endif
70   NULL  /* Cir_BlitTransRect */
71};
72
73
74
75
76_X_EXPORT Bool
77CirDGAInit(ScreenPtr pScreen)
78{
79  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
80  CirPtr pCir = CIRPTR(pScrn);
81  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
82  DisplayModePtr pMode, firstMode;
83  int Bpp = pScrn->bitsPerPixel >> 3;
84  int num = 0;
85  int imlines =  (pScrn->videoRam * 1024) /
86       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
87
88
89  if (!pCir->DGAnumModes) {
90    pMode = firstMode = pScrn->modes;
91    while (pMode) {
92      newmodes = realloc(modes, (num + 1) * sizeof (DGAModeRec));
93      if (!newmodes) {
94	free(modes);
95	return FALSE;
96      }
97      modes = newmodes;
98      currentMode = modes + num;
99      num++;
100      (void)memset(currentMode, 1, sizeof(DGAModeRec));
101      currentMode->mode = pMode;
102      currentMode->flags = DGA_PIXMAP_AVAILABLE
103	  | ((!pCir->NoAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
104      if (pMode->Flags & V_DBLSCAN)
105	currentMode->flags |= DGA_DOUBLESCAN;
106      if(pMode->Flags & V_INTERLACE)
107	currentMode->flags |= DGA_INTERLACED;
108      currentMode->byteOrder        = pScrn->imageByteOrder;
109      currentMode->depth            = pScrn->depth;
110      currentMode->bitsPerPixel     = pScrn->bitsPerPixel;
111      currentMode->red_mask         = pScrn->mask.red;
112      currentMode->green_mask       = pScrn->mask.green;
113      currentMode->blue_mask        = pScrn->mask.blue;
114      currentMode->visualClass      = (Bpp == 1) ? PseudoColor : TrueColor;
115      currentMode->viewportWidth    = pMode->HDisplay;
116      currentMode->viewportHeight   = pMode->VDisplay;
117      currentMode->xViewportStep    = 1; /*  The granularity of x and y pos. */
118      currentMode->yViewportStep    = 1;
119      currentMode->viewportFlags    = 0 /*DGA_FLIP_RETRACE*/;
120      currentMode->offset           = 0;
121      currentMode->address          = pCir->FbBase;
122      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
123      currentMode->pixmapWidth      = currentMode->imageWidth
124	                               = pScrn->displayWidth;
125      currentMode->pixmapHeight     = currentMode->imageHeight = imlines;
126      currentMode->maxViewportX     = currentMode->imageWidth -
127                                      currentMode->viewportWidth;
128      /* this might need to get clamped to some maximum */
129      currentMode->maxViewportY     = currentMode->imageHeight -
130                                      currentMode->viewportHeight;
131
132      pMode = pMode->next;
133      if(pMode == firstMode)
134	break;
135    }
136    pCir->DGAnumModes = num;
137    pCir->DGAModes = modes;
138  }
139  return DGAInit(pScreen, &CirDGAFuncs, pCir->DGAModes, pCir->DGAnumModes);
140}
141
142static Bool
143Cir_OpenFramebuffer(
144   ScrnInfoPtr pScrn,
145   char **name,
146   unsigned char **mem,
147   int *size,
148   int *offset,
149   int *flags
150){
151    CirPtr pCir = CIRPTR(pScrn);
152
153    *name = NULL; 		/* no special device */
154    *mem = (unsigned char*)(long)pCir->FbAddress;
155    *size = pCir->FbMapSize;
156    *offset = 0;                /* Always */
157    *flags = 0;                 /* Root permissions OS-dependent */
158
159    return TRUE;
160}
161
162
163static Bool
164Cir_SetMode(
165   ScrnInfoPtr pScrn,
166   DGAModePtr pMode
167){
168   CirPtr pCir = CIRPTR(pScrn);
169   static int OldDisplayWidth[MAXSCREENS];
170   int index = pScrn->pScreen->myNum;
171   Bool ret = FALSE;
172
173   if(!pMode) { /* restore the original mode */
174	/* put the ScreenParameters back */
175	pScrn->displayWidth = OldDisplayWidth[index];
176	ret = pCir->DGAModeInit(xf86Screens[index], pScrn->currentMode);
177	pCir->DGAactive = FALSE;
178   } else {
179	if(!pCir->DGAactive) {  /* save the old parameters */
180	    OldDisplayWidth[index] = pScrn->displayWidth;
181
182	    pCir->DGAactive = TRUE;
183	}
184	pScrn->displayWidth = pMode->bytesPerScanline /
185			      (pMode->bitsPerPixel >> 3);
186
187	ret = pCir->DGAModeInit(xf86Screens[index], pMode->mode);
188   }
189   return ret;
190}
191
192static void
193Cir_SetViewport(
194   ScrnInfoPtr pScrn,
195   int x, int y,
196   int flags
197){
198   CirPtr pCir = CIRPTR(pScrn);
199   vgaHWPtr hwp = VGAHWPTR(pScrn);
200
201   pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
202
203   while((hwp->readST01(hwp) & 0x08));
204   while(!(hwp->readST01(hwp) & 0x08));
205
206   pCir->DGAViewportStatus = 0;  /* AdjustFrame loops until finished */
207}
208
209static int
210Cir_GetViewport(
211  ScrnInfoPtr pScrn
212){
213    CirPtr pCir = CIRPTR(pScrn);
214
215    return pCir->DGAViewportStatus;
216}
217
218#ifdef HAVE_XAA_H
219static void
220Cir_Sync(
221   ScrnInfoPtr pScrn
222){
223    CirPtr pCir = CIRPTR(pScrn);
224    if(pCir->AccelInfoRec) {
225	(*pCir->AccelInfoRec->Sync)(pScrn);
226    }
227}
228
229static void
230Cir_FillRect (
231   ScrnInfoPtr pScrn,
232   int x, int y, int w, int h,
233   unsigned long color
234){
235    CirPtr pCir = CIRPTR(pScrn);
236
237    if(pCir->AccelInfoRec) {
238	(*pCir->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
239	(*pCir->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
240	SET_SYNC_FLAG(pCir->AccelInfoRec);
241    }
242}
243
244static void
245Cir_BlitRect(
246   ScrnInfoPtr pScrn,
247   int srcx, int srcy,
248   int w, int h,
249   int dstx, int dsty
250){
251    CirPtr pCir = CIRPTR(pScrn);
252
253    if(pCir->AccelInfoRec) {
254	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
255	int ydir = (srcy < dsty) ? -1 : 1;
256
257	(*pCir->AccelInfoRec->SetupForScreenToScreenCopy)(
258		pScrn, xdir, ydir, GXcopy, ~0, -1);
259	(*pCir->AccelInfoRec->SubsequentScreenToScreenCopy)(
260		pScrn, srcx, srcy, dstx, dsty, w, h);
261	SET_SYNC_FLAG(pCir->AccelInfoRec);
262    }
263}
264#endif
265