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