1 /*
2  * file: apm_dga.c
3  * ported from s3virge, ported from mga
4  *
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "xf86.h"
12 #include "xf86_OSproc.h"
13 #include "xf86Pci.h"
14 #include "apm.h"
15 #include "dgaproc.h"
16 
17 
18 static Bool ApmOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
19 					int *, int *, int *);
20 static Bool ApmSetMode(ScrnInfoPtr, DGAModePtr);
21 static int  ApmGetViewport(ScrnInfoPtr);
22 static void ApmSetViewport(ScrnInfoPtr, int, int, int);
23 #ifdef HAVE_XAA_H
24 static void ApmFillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
25 static void ApmBlitRect(ScrnInfoPtr, int, int, int, int, int, int);
26 static void ApmBlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
27 					unsigned long);
28 #endif
29 static void ApmSync(ScrnInfoPtr);
30 
31 static
32 DGAFunctionRec ApmDGAFuncs = {
33     ApmOpenFramebuffer,
34     NULL,
35     ApmSetMode,
36     ApmSetViewport,
37     ApmGetViewport,
38     ApmSync,
39 #ifdef HAVE_XAA_H
40     ApmFillRect,
41     ApmBlitRect,
42     ApmBlitTransRect
43 #else
44     NULL, NULL, NULL
45 #endif
46 };
47 
48 /*
49  * Placeholder
50  */
51 void
ApmSync(ScrnInfoPtr pScrn)52 ApmSync(ScrnInfoPtr pScrn)
53 {
54 }
55 
FindSmallestPitch(ApmPtr pApm,int Bpp,int width)56 static __inline__ int FindSmallestPitch(ApmPtr pApm, int Bpp, int width)
57 {
58     if (width <= 640)
59 	return 640;
60     else if (width <= 800)
61 	return 800;
62     else if (width <= 1024)
63 	return 1024;
64     else if (width <= 1152)
65 	return 1152;
66     else if (width <= 1280)
67 	return 1280;
68     else if (width <= 1600)
69 	return 1600;
70     return (width + 7) & ~7;
71 }
72 
73 static DGAModePtr
ApmSetupDGAMode(ScrnInfoPtr pScrn,DGAModePtr modes,int * num,int bitsPerPixel,int depth,Bool pixmap,int secondPitch,unsigned long red,unsigned long green,unsigned long blue,short visualClass)74 ApmSetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, int *num,
75 		   int bitsPerPixel, int depth, Bool pixmap, int secondPitch,
76 		   unsigned long red, unsigned long green, unsigned long blue,
77 		   short visualClass)
78 {
79    DisplayModePtr firstMode, pMode;
80    APMDECL(pScrn);
81    DGAModePtr mode, newmodes;
82    int size, pitch, Bpp = bitsPerPixel >> 3;
83    Bool reduced_pitch = TRUE;
84 
85 SECOND_PASS:
86 
87    firstMode = NULL;
88 
89    for (pMode = pScrn->modes; pMode != firstMode; pMode = pMode->next) {
90 
91 	if (!firstMode)
92 	    firstMode = pMode;
93 
94 	if (reduced_pitch)
95 	    pitch = FindSmallestPitch(pApm, Bpp, pMode->HDisplay);
96 	else
97 	    pitch = pMode->HDisplay;
98 	if (!reduced_pitch && pitch == FindSmallestPitch(pApm, Bpp, pMode->HDisplay))
99 	    continue;
100 
101 	size = pitch * Bpp * pMode->VDisplay;
102 
103 	if((!secondPitch || (pitch != secondPitch)) &&
104 		(size <= pScrn->videoRam * 1024 - pApm->OffscreenReserved)) {
105 
106 	    if(secondPitch)
107 		pitch = secondPitch;
108 
109 	    if(!(newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec))))
110 		break;
111 
112 	    modes = newmodes;
113 	    mode = modes + *num;
114 
115 	    mode->mode = pMode;
116 	    mode->flags = DGA_CONCURRENT_ACCESS;
117 
118 	    if(pixmap)
119 		mode->flags |= DGA_PIXMAP_AVAILABLE;
120 	    if(!pApm->NoAccel) {
121 		mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
122 		if (Bpp != 3)
123 		    mode->flags |= DGA_BLIT_RECT_TRANS;
124 	    }
125 	    if(pMode->Flags & V_DBLSCAN)
126 		mode->flags |= DGA_DOUBLESCAN;
127 	    if(pMode->Flags & V_INTERLACE)
128 		mode->flags |= DGA_INTERLACED;
129 	    mode->byteOrder = pScrn->imageByteOrder;
130 	    mode->depth = depth;
131 	    mode->bitsPerPixel = bitsPerPixel;
132 	    mode->red_mask = red;
133 	    mode->green_mask = green;
134 	    mode->blue_mask = blue;
135 	    mode->visualClass = visualClass;
136 	    mode->viewportWidth = pMode->HDisplay;
137 	    mode->viewportHeight = pMode->VDisplay;
138 	    mode->xViewportStep = (bitsPerPixel == 24) ? 4 : 1;
139 	    mode->yViewportStep = 1;
140 	    mode->viewportFlags = DGA_FLIP_RETRACE;
141 	    mode->offset = 0;
142 	    mode->address = pApm->FbBase;
143 	    mode->bytesPerScanline = pitch * Bpp;
144 	    mode->imageWidth = pitch;
145 	    mode->imageHeight =  (pScrn->videoRam * 1024 -
146 			pApm->OffscreenReserved) / mode->bytesPerScanline;
147 	    mode->pixmapWidth = mode->imageWidth;
148 	    mode->pixmapHeight = mode->imageHeight;
149 	    mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
150 	   /* this might need to get clamped to some maximum */
151 	    mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
152 
153 	    (*num)++;
154 	}
155 
156     }
157 
158     if(secondPitch) {
159 	secondPitch = 0;
160 	goto SECOND_PASS;
161     }
162 
163     if (reduced_pitch) {
164 	reduced_pitch = FALSE;
165 	goto SECOND_PASS;
166     }
167 
168     return modes;
169 }
170 
171 Bool
ApmDGAInit(ScreenPtr pScreen)172 ApmDGAInit(ScreenPtr pScreen)
173 {
174    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
175    APMDECL(pScrn);
176    DGAModePtr modes = NULL;
177    int num = 0;
178 
179    /* 8 */
180    modes = ApmSetupDGAMode (pScrn, modes, &num, 8, 8,
181 		(pScrn->bitsPerPixel != 24),
182 		(pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
183 		0, 0, 0, PseudoColor);
184 
185    /* 15 */
186    modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
187 		(pScrn->bitsPerPixel != 24),
188 		(pScrn->depth != 15) ? 0 : pScrn->displayWidth,
189 		0x7C00, 0x03E0, 0x001F, TrueColor);
190 
191    modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
192 		(pScrn->bitsPerPixel != 24),
193 		(pScrn->depth != 15) ? 0 : pScrn->displayWidth,
194 		0x7C00, 0x03E0, 0x001F, DirectColor);
195 
196    /* 16 */
197    modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
198 		(pScrn->bitsPerPixel != 24),
199 		(pScrn->depth != 16) ? 0 : pScrn->displayWidth,
200 		0xF800, 0x07E0, 0x001F, TrueColor);
201 
202    modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
203 		(pScrn->bitsPerPixel != 24),
204 		(pScrn->depth != 16) ? 0 : pScrn->displayWidth,
205 		0xF800, 0x07E0, 0x001F, DirectColor);
206 
207    /* 24 */
208    modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
209 		(pScrn->bitsPerPixel == 24),
210 		(pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
211 		0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
212 
213    modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
214 		(pScrn->bitsPerPixel == 24),
215 		(pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
216 		0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
217 
218    /* 32 */
219    modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
220 		(pScrn->bitsPerPixel != 24),
221 		(pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
222 		0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
223 
224    modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
225 		(pScrn->bitsPerPixel != 24),
226 		(pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
227 		0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
228 
229    pApm->numDGAModes = num;
230    pApm->DGAModes = modes;
231 
232    return DGAInit(pScreen, &ApmDGAFuncs, modes, num);
233 }
234 
235 
236 static Bool
ApmSetMode(ScrnInfoPtr pScrn,DGAModePtr pMode)237 ApmSetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
238 {
239     APMDECL(pScrn);
240 
241     if (!pMode) { /* restore the original mode */
242 	if (pApm->DGAactive) {
243 	    memcpy(&pApm->CurrentLayout, &pApm->SavedLayout,
244 						sizeof pApm->CurrentLayout);
245 	    pApm->DGAactive = FALSE;
246 	}
247 
248 	pScrn->currentMode = pApm->CurrentLayout.pMode;
249         ApmSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
250 	ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
251 #if 0
252 	if (pApm->AccelInfoRec)
253 	    XAAInit(pScrn->pScreen, pApm->AccelInfoRec);
254 #endif
255     }
256     else {
257 	if (!pApm->DGAactive) {
258 	    memcpy(&pApm->SavedLayout, &pApm->CurrentLayout,
259 						sizeof pApm->CurrentLayout);
260 	    pApm->DGAactive = TRUE;
261 	}
262 
263 	pApm->CurrentLayout.displayWidth	= pMode->imageWidth;
264 	pApm->CurrentLayout.displayHeight	= pMode->imageHeight;
265 	pApm->CurrentLayout.Scanlines		= pMode->imageHeight + 1;
266 	pApm->CurrentLayout.depth		= pMode->depth;
267 	pApm->CurrentLayout.bitsPerPixel	= pMode->bitsPerPixel;
268 	pApm->CurrentLayout.bytesPerScanline	= pMode->bytesPerScanline;
269 	pApm->CurrentLayout.pMode		= pMode->mode;
270 	if (pMode->bitsPerPixel == 24)
271 	    pApm->CurrentLayout.mask32		= 3;
272 	else
273 	    pApm->CurrentLayout.mask32		= 32 / pMode->bitsPerPixel - 1;
274 
275         ApmSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
276 #ifdef HAVE_XAA_H
277 	ApmSetupXAAInfo(pApm, NULL);
278 #endif
279 
280 #if 0
281 	if (pApm->DGAXAAInfo)
282 	    bzero(pApm->DGAXAAInfo, sizeof(*pApm->DGAXAAInfo));
283 	else
284 	    pApm->DGAXAAInfo = XAACreateInfoRec();
285 	ApmSetupXAAInfo(pApm, pApm->DGAXAAInfo);
286 	/*
287 	 * Let's hope this won't fail, that is reinitialize XAA for this
288 	 * setup...
289 	 */
290 	XAAInit(pScrn->pScreen, pApm->DGAXAAInfo);
291 #endif
292     }
293 
294     return TRUE;
295 }
296 
297 
298 
299 static int
ApmGetViewport(ScrnInfoPtr pScrn)300 ApmGetViewport(
301   ScrnInfoPtr pScrn
302 )
303 {
304     return 0;
305 }
306 
307 static void
ApmSetViewport(ScrnInfoPtr pScrn,int x,int y,int flags)308 ApmSetViewport(
309     ScrnInfoPtr pScrn,
310     int x, int y,
311     int flags
312 )
313 {
314     unsigned char tmp;
315 
316     APMDECL(pScrn);
317 
318     if (pApm->apmLock) {
319 	/*
320 	 * This is just an attempt, because Daryll is tampering with MY
321 	 * registers.
322 	 */
323 	tmp = (RDXB(0xDB) & 0xF4) |  0x0A;
324 	WRXB(0xDB, tmp);
325 	ApmWriteSeq(0x1B, 0x20);
326 	ApmWriteSeq(0x1C, 0x2F);
327 	pApm->apmLock = FALSE;
328     }
329     pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
330     if (pApm->VGAMap) {
331 	/* Wait until vertical retrace is in progress. */
332 	while (APMVGAB(0x3DA) & 0x08);
333 	while (!(APMVGAB(0x3DA) & 0x08));
334     }
335     else {
336 	/* Wait until vertical retrace is in progress. */
337 	while (inb(pApm->iobase + 0x3DA) & 0x08);
338 	while (!(inb(pApm->iobase + 0x3DA) & 0x08));
339     }
340 }
341 
342 #ifdef HAVE_XAA_H
343 static void
ApmFillRect(ScrnInfoPtr pScrn,int x,int y,int w,int h,unsigned long color)344 ApmFillRect (
345     ScrnInfoPtr pScrn,
346     int x, int y, int w, int h,
347     unsigned long color
348 )
349 {
350     APMDECL(pScrn);
351 
352     if(pApm->CurrentLayout.depth != 24) {
353 	(*pApm->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
354 	(*pApm->SubsequentSolidFillRect)(pScrn, x, y, w, h);
355     }
356     else {
357 	(*pApm->SetupForSolidFill24)(pScrn, color, GXcopy, ~0);
358 	(*pApm->SubsequentSolidFillRect24)(pScrn, x, y, w, h);
359     }
360     SET_SYNC_FLAG(pApm->AccelInfoRec);
361 }
362 
363 static void
ApmBlitRect(ScrnInfoPtr pScrn,int srcx,int srcy,int w,int h,int dstx,int dsty)364 ApmBlitRect(
365     ScrnInfoPtr pScrn,
366     int srcx, int srcy,
367     int w, int h,
368     int dstx, int dsty
369 )
370 {
371     APMDECL(pScrn);
372     int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
373     int ydir = (srcy < dsty) ? -1 : 1;
374 
375     if(pApm->CurrentLayout.depth != 24) {
376 	(*pApm->SetupForScreenToScreenCopy)(
377 		pScrn, xdir, ydir, GXcopy, ~0, -1);
378 	(*pApm->SubsequentScreenToScreenCopy)(
379 		pScrn, srcx, srcy, dstx, dsty, w, h);
380     }
381     else {
382 	(*pApm->SetupForScreenToScreenCopy24)(
383 		pScrn, xdir, ydir, GXcopy, ~0, -1);
384 	(*pApm->SubsequentScreenToScreenCopy24)(
385 		pScrn, srcx, srcy, dstx, dsty, w, h);
386     }
387     SET_SYNC_FLAG(pApm->AccelInfoRec);
388 }
389 
390 static void
ApmBlitTransRect(ScrnInfoPtr pScrn,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long color)391 ApmBlitTransRect(
392     ScrnInfoPtr pScrn,
393     int srcx, int srcy,
394     int w, int h,
395     int dstx, int dsty,
396     unsigned long color
397 )
398 {
399     APMDECL(pScrn);
400 
401     if(pApm->AccelInfoRec) {
402 	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
403 	int ydir = (srcy < dsty) ? -1 : 1;
404 
405 	(*pApm->AccelInfoRec->SetupForScreenToScreenCopy)(
406 		pScrn, xdir, ydir, GXcopy, ~0, (int)color);
407 	(*pApm->AccelInfoRec->SubsequentScreenToScreenCopy)(
408 		pScrn, srcx, srcy, dstx, dsty, w, h);
409 	SET_SYNC_FLAG(pApm->AccelInfoRec);
410     }
411 }
412 #endif
413 
414 static Bool
ApmOpenFramebuffer(ScrnInfoPtr pScrn,char ** name,unsigned char ** mem,int * size,int * offset,int * flags)415 ApmOpenFramebuffer(
416     ScrnInfoPtr pScrn,
417     char **name,
418     unsigned char **mem,
419     int *size,
420     int *offset,
421     int *flags
422 )
423 {
424     APMDECL(pScrn);
425 
426     *name = NULL; 		/* no special device */
427     *mem = (unsigned char*)(pApm->LinAddress +
428 			0*((char *)pApm->FbBase - (char *)pApm->LinMap));
429     *size = pScrn->videoRam << 10;
430     *offset = 0;
431     *flags = DGA_NEED_ROOT;
432 
433     return TRUE;
434 }
435