ffb_driver.c revision 7a5333bc
1/*
2 * Creator, Creator3D and Elite3D framebuffer driver.
3 *
4 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <string.h>
29
30#include "xf86.h"
31#include "xf86_OSproc.h"
32#include "mipointer.h"
33#include "micmap.h"
34#include "fb.h"
35
36#include "xf86cmap.h"
37
38#include "ffb.h"
39
40static const OptionInfoRec * FFBAvailableOptions(int chipid, int busid);
41static void	FFBIdentify(int flags);
42static Bool	FFBProbe(DriverPtr drv, int flags);
43static Bool	FFBPreInit(ScrnInfoPtr pScrn, int flags);
44static Bool	FFBScreenInit(SCREEN_INIT_ARGS_DECL);
45static Bool	FFBEnterVT(VT_FUNC_ARGS_DECL);
46static void	FFBLeaveVT(VT_FUNC_ARGS_DECL);
47static Bool	FFBCloseScreen(CLOSE_SCREEN_ARGS_DECL);
48static Bool	FFBSaveScreen(ScreenPtr pScreen, int mode);
49static void	FFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags);
50
51/* Required if the driver supports mode switching */
52static Bool	FFBSwitchMode(SWITCH_MODE_ARGS_DECL);
53/* Required if the driver supports moving the viewport */
54static void	FFBAdjustFrame(ADJUST_FRAME_ARGS_DECL);
55
56/* Optional functions */
57static void	FFBFreeScreen(FREE_SCREEN_ARGS_DECL);
58static ModeStatus FFBValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
59			       Bool verbose, int flags);
60static void     FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags);
61/* ffb_dga.c */
62extern void FFB_InitDGA(ScreenPtr pScreen);
63
64void FFBSync(ScrnInfoPtr pScrn);
65
66static Bool FFBDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
67				pointer ptr);
68
69#define FFB_VERSION 4000
70#define FFB_NAME "SUNFFB"
71#define FFB_DRIVER_NAME "sunffb"
72#define FFB_MAJOR_VERSION PACKAGE_VERSION_MAJOR
73#define FFB_MINOR_VERSION PACKAGE_VERSION_MINOR
74#define FFB_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
75
76/*
77 * This contains the functions needed by the server after loading the driver
78 * module.  It must be supplied, and gets passed back by the SetupProc
79 * function in the dynamic case.  In the static case, a reference to this
80 * is compiled in, and this requires that the name of this DriverRec be
81 * an upper-case version of the driver name.
82 */
83
84_X_EXPORT DriverRec SUNFFB = {
85    FFB_VERSION,
86    FFB_DRIVER_NAME,
87    FFBIdentify,
88    FFBProbe,
89    FFBAvailableOptions,
90    NULL,
91    0,
92    FFBDriverFunc
93};
94
95typedef enum {
96    OPTION_SW_CURSOR,
97    OPTION_HW_CURSOR,
98    OPTION_NOACCEL
99} FFBOpts;
100
101static const OptionInfoRec FFBOptions[] = {
102    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
103    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
104    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
105    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
106};
107
108#ifdef XFree86LOADER
109
110static MODULESETUPPROTO(ffbSetup);
111
112static XF86ModuleVersionInfo sunffbVersRec =
113{
114	"sunffb",
115	MODULEVENDORSTRING,
116	MODINFOSTRING1,
117	MODINFOSTRING2,
118	XORG_VERSION_CURRENT,
119	FFB_MAJOR_VERSION, FFB_MINOR_VERSION, FFB_PATCHLEVEL,
120	ABI_CLASS_VIDEODRV,
121	ABI_VIDEODRV_VERSION,
122	MOD_CLASS_VIDEODRV,
123	{0,0,0,0}
124};
125
126_X_EXPORT XF86ModuleData sunffbModuleData = { &sunffbVersRec, ffbSetup, NULL };
127
128pointer
129ffbSetup(pointer module, pointer opts, int *errmaj, int *errmin)
130{
131    static Bool setupDone = FALSE;
132
133    if (!setupDone) {
134	setupDone = TRUE;
135	xf86AddDriver(&SUNFFB, module, HaveDriverFuncs);
136
137	/*
138	 * Modules that this driver always requires can be loaded here
139	 * by calling LoadSubModule().
140	 */
141
142	/*
143	 * The return value must be non-NULL on success even though there
144	 * is no TearDownProc.
145	 */
146	return (pointer)TRUE;
147    } else {
148	if (errmaj) *errmaj = LDR_ONCEONLY;
149	return NULL;
150    }
151}
152
153#endif /* XFree86LOADER */
154
155static Bool
156FFBGetRec(ScrnInfoPtr pScrn)
157{
158    /*
159     * Allocate an FFBRec, and hook it into pScrn->driverPrivate.
160     * pScrn->driverPrivate is initialised to NULL, so we can check if
161     * the allocation has already been done.
162     */
163    if (pScrn->driverPrivate != NULL)
164	return TRUE;
165
166    pScrn->driverPrivate = xnfcalloc(sizeof(FFBRec), 1);
167    return TRUE;
168}
169
170static void
171FFBFreeRec(ScrnInfoPtr pScrn)
172{
173    FFBPtr pFfb;
174
175    if (pScrn->driverPrivate == NULL)
176	return;
177
178    pFfb = GET_FFB_FROM_SCRN(pScrn);
179
180    free(pScrn->driverPrivate);
181    pScrn->driverPrivate = NULL;
182
183    return;
184}
185
186static const OptionInfoRec *
187FFBAvailableOptions(int chipid, int busid)
188{
189    return FFBOptions;
190}
191
192/* Mandatory */
193static void
194FFBIdentify(int flags)
195{
196    xf86Msg(X_INFO, "%s: driver for Creator, Creator 3D and Elite 3D\n", FFB_NAME);
197}
198
199
200/* Mandatory */
201static Bool
202FFBProbe(DriverPtr drv, int flags)
203{
204    int i;
205    GDevPtr *devSections;
206    int *usedChips;
207    int numDevSections;
208    int numUsed;
209    Bool foundScreen = FALSE;
210    EntityInfoPtr pEnt;
211
212    /*
213     * The aim here is to find all cards that this driver can handle,
214     * and for the ones not already claimed by another driver, claim the
215     * slot, and allocate a ScrnInfoRec.
216     *
217     * This should be a minimal probe, and it should under no circumstances
218     * change the state of the hardware.  Because a device is found, don't
219     * assume that it will be used.  Don't do any initialisations other than
220     * the required ScrnInfoRec initialisations.  Don't allocate any new
221     * data structures.
222     */
223
224    /*
225     * Next we check, if there has been a chipset override in the config file.
226     * For this we must find out if there is an active device section which
227     * is relevant, i.e., which has no driver specified or has THIS driver
228     * specified.
229     */
230
231    if ((numDevSections = xf86MatchDevice(FFB_DRIVER_NAME,
232					  &devSections)) <= 0) {
233	/*
234	 * There's no matching device section in the config file, so quit
235	 * now.
236	 */
237	return FALSE;
238    }
239
240    /*
241     * We need to probe the hardware first.  We then need to see how this
242     * fits in with what is given in the config file, and allow the config
243     * file info to override any contradictions.
244     */
245
246    numUsed = xf86MatchSbusInstances(FFB_NAME, SBUS_DEVICE_FFB,
247		   devSections, numDevSections,
248		   drv, &usedChips);
249
250    free(devSections);
251    if (numUsed <= 0)
252	return FALSE;
253
254    if (flags & PROBE_DETECT)
255	foundScreen = TRUE;
256    else for (i = 0; i < numUsed; i++) {
257	pEnt = xf86GetEntityInfo(usedChips[i]);
258
259	/*
260	 * Check that nothing else has claimed the slots.
261	 */
262	if(pEnt->active) {
263	    ScrnInfoPtr pScrn;
264
265	    /* Allocate a ScrnInfoRec and claim the slot */
266	    pScrn = xf86AllocateScreen(drv, 0);
267
268	    /* Fill in what we can of the ScrnInfoRec */
269	    pScrn->driverVersion = FFB_VERSION;
270	    pScrn->driverName	 = FFB_DRIVER_NAME;
271	    pScrn->name		 = FFB_NAME;
272	    pScrn->Probe	 = FFBProbe;
273	    pScrn->PreInit	 = FFBPreInit;
274	    pScrn->ScreenInit	 = FFBScreenInit;
275  	    pScrn->SwitchMode	 = FFBSwitchMode;
276  	    pScrn->AdjustFrame	 = FFBAdjustFrame;
277	    pScrn->EnterVT	 = FFBEnterVT;
278	    pScrn->LeaveVT	 = FFBLeaveVT;
279	    pScrn->FreeScreen	 = FFBFreeScreen;
280	    pScrn->ValidMode	 = FFBValidMode;
281	    xf86AddEntityToScreen(pScrn, pEnt->index);
282	    foundScreen = TRUE;
283	}
284	free(pEnt);
285    }
286    free(usedChips);
287    return foundScreen;
288}
289
290/* Mandatory */
291static Bool
292FFBPreInit(ScrnInfoPtr pScrn, int flags)
293{
294    FFBPtr pFfb;
295    sbusDevicePtr psdp;
296    MessageType from;
297    int i;
298
299    if (flags & PROBE_DETECT) return FALSE;
300
301    /*
302     * Note: This function is only called once at server startup, and
303     * not at the start of each server generation.  This means that
304     * only things that are persistent across server generations can
305     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
306     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
307     * are too, and should be used for data that must persist across
308     * server generations.
309     *
310     * Per-generation data should be allocated with
311     * AllocateScreenPrivateIndex() from the ScreenInit() function.
312     */
313
314    /* Allocate the FFBRec driverPrivate */
315    if (!FFBGetRec(pScrn))
316	return FALSE;
317
318    pFfb = GET_FFB_FROM_SCRN(pScrn);
319
320    /* Set pScrn->monitor */
321    pScrn->monitor = pScrn->confScreen->monitor;
322
323    /* This driver doesn't expect more than one entity per screen */
324    if (pScrn->numEntities > 1)
325	return FALSE;
326    /* This is the general case */
327    for (i = 0; i < pScrn->numEntities; i++) {
328	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
329
330	/* FFB is purely UPA (but we handle it as SBUS) */
331	if (pEnt->location.type == BUS_SBUS) {
332	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
333	    pFfb->psdp = psdp;
334	} else
335	    return FALSE;
336    }
337
338    /*********************
339    deal with depth
340    *********************/
341
342    if (!xf86SetDepthBpp(pScrn, 24, 0, 32, Support32bppFb)) {
343	return FALSE;
344    } else {
345	/* Check that the returned depth is one we support */
346	switch (pScrn->depth) {
347	case 24:
348	    /* OK */
349	    break;
350	default:
351	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
352		       "Given depth (%d) is not supported by this driver\n",
353		       pScrn->depth);
354	    return FALSE;
355	}
356    }
357
358    /* Collect all of the relevant option flags (fill in pScrn->options) */
359    xf86CollectOptions(pScrn, NULL);
360    /* Process the options */
361    if (!(pFfb->Options = malloc(sizeof(FFBOptions))))
362	return FALSE;
363    memcpy(pFfb->Options, FFBOptions, sizeof(FFBOptions));
364    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pFfb->Options);
365
366    /*
367     * This must happen after pScrn->display has been set because
368     * xf86SetWeight references it.
369     */
370    if (pScrn->depth > 8) {
371	rgb weight = {8, 8, 8};
372	rgb mask = {0xff, 0xff00, 0xff0000};
373
374	if (!xf86SetWeight(pScrn, weight, mask)) {
375	    return FALSE;
376	}
377    }
378
379    if (!xf86SetDefaultVisual(pScrn, -1))
380	return FALSE;
381
382    /*
383     * The new cmap code requires this to be initialised.
384     */
385
386    {
387	Gamma zeros = {0.0, 0.0, 0.0};
388
389	if (!xf86SetGamma(pScrn, zeros)) {
390	    return FALSE;
391	}
392    }
393
394    /* Set the bits per RGB for 8bpp mode */
395    from = X_DEFAULT;
396
397    /* determine whether we use hardware or software cursor */
398
399    pFfb->HWCursor = TRUE;
400    if (xf86GetOptValBool(pFfb->Options, OPTION_HW_CURSOR, &pFfb->HWCursor))
401	from = X_CONFIG;
402    if (xf86ReturnOptValBool(pFfb->Options, OPTION_SW_CURSOR, FALSE)) {
403	from = X_CONFIG;
404	pFfb->HWCursor = FALSE;
405    }
406
407    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
408		pFfb->HWCursor ? "HW" : "SW");
409
410    if (xf86ReturnOptValBool(pFfb->Options, OPTION_NOACCEL, FALSE)) {
411	pFfb->NoAccel = TRUE;
412	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
413    }
414
415    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
416	FFBFreeRec(pScrn);
417	return FALSE;
418    }
419
420    if (xf86LoadSubModule(pScrn, "xaa") == NULL) {
421	FFBFreeRec(pScrn);
422	return FALSE;
423    }
424
425    if (pFfb->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
426	FFBFreeRec(pScrn);
427	return FALSE;
428    }
429
430    if (xf86LoadSubModule(pScrn, "dbe") == NULL) {
431	FFBFreeRec(pScrn);
432	return FALSE;
433    }
434
435
436    /*********************
437    set up clock and mode stuff
438    *********************/
439
440    pScrn->progClock = TRUE;
441
442    if(pScrn->display->virtualX || pScrn->display->virtualY) {
443	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
444		   "FFB does not support a virtual desktop\n");
445	pScrn->display->virtualX = 0;
446	pScrn->display->virtualY = 0;
447    }
448
449    xf86SbusUseBuiltinMode(pScrn, pFfb->psdp);
450    pScrn->currentMode = pScrn->modes;
451    pScrn->displayWidth = pScrn->virtualX;
452
453    /* Set display resolution */
454    xf86SetDpi(pScrn, 0, 0);
455
456    return TRUE;
457}
458
459/* Determine the FFB/AFB board type.  We need this information even
460 * if acceleration is disabled because the ramdac support layer needs
461 * to know what kind of FFB/AFB this is.
462 */
463static void
464FFBProbeBoardType(FFBPtr pFfb)
465{
466	ffb_fbcPtr ffb = pFfb->regs;
467	volatile unsigned int *afb_fem;
468	unsigned int val;
469
470	afb_fem = ((volatile unsigned int *) ((char *)ffb + 0x1540));
471	val = *afb_fem;
472	val &= 0x7f;
473
474	xf86Msg(X_INFO, "%s: ", pFfb->psdp->device);
475	if (val == 0x3f || val == 0x07 || val == 0x01) {
476		/* When firmware has not been loaded onto AFB we
477		 * just assume it is an M6 board.
478		 */
479		if (val == 0x3f || val != 0x07) {
480			pFfb->ffb_type = afb_m6;
481			ErrorF("AFB: Detected Elite3D/M6.\n");
482		} else {
483			pFfb->ffb_type = afb_m3;
484			ErrorF("AFB: Detected Elite3D/M3.\n");
485		}
486
487		/* These attributes are invariant on AFB. */
488		pFfb->has_double_res = 0;
489		pFfb->has_z_buffer = 1;
490		pFfb->has_double_buffer = 1;
491	} else {
492		unsigned char sbits;
493
494		/* Read the board strapping bits twice, because sometimes
495		 * the strapping pins can get misrouted to the bus interface
496		 * on the first attempt.  The second attempt will get the
497		 * correct value.
498		 */
499		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
500		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
501		switch (sbits & 0x78) {
502		case (0x0 << 5) | (0x0 << 3):
503			pFfb->ffb_type = ffb1_prototype;
504			ErrorF("Detected FFB1 pre-FCS prototype, ");
505			break;
506		case (0x0 << 5) | (0x1 << 3):
507			pFfb->ffb_type = ffb1_standard;
508			ErrorF("Detected FFB1, ");
509			break;
510		case (0x0 << 5) | (0x3 << 3):
511			pFfb->ffb_type = ffb1_speedsort;
512			ErrorF("Detected FFB1-SpeedSort, ");
513			break;
514		case (0x1 << 5) | (0x0 << 3):
515			pFfb->ffb_type = ffb2_prototype;
516			ErrorF("Detected FFB2/vertical pre-FCS prototype, ");
517			break;
518		case (0x1 << 5) | (0x1 << 3):
519			pFfb->ffb_type = ffb2_vertical;
520			ErrorF("Detected FFB2/vertical, ");
521			break;
522		case (0x1 << 5) | (0x2 << 3):
523			pFfb->ffb_type = ffb2_vertical_plus;
524			ErrorF("Detected FFB2+/vertical, ");
525			break;
526		case (0x2 << 5) | (0x0 << 3):
527			pFfb->ffb_type = ffb2_horizontal;
528			ErrorF("Detected FFB2/horizontal, ");
529			break;
530		case (0x2 << 5) | (0x2 << 3):
531			pFfb->ffb_type = ffb2_horizontal;
532			ErrorF("Detected FFB2+/horizontal, ");
533			break;
534		default:
535			pFfb->ffb_type = ffb2_vertical;
536			ErrorF("Unknown boardID[%08x], assuming FFB2, ", sbits);
537			break;
538		};
539
540		if (sbits & (1 << 2)) {
541			ErrorF("DoubleRES, ");
542			pFfb->has_double_res = 1;
543		} else {
544			pFfb->has_double_res = 0;
545		}
546		if (sbits & (1 << 1)) {
547			ErrorF("Z-buffer, ");
548			pFfb->has_z_buffer = 1;
549		} else {
550			pFfb->has_z_buffer = 0;
551		}
552		if (sbits & (1 << 0)) {
553			/* This state really means to the driver that the double
554			 * buffers are available for hw accelerate Dbe.  When the
555			 * FFB is in high-resolution mode, the buffers are combined
556			 * into one single large framebuffer.  So in high-resolution
557			 * hw accelerated double-buffering is not available.
558			 */
559			if ((ffb->fbcfg0 & FFB_FBCFG0_RES_MASK) != FFB_FBCFG0_RES_HIGH)
560				pFfb->has_double_buffer = 1;
561			else
562				pFfb->has_double_buffer = 0;
563		} else {
564			pFfb->has_double_buffer = 0;
565		}
566		if (pFfb->has_double_buffer)
567			ErrorF("Double-buffered.\n");
568		else
569			ErrorF("Single-buffered.\n");
570	}
571}
572
573/* Mandatory */
574
575/* This gets called at the start of each server generation */
576
577static Bool
578FFBScreenInit(SCREEN_INIT_ARGS_DECL)
579{
580    ScrnInfoPtr pScrn;
581    FFBPtr pFfb;
582    int ret;
583    unsigned int afb_fem;
584    VisualPtr visual;
585
586    /*
587     * First get the ScrnInfoRec
588     */
589    pScrn = xf86ScreenToScrn(pScreen);
590
591    pFfb = GET_FFB_FROM_SCRN(pScrn);
592
593    /* Map the FFB framebuffer, for each view. */
594
595    /* 24-bit RGB Dumb view */
596    pFfb->fb = pFfb->dfb24 =
597	xf86MapSbusMem (pFfb->psdp, FFB_DFB24_VOFF, 0x1000000);
598
599    if (! pFfb->dfb24)
600	return FALSE;
601
602    /* 8-bit R Dumb view */
603    pFfb->dfb8r =
604	xf86MapSbusMem (pFfb->psdp, FFB_DFB8R_VOFF, 0x400000);
605
606    if (! pFfb->dfb8r)
607	return FALSE;
608
609    /* 8-bit X Dumb view */
610    pFfb->dfb8x =
611	xf86MapSbusMem (pFfb->psdp, FFB_DFB8X_VOFF, 0x400000);
612
613    if (! pFfb->dfb8x)
614	return FALSE;
615
616    /* 32-bit RGB Smart view */
617    pFfb->sfb32 =
618	xf86MapSbusMem (pFfb->psdp, FFB_SFB32_VOFF, 0x1000000);
619
620    if (!pFfb->sfb32)
621	return FALSE;
622
623    /* 8-bit R Smart view */
624    pFfb->sfb8r =
625	xf86MapSbusMem(pFfb->psdp, FFB_SFB8R_VOFF, 0x400000);
626
627    if (!pFfb->sfb8r)
628	return FALSE;
629
630    /* 8-bit X Smart view */
631    pFfb->sfb8x =
632	xf86MapSbusMem(pFfb->psdp, FFB_SFB8X_VOFF, 0x400000);
633
634    if (!pFfb->sfb8x)
635	return FALSE;
636
637    /* Map the rendering pipeline */
638    pFfb->regs =
639	xf86MapSbusMem (pFfb->psdp, FFB_FBC_REGS_VOFF, 16384);
640
641    if (! pFfb->regs)
642	return FALSE;
643
644    /* Map the ramdac */
645    pFfb->dac =
646	xf86MapSbusMem (pFfb->psdp, FFB_DAC_VOFF, 8192);
647
648    if (! pFfb->dac)
649	return FALSE;
650
651    /* Map the board strapping bits */
652    pFfb->strapping_bits = (volatile unsigned int *)
653	    xf86MapSbusMem(pFfb->psdp, FFB_EXP_VOFF, 8192);
654
655    if (! pFfb->strapping_bits)
656	return FALSE;
657
658    /* Probe for the type of FFB/AFB we have. */
659    FFBProbeBoardType(pFfb);
660
661    /* Now that we have the board type, we can init the ramdac layer. */
662    if (FFBDacInit(pFfb) == FALSE)
663	return FALSE;
664
665    /* OK, a fun gross hack to detect if this is
666     * AFB and if so whether the correct firmware
667     * has been loaded.  The machine will flatline
668     * if you try to use certain acceleration features
669     * without the full firmware loaded.
670     *
671     * The bootup Elite3D/AFB firmware is minimal, and
672     * will leave the FloatEnableMask register at a
673     * value of 0x01.  Creator{,3D} lacks the FEM register
674     * and will return a "nonsense" value on attempts to
675     * read this location.  After experimentation, an
676     * appropriate definition for "nonsense" seems to
677     * be anything with all low 7 bits not 0x3f, 0x07,
678     * of 0x01.
679     *
680     * If the FEM register is non-zero and is some value
681     * other than 0x1 (usually 0x3f or 0x7 depending upon
682     * whether the card has 3 or 6 floats) we can assume
683     * the correct firmware has been loaded. -DaveM
684     */
685    afb_fem = *(unsigned int *)((char *)pFfb->regs + 0x1540);
686    if ((afb_fem & 0x7f) != 0x3f &&
687	(afb_fem & 0x7f) != 0x07 &&
688	(afb_fem & 0x7f) != 0x01)
689	xf86Msg(X_INFO, "%s: Detected Creator/Creator3D\n", pFfb->psdp->device);
690    else {
691	xf86Msg(X_INFO, "%s: Detected Elite3D M3/M6, checking firmware...\n", pFfb->psdp->device);
692	if (afb_fem == 0x1) {
693	    xf86Msg(X_INFO, "%s: ... AFB firmware not loaded\n", pFfb->psdp->device);
694	    if (!pFfb->NoAccel) {
695		xf86Msg(X_WARNING, "%s: Forcing no acceleration on Elite3D M3/M6\n", pFfb->psdp->device);
696		pFfb->NoAccel = TRUE;
697	    }
698	} else
699	    xf86Msg(X_INFO, "%s: ... AFB firmware is loaded\n", pFfb->psdp->device);
700    }
701
702    /* Darken the screen for aesthetic reasons and set the viewport */
703    /* XXX can't do this yet */
704    /* FFBSaveScreen(pScreen, SCREEN_SAVER_ON);*/
705
706    /*
707     * The next step is to setup the screen's visuals, and initialise the
708     * framebuffer code.  In cases where the framebuffer's default
709     * choices for things like visual layouts and bits per RGB are OK,
710     * this may be as simple as calling the framebuffer's ScreenInit()
711     * function.  If not, the visuals will need to be setup before calling
712     * a fb ScreenInit() function and fixed up after.
713     */
714
715    /*
716     * Reset visual list.
717     */
718    miClearVisualTypes();
719
720    /* Setup the visuals we support. */
721    if (!miSetVisualTypes(24, TrueColorMask,
722			  pScrn->rgbBits, TrueColor))
723	    return FALSE;
724
725    if (!miSetPixmapDepths())
726        return FALSE;
727
728    /*
729     * Call the framebuffer layer's ScreenInit function, and fill in other
730     * pScreen fields.
731     */
732    ret = fbScreenInit(pScreen, (pFfb->NoAccel ? pFfb->dfb24 : pFfb->sfb32),
733		       pScrn->virtualX, pScrn->virtualY,
734		       pScrn->xDpi, pScrn->yDpi,
735		       2048, 32);
736
737    if (!ret)
738	return FALSE;
739
740    if (pScrn->bitsPerPixel > 8) {
741        /* Fixup RGB ordering */
742        visual = pScreen->visuals + pScreen->numVisuals;
743        while (--visual >= pScreen->visuals) {
744	    if ((visual->class | DynamicClass) == DirectColor) {
745		visual->offsetRed = pScrn->offset.red;
746		visual->offsetGreen = pScrn->offset.green;
747		visual->offsetBlue = pScrn->offset.blue;
748		visual->redMask = pScrn->mask.red;
749		visual->greenMask = pScrn->mask.green;
750		visual->blueMask = pScrn->mask.blue;
751	    }
752	}
753    }
754
755    if (!fbPictureInit(pScreen, NULL, 0) &&
756	(serverGeneration == 1))
757      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
758		 "RENDER extension initialisation failed.\n");
759
760    xf86SetBlackWhitePixels(pScreen);
761
762    if (!pFfb->NoAccel) {
763	if (!FFBAccelInit(pScreen, pFfb))
764	    return FALSE;
765	xf86Msg(X_INFO, "%s: Using acceleration\n", pFfb->psdp->device);
766    }
767
768
769    xf86SetBackingStore(pScreen);
770    xf86SetSilkenMouse(pScreen);
771
772    /* Initialise cursor functions */
773    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
774
775    /* Initialize HW cursor layer.
776     * Must follow software cursor initialization.
777     */
778    if (pFfb->HWCursor) {
779	if(!FFBHWCursorInit(pScreen)) {
780	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
781		       "Hardware cursor initialization failed\n");
782	    return(FALSE);
783	}
784	xf86SbusHideOsHwCursor(pFfb->psdp);
785    }
786
787    /* Initialise default colourmap. */
788    if (!miCreateDefColormap(pScreen))
789	return FALSE;
790
791    /* Initialize colormap layer.
792     * Must follow initialization of the default colormap.
793     */
794    if (!xf86HandleColormaps(pScreen, 256, 8,
795			     FFBDacLoadPalette, NULL,
796			     CMAP_LOAD_EVEN_IF_OFFSCREEN |
797			     CMAP_RELOAD_ON_MODE_SWITCH))
798	return FALSE;
799
800    /* Setup DGA support. */
801    if (!pFfb->NoAccel)
802	    FFB_InitDGA(pScreen);
803
804    xf86DPMSInit(pScreen, FFBDPMSSet, 0);
805
806    pFfb->CloseScreen = pScreen->CloseScreen;
807    pScreen->CloseScreen = FFBCloseScreen;
808    pScreen->SaveScreen = FFBSaveScreen;
809
810    (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
811
812    /* Report any unused options (only for the first generation) */
813    if (serverGeneration == 1) {
814	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
815    }
816
817    /* unblank the screen */
818    /* XXX since we didn't blank it we don't need to unblank it here */
819    /* FFBSaveScreen(pScreen, SCREEN_SAVER_OFF); */
820
821    /* Done */
822    return TRUE;
823}
824
825
826/* Usually mandatory */
827static Bool
828FFBSwitchMode(SWITCH_MODE_ARGS_DECL)
829{
830    return TRUE;
831}
832
833
834/*
835 * This function is used to initialize the Start Address - the first
836 * displayed location in the video memory.
837 */
838/* Usually mandatory */
839static void
840FFBAdjustFrame(ADJUST_FRAME_ARGS_DECL)
841{
842    /* we don't support virtual desktops */
843    return;
844}
845
846/*
847 * This is called when VT switching back to the X server.  Its job is
848 * to reinitialise the video mode.
849 */
850
851/* Mandatory */
852static Bool
853FFBEnterVT(VT_FUNC_ARGS_DECL)
854{
855    SCRN_INFO_PTR(arg);
856    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
857
858    pFfb->vtSema = FALSE;
859    if (!pFfb->NoAccel)
860	CreatorVtChange (pScrn->pScreen, TRUE);
861    if (pFfb->HWCursor)
862	xf86SbusHideOsHwCursor (pFfb->psdp);
863
864    FFBDacEnterVT(pFfb);
865
866    return TRUE;
867}
868
869
870/*
871 * This is called when VT switching away from the X server.
872 */
873
874/* Mandatory */
875static void
876FFBLeaveVT(VT_FUNC_ARGS_DECL)
877{
878    SCRN_INFO_PTR(arg);
879    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
880
881    FFBDacLeaveVT(pFfb);
882
883    if (!pFfb->NoAccel)
884	CreatorVtChange (pScrn->pScreen, FALSE);
885
886    if (pFfb->HWCursor)
887	xf86SbusHideOsHwCursor (pFfb->psdp);
888
889    pFfb->vtSema = TRUE;
890    return;
891}
892
893
894/*
895 * This is called at the end of each server generation.  It restores the
896 * original (text) mode.  It should really also unmap the video memory too.
897 */
898
899/* Mandatory */
900static Bool
901FFBCloseScreen(CLOSE_SCREEN_ARGS_DECL)
902{
903	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
904	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
905
906	FFBDacCursorEnableDisable(pFfb, 0);
907	/* Restore kernel ramdac state before we unmap registers. */
908	FFBDacFini(pFfb);
909
910	pScrn->vtSema = FALSE;
911
912	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb24, 0x1000000);
913	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8r, 0x400000);
914	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8x, 0x400000);
915	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb32, 0x1000000);
916	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8r, 0x400000);
917	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8x, 0x400000);
918	xf86UnmapSbusMem(pFfb->psdp, pFfb->regs, 16384);
919	xf86UnmapSbusMem(pFfb->psdp, pFfb->dac, 8192);
920	xf86UnmapSbusMem(pFfb->psdp, (void *)pFfb->strapping_bits, 8192);
921
922	if (pFfb->HWCursor)
923		xf86SbusHideOsHwCursor (pFfb->psdp);
924
925	pScreen->CloseScreen = pFfb->CloseScreen;
926	return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
927}
928
929
930/* Free up any per-generation data structures */
931
932/* Optional */
933static void
934FFBFreeScreen(FREE_SCREEN_ARGS_DECL)
935{
936	SCRN_INFO_PTR(arg);
937	FFBFreeRec(pScrn);
938}
939
940
941/* Checks if a mode is suitable for the selected chipset. */
942
943/* Optional */
944static ModeStatus
945FFBValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
946{
947	if (mode->Flags & V_INTERLACE)
948		return MODE_BAD;
949
950	return MODE_OK;
951}
952
953/* Do screen blanking */
954
955/* Mandatory */
956static Bool
957FFBSaveScreen(ScreenPtr pScreen, int mode)
958    /* This function blanks the screen when mode=SCREEN_SAVER_ON and
959       unblanks it when mode=SCREEN_SAVER_OFF.  It is used internally in the
960       FFBScreenInit code `for aesthetic reasons,' and it is used for
961       blanking if you set "xset s on s blank."  The work (such as it is) is
962       done in "ffb_dac.c" `for aesthetic reasons.'
963    */
964{
965
966    return FFBDacSaveScreen(pScreen, mode);
967}
968
969static void
970FFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
971{
972	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
973
974	FFBDacDPMSMode(pFfb, mode, 0);
975}
976
977/*
978 * This is the implementation of the Sync() function.
979 */
980void
981FFBSync(ScrnInfoPtr pScrn)
982{
983    return;
984}
985
986/*
987  Hook for DPMS Mode.
988*/
989
990static void
991FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
992{
993  FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
994}
995
996static Bool
997FFBDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
998    pointer ptr)
999{
1000	xorgHWFlags *flag;
1001
1002	switch (op) {
1003	case GET_REQUIRED_HW_INTERFACES:
1004		flag = (CARD32*)ptr;
1005		(*flag) = HW_MMIO;
1006		return TRUE;
1007	default:
1008		return FALSE;
1009	}
1010}
1011
1012