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 "ffb.h"
31
32#include "xf86.h"
33#include "xf86_OSproc.h"
34#include "mipointer.h"
35#include "micmap.h"
36#include "fb.h"
37
38#include "xf86cmap.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_ACCELMETHOD,
99    OPTION_NOACCEL
100} FFBOpts;
101
102static const OptionInfoRec FFBOptions[] = {
103    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
104    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
105    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
106    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_STRING,	{0}, FALSE },
107    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
108};
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
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    free(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    free(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	free(pEnt);
283    }
284    free(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 = malloc(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 (pFfb->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
419	FFBFreeRec(pScrn);
420	return FALSE;
421    }
422
423    if (xf86LoadSubModule(pScrn, "dbe") == NULL) {
424	FFBFreeRec(pScrn);
425	return FALSE;
426    }
427
428
429    /*********************
430    set up clock and mode stuff
431    *********************/
432
433    pScrn->progClock = TRUE;
434
435    if(pScrn->display->virtualX || pScrn->display->virtualY) {
436	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
437		   "FFB does not support a virtual desktop\n");
438	pScrn->display->virtualX = 0;
439	pScrn->display->virtualY = 0;
440    }
441
442    xf86SbusUseBuiltinMode(pScrn, pFfb->psdp);
443    pScrn->currentMode = pScrn->modes;
444    pScrn->displayWidth = pScrn->virtualX;
445
446    /* Set display resolution */
447    xf86SetDpi(pScrn, 0, 0);
448
449    return TRUE;
450}
451
452/* Determine the FFB/AFB board type.  We need this information even
453 * if acceleration is disabled because the ramdac support layer needs
454 * to know what kind of FFB/AFB this is.
455 */
456static void
457FFBProbeBoardType(FFBPtr pFfb)
458{
459	ffb_fbcPtr ffb = pFfb->regs;
460	volatile unsigned int *afb_fem;
461	unsigned int val;
462
463	afb_fem = ((volatile unsigned int *) ((char *)ffb + 0x1540));
464	val = *afb_fem;
465	val &= 0x7f;
466
467	xf86Msg(X_INFO, "%s: ", pFfb->psdp->device);
468	if (val == 0x3f || val == 0x07 || val == 0x01) {
469		/* When firmware has not been loaded onto AFB we
470		 * just assume it is an M6 board.
471		 */
472		if (val == 0x3f || val != 0x07) {
473			pFfb->ffb_type = afb_m6;
474			ErrorF("AFB: Detected Elite3D/M6.\n");
475		} else {
476			pFfb->ffb_type = afb_m3;
477			ErrorF("AFB: Detected Elite3D/M3.\n");
478		}
479
480		/* These attributes are invariant on AFB. */
481		pFfb->has_double_res = 0;
482		pFfb->has_z_buffer = 1;
483		pFfb->has_double_buffer = 1;
484	} else {
485		unsigned char sbits;
486
487		/* Read the board strapping bits twice, because sometimes
488		 * the strapping pins can get misrouted to the bus interface
489		 * on the first attempt.  The second attempt will get the
490		 * correct value.
491		 */
492		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
493		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
494		switch (sbits & 0x78) {
495		case (0x0 << 5) | (0x0 << 3):
496			pFfb->ffb_type = ffb1_prototype;
497			ErrorF("Detected FFB1 pre-FCS prototype, ");
498			break;
499		case (0x0 << 5) | (0x1 << 3):
500			pFfb->ffb_type = ffb1_standard;
501			ErrorF("Detected FFB1, ");
502			break;
503		case (0x0 << 5) | (0x3 << 3):
504			pFfb->ffb_type = ffb1_speedsort;
505			ErrorF("Detected FFB1-SpeedSort, ");
506			break;
507		case (0x1 << 5) | (0x0 << 3):
508			pFfb->ffb_type = ffb2_prototype;
509			ErrorF("Detected FFB2/vertical pre-FCS prototype, ");
510			break;
511		case (0x1 << 5) | (0x1 << 3):
512			pFfb->ffb_type = ffb2_vertical;
513			ErrorF("Detected FFB2/vertical, ");
514			break;
515		case (0x1 << 5) | (0x2 << 3):
516			pFfb->ffb_type = ffb2_vertical_plus;
517			ErrorF("Detected FFB2+/vertical, ");
518			break;
519		case (0x2 << 5) | (0x0 << 3):
520			pFfb->ffb_type = ffb2_horizontal;
521			ErrorF("Detected FFB2/horizontal, ");
522			break;
523		case (0x2 << 5) | (0x2 << 3):
524			pFfb->ffb_type = ffb2_horizontal;
525			ErrorF("Detected FFB2+/horizontal, ");
526			break;
527		default:
528			pFfb->ffb_type = ffb2_vertical;
529			ErrorF("Unknown boardID[%08x], assuming FFB2, ", sbits);
530			break;
531		};
532
533		if (sbits & (1 << 2)) {
534			ErrorF("DoubleRES, ");
535			pFfb->has_double_res = 1;
536		} else {
537			pFfb->has_double_res = 0;
538		}
539		if (sbits & (1 << 1)) {
540			ErrorF("Z-buffer, ");
541			pFfb->has_z_buffer = 1;
542		} else {
543			pFfb->has_z_buffer = 0;
544		}
545		if (sbits & (1 << 0)) {
546			/* This state really means to the driver that the double
547			 * buffers are available for hw accelerate Dbe.  When the
548			 * FFB is in high-resolution mode, the buffers are combined
549			 * into one single large framebuffer.  So in high-resolution
550			 * hw accelerated double-buffering is not available.
551			 */
552			if ((ffb->fbcfg0 & FFB_FBCFG0_RES_MASK) != FFB_FBCFG0_RES_HIGH)
553				pFfb->has_double_buffer = 1;
554			else
555				pFfb->has_double_buffer = 0;
556		} else {
557			pFfb->has_double_buffer = 0;
558		}
559		if (pFfb->has_double_buffer)
560			ErrorF("Double-buffered.\n");
561		else
562			ErrorF("Single-buffered.\n");
563	}
564}
565
566/* Mandatory */
567
568/* This gets called at the start of each server generation */
569
570static Bool
571FFBScreenInit(SCREEN_INIT_ARGS_DECL)
572{
573    ScrnInfoPtr pScrn;
574    FFBPtr pFfb;
575    int ret;
576    unsigned int afb_fem;
577    VisualPtr visual;
578
579    /*
580     * First get the ScrnInfoRec
581     */
582    pScrn = xf86ScreenToScrn(pScreen);
583
584    pFfb = GET_FFB_FROM_SCRN(pScrn);
585
586    /* Map the FFB framebuffer, for each view. */
587
588    /* 24-bit RGB Dumb view */
589    pFfb->fb = pFfb->dfb24 =
590	xf86MapSbusMem (pFfb->psdp, FFB_DFB24_VOFF, 0x1000000);
591
592    if (! pFfb->dfb24)
593	return FALSE;
594
595    /* 8-bit R Dumb view */
596    pFfb->dfb8r =
597	xf86MapSbusMem (pFfb->psdp, FFB_DFB8R_VOFF, 0x400000);
598
599    if (! pFfb->dfb8r)
600	return FALSE;
601
602    /* 8-bit X Dumb view */
603    pFfb->dfb8x =
604	xf86MapSbusMem (pFfb->psdp, FFB_DFB8X_VOFF, 0x400000);
605
606    if (! pFfb->dfb8x)
607	return FALSE;
608
609    /* 32-bit RGB Smart view */
610    pFfb->sfb32 =
611	xf86MapSbusMem (pFfb->psdp, FFB_SFB32_VOFF, 0x1000000);
612
613    if (!pFfb->sfb32)
614	return FALSE;
615
616    /* 8-bit R Smart view */
617    pFfb->sfb8r =
618	xf86MapSbusMem(pFfb->psdp, FFB_SFB8R_VOFF, 0x400000);
619
620    if (!pFfb->sfb8r)
621	return FALSE;
622
623    /* 8-bit X Smart view */
624    pFfb->sfb8x =
625	xf86MapSbusMem(pFfb->psdp, FFB_SFB8X_VOFF, 0x400000);
626
627    if (!pFfb->sfb8x)
628	return FALSE;
629
630    /* Map the rendering pipeline */
631    pFfb->regs =
632	xf86MapSbusMem (pFfb->psdp, FFB_FBC_REGS_VOFF, 16384);
633
634    if (! pFfb->regs)
635	return FALSE;
636
637    /* Map the ramdac */
638    pFfb->dac =
639	xf86MapSbusMem (pFfb->psdp, FFB_DAC_VOFF, 8192);
640
641    if (! pFfb->dac)
642	return FALSE;
643
644    /* Map the board strapping bits */
645    pFfb->strapping_bits = (volatile unsigned int *)
646	    xf86MapSbusMem(pFfb->psdp, FFB_EXP_VOFF, 8192);
647
648    if (! pFfb->strapping_bits)
649	return FALSE;
650
651    /* Probe for the type of FFB/AFB we have. */
652    FFBProbeBoardType(pFfb);
653
654    /* Now that we have the board type, we can init the ramdac layer. */
655    if (FFBDacInit(pFfb) == FALSE)
656	return FALSE;
657
658    /* OK, a fun gross hack to detect if this is
659     * AFB and if so whether the correct firmware
660     * has been loaded.  The machine will flatline
661     * if you try to use certain acceleration features
662     * without the full firmware loaded.
663     *
664     * The bootup Elite3D/AFB firmware is minimal, and
665     * will leave the FloatEnableMask register at a
666     * value of 0x01.  Creator{,3D} lacks the FEM register
667     * and will return a "nonsense" value on attempts to
668     * read this location.  After experimentation, an
669     * appropriate definition for "nonsense" seems to
670     * be anything with all low 7 bits not 0x3f, 0x07,
671     * of 0x01.
672     *
673     * If the FEM register is non-zero and is some value
674     * other than 0x1 (usually 0x3f or 0x7 depending upon
675     * whether the card has 3 or 6 floats) we can assume
676     * the correct firmware has been loaded. -DaveM
677     */
678    afb_fem = *(unsigned int *)((char *)pFfb->regs + 0x1540);
679    if ((afb_fem & 0x7f) != 0x3f &&
680	(afb_fem & 0x7f) != 0x07 &&
681	(afb_fem & 0x7f) != 0x01)
682	xf86Msg(X_INFO, "%s: Detected Creator/Creator3D\n", pFfb->psdp->device);
683    else {
684	xf86Msg(X_INFO, "%s: Detected Elite3D M3/M6, checking firmware...\n", pFfb->psdp->device);
685	if (afb_fem == 0x1) {
686	    xf86Msg(X_INFO, "%s: ... AFB firmware not loaded\n", pFfb->psdp->device);
687	    if (!pFfb->NoAccel) {
688		xf86Msg(X_WARNING, "%s: Forcing no acceleration on Elite3D M3/M6\n", pFfb->psdp->device);
689		pFfb->NoAccel = TRUE;
690	    }
691	} else
692	    xf86Msg(X_INFO, "%s: ... AFB firmware is loaded\n", pFfb->psdp->device);
693    }
694
695    /* Darken the screen for aesthetic reasons and set the viewport */
696    /* XXX can't do this yet */
697    /* FFBSaveScreen(pScreen, SCREEN_SAVER_ON);*/
698
699    /*
700     * The next step is to setup the screen's visuals, and initialise the
701     * framebuffer code.  In cases where the framebuffer's default
702     * choices for things like visual layouts and bits per RGB are OK,
703     * this may be as simple as calling the framebuffer's ScreenInit()
704     * function.  If not, the visuals will need to be setup before calling
705     * a fb ScreenInit() function and fixed up after.
706     */
707
708    /*
709     * Reset visual list.
710     */
711    miClearVisualTypes();
712
713    /* Setup the visuals we support. */
714    if (!miSetVisualTypes(24, TrueColorMask,
715			  pScrn->rgbBits, TrueColor))
716	    return FALSE;
717
718    if (!miSetPixmapDepths())
719        return FALSE;
720
721    /*
722     * Call the framebuffer layer's ScreenInit function, and fill in other
723     * pScreen fields.
724     */
725    ret = fbScreenInit(pScreen, (pFfb->NoAccel ? pFfb->dfb24 : pFfb->sfb32),
726		       pScrn->virtualX, pScrn->virtualY,
727		       pScrn->xDpi, pScrn->yDpi,
728		       2048, 32);
729
730    if (!ret)
731	return FALSE;
732
733    if (pScrn->bitsPerPixel > 8) {
734        /* Fixup RGB ordering */
735        visual = pScreen->visuals + pScreen->numVisuals;
736        while (--visual >= pScreen->visuals) {
737	    if ((visual->class | DynamicClass) == DirectColor) {
738		visual->offsetRed = pScrn->offset.red;
739		visual->offsetGreen = pScrn->offset.green;
740		visual->offsetBlue = pScrn->offset.blue;
741		visual->redMask = pScrn->mask.red;
742		visual->greenMask = pScrn->mask.green;
743		visual->blueMask = pScrn->mask.blue;
744	    }
745	}
746    }
747
748    if (!fbPictureInit(pScreen, NULL, 0) &&
749	(serverGeneration == 1))
750      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
751		 "RENDER extension initialisation failed.\n");
752
753    xf86SetBlackWhitePixels(pScreen);
754
755    if (!pFfb->NoAccel) {
756	char *optstr;
757	optstr = (char *)xf86GetOptValString(pFfb->Options, OPTION_ACCELMETHOD);
758#ifdef HAVE_XAA_H
759	if (optstr == NULL) optstr = "xaa";
760#else
761	if (optstr == NULL) optstr = "exa";
762#endif
763	if (xf86NameCmp(optstr, "EXA") == 0) {
764	    xf86Msg(X_INFO, "using EXA\n");
765	    if (xf86LoadSubModule(pScrn, "exa") == NULL ||
766		!FFBInitEXA(pScreen)) {
767		pFfb->NoAccel = TRUE;
768		return FALSE;
769    	    }
770    	}
771#ifdef HAVE_XAA_H
772    	  else if (xf86NameCmp(optstr, "XAA") == 0) {
773	    xf86Msg(X_INFO, "using XAA\n");
774	    if (xf86LoadSubModule(pScrn, "xaa") == NULL ||
775		!FFBAccelInit(pScreen, pFfb)) {
776		pFfb->NoAccel = TRUE;
777		return FALSE;
778	    }
779	}
780#endif
781    }
782
783
784    xf86SetBackingStore(pScreen);
785    xf86SetSilkenMouse(pScreen);
786
787    /* Initialise cursor functions */
788    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
789
790    /* Initialize HW cursor layer.
791     * Must follow software cursor initialization.
792     */
793    if (pFfb->HWCursor) {
794	if(!FFBHWCursorInit(pScreen)) {
795	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
796		       "Hardware cursor initialization failed\n");
797	    return(FALSE);
798	}
799	xf86SbusHideOsHwCursor(pFfb->psdp);
800    }
801
802    /* Initialise default colourmap. */
803    if (!miCreateDefColormap(pScreen))
804	return FALSE;
805
806    /* Initialize colormap layer.
807     * Must follow initialization of the default colormap.
808     */
809    if (!xf86HandleColormaps(pScreen, 256, 8,
810			     FFBDacLoadPalette, NULL,
811			     CMAP_LOAD_EVEN_IF_OFFSCREEN |
812			     CMAP_RELOAD_ON_MODE_SWITCH))
813	return FALSE;
814
815    /* Setup DGA support. */
816    if (!pFfb->NoAccel)
817	    FFB_InitDGA(pScreen);
818
819    xf86DPMSInit(pScreen, FFBDPMSSet, 0);
820
821    pFfb->CloseScreen = pScreen->CloseScreen;
822    pScreen->CloseScreen = FFBCloseScreen;
823    pScreen->SaveScreen = FFBSaveScreen;
824
825    (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
826
827    /* Report any unused options (only for the first generation) */
828    if (serverGeneration == 1) {
829	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
830    }
831
832    /* unblank the screen */
833    /* XXX since we didn't blank it we don't need to unblank it here */
834    /* FFBSaveScreen(pScreen, SCREEN_SAVER_OFF); */
835
836    /* Done */
837    return TRUE;
838}
839
840
841/* Usually mandatory */
842static Bool
843FFBSwitchMode(SWITCH_MODE_ARGS_DECL)
844{
845    return TRUE;
846}
847
848
849/*
850 * This function is used to initialize the Start Address - the first
851 * displayed location in the video memory.
852 */
853/* Usually mandatory */
854static void
855FFBAdjustFrame(ADJUST_FRAME_ARGS_DECL)
856{
857    /* we don't support virtual desktops */
858    return;
859}
860
861/*
862 * This is called when VT switching back to the X server.  Its job is
863 * to reinitialise the video mode.
864 */
865
866/* Mandatory */
867static Bool
868FFBEnterVT(VT_FUNC_ARGS_DECL)
869{
870    SCRN_INFO_PTR(arg);
871    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
872
873    pFfb->vtSema = FALSE;
874    if (!pFfb->NoAccel)
875	CreatorVtChange (pScrn->pScreen, TRUE);
876    if (pFfb->HWCursor)
877	xf86SbusHideOsHwCursor (pFfb->psdp);
878
879    FFBDacEnterVT(pFfb);
880
881    return TRUE;
882}
883
884
885/*
886 * This is called when VT switching away from the X server.
887 */
888
889/* Mandatory */
890static void
891FFBLeaveVT(VT_FUNC_ARGS_DECL)
892{
893    SCRN_INFO_PTR(arg);
894    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
895
896    FFBDacLeaveVT(pFfb);
897
898    if (!pFfb->NoAccel)
899	CreatorVtChange (pScrn->pScreen, FALSE);
900
901    if (pFfb->HWCursor)
902	xf86SbusHideOsHwCursor (pFfb->psdp);
903
904    pFfb->vtSema = TRUE;
905    return;
906}
907
908
909/*
910 * This is called at the end of each server generation.  It restores the
911 * original (text) mode.  It should really also unmap the video memory too.
912 */
913
914/* Mandatory */
915static Bool
916FFBCloseScreen(CLOSE_SCREEN_ARGS_DECL)
917{
918	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
919	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
920
921	FFBDacCursorEnableDisable(pFfb, 0);
922	/* Restore kernel ramdac state before we unmap registers. */
923	FFBDacFini(pFfb);
924
925	pScrn->vtSema = FALSE;
926
927	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb24, 0x1000000);
928	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8r, 0x400000);
929	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8x, 0x400000);
930	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb32, 0x1000000);
931	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8r, 0x400000);
932	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8x, 0x400000);
933	xf86UnmapSbusMem(pFfb->psdp, pFfb->regs, 16384);
934	xf86UnmapSbusMem(pFfb->psdp, pFfb->dac, 8192);
935	xf86UnmapSbusMem(pFfb->psdp, (void *)pFfb->strapping_bits, 8192);
936
937	if (pFfb->HWCursor)
938		xf86SbusHideOsHwCursor (pFfb->psdp);
939
940	pScreen->CloseScreen = pFfb->CloseScreen;
941	return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
942}
943
944
945/* Free up any per-generation data structures */
946
947/* Optional */
948static void
949FFBFreeScreen(FREE_SCREEN_ARGS_DECL)
950{
951	SCRN_INFO_PTR(arg);
952	FFBFreeRec(pScrn);
953}
954
955
956/* Checks if a mode is suitable for the selected chipset. */
957
958/* Optional */
959static ModeStatus
960FFBValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
961{
962	if (mode->Flags & V_INTERLACE)
963		return MODE_BAD;
964
965	return MODE_OK;
966}
967
968/* Do screen blanking */
969
970/* Mandatory */
971static Bool
972FFBSaveScreen(ScreenPtr pScreen, int mode)
973    /* This function blanks the screen when mode=SCREEN_SAVER_ON and
974       unblanks it when mode=SCREEN_SAVER_OFF.  It is used internally in the
975       FFBScreenInit code `for aesthetic reasons,' and it is used for
976       blanking if you set "xset s on s blank."  The work (such as it is) is
977       done in "ffb_dac.c" `for aesthetic reasons.'
978    */
979{
980
981    return FFBDacSaveScreen(pScreen, mode);
982}
983
984static void
985FFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
986{
987	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
988
989	FFBDacDPMSMode(pFfb, mode, 0);
990}
991
992/*
993 * This is the implementation of the Sync() function.
994 */
995void
996FFBSync(ScrnInfoPtr pScrn)
997{
998    return;
999}
1000
1001/*
1002  Hook for DPMS Mode.
1003*/
1004
1005static void
1006FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
1007{
1008  FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
1009}
1010
1011static Bool
1012FFBDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
1013    pointer ptr)
1014{
1015	xorgHWFlags *flag;
1016
1017	switch (op) {
1018	case GET_REQUIRED_HW_INTERFACES:
1019		flag = (CARD32*)ptr;
1020		(*flag) = HW_MMIO;
1021		return TRUE;
1022	default:
1023		return FALSE;
1024	}
1025}
1026
1027