ffb_driver.c revision e33a93fd
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
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
656    /* Probe for the type of FFB/AFB we have. */
657    FFBProbeBoardType(pFfb);
658
659    /* Now that we have the board type, we can init the ramdac layer. */
660    if (FFBDacInit(pFfb) == FALSE)
661	return FALSE;
662
663    /* OK, a fun gross hack to detect if this is
664     * AFB and if so whether the correct firmware
665     * has been loaded.  The machine will flatline
666     * if you try to use certain acceleration features
667     * without the full firmware loaded.
668     *
669     * The bootup Elite3D/AFB firmware is minimal, and
670     * will leave the FloatEnableMask register at a
671     * value of 0x01.  Creator{,3D} lacks the FEM register
672     * and will return a "nonsense" value on attempts to
673     * read this location.  After experimentation, an
674     * appropriate definition for "nonsense" seems to
675     * be anything with all low 7 bits not 0x3f, 0x07,
676     * of 0x01.
677     *
678     * If the FEM register is non-zero and is some value
679     * other than 0x1 (usually 0x3f or 0x7 depending upon
680     * whether the card has 3 or 6 floats) we can assume
681     * the correct firmware has been loaded. -DaveM
682     */
683    afb_fem = *(unsigned int *)((char *)pFfb->regs + 0x1540);
684    if ((afb_fem & 0x7f) != 0x3f &&
685	(afb_fem & 0x7f) != 0x07 &&
686	(afb_fem & 0x7f) != 0x01)
687	xf86Msg(X_INFO, "%s: Detected Creator/Creator3D\n", pFfb->psdp->device);
688    else {
689	xf86Msg(X_INFO, "%s: Detected Elite3D M3/M6, checking firmware...\n", pFfb->psdp->device);
690	if (afb_fem == 0x1) {
691	    xf86Msg(X_INFO, "%s: ... AFB firmware not loaded\n", pFfb->psdp->device);
692	    if (!pFfb->NoAccel) {
693		xf86Msg(X_WARNING, "%s: Forcing no acceleration on Elite3D M3/M6\n", pFfb->psdp->device);
694		pFfb->NoAccel = TRUE;
695	    }
696	} else
697	    xf86Msg(X_INFO, "%s: ... AFB firmware is loaded\n", pFfb->psdp->device);
698    }
699
700    /* Darken the screen for aesthetic reasons and set the viewport */
701    /* XXX can't do this yet */
702    /* FFBSaveScreen(pScreen, SCREEN_SAVER_ON);*/
703
704    /*
705     * The next step is to setup the screen's visuals, and initialise the
706     * framebuffer code.  In cases where the framebuffer's default
707     * choices for things like visual layouts and bits per RGB are OK,
708     * this may be as simple as calling the framebuffer's ScreenInit()
709     * function.  If not, the visuals will need to be setup before calling
710     * a fb ScreenInit() function and fixed up after.
711     */
712
713    /*
714     * Reset visual list.
715     */
716    miClearVisualTypes();
717
718    /* Setup the visuals we support. */
719    if (!miSetVisualTypes(24, TrueColorMask,
720			  pScrn->rgbBits, TrueColor))
721	    return FALSE;
722
723    if (!miSetPixmapDepths())
724        return FALSE;
725
726    /*
727     * Call the framebuffer layer's ScreenInit function, and fill in other
728     * pScreen fields.
729     */
730    ret = fbScreenInit(pScreen, (pFfb->NoAccel ? pFfb->dfb24 : pFfb->sfb32),
731		       pScrn->virtualX, pScrn->virtualY,
732		       pScrn->xDpi, pScrn->yDpi,
733		       2048, 32);
734
735    if (!ret)
736	return FALSE;
737
738    if (pScrn->bitsPerPixel > 8) {
739        /* Fixup RGB ordering */
740        visual = pScreen->visuals + pScreen->numVisuals;
741        while (--visual >= pScreen->visuals) {
742	    if ((visual->class | DynamicClass) == DirectColor) {
743		visual->offsetRed = pScrn->offset.red;
744		visual->offsetGreen = pScrn->offset.green;
745		visual->offsetBlue = pScrn->offset.blue;
746		visual->redMask = pScrn->mask.red;
747		visual->greenMask = pScrn->mask.green;
748		visual->blueMask = pScrn->mask.blue;
749	    }
750	}
751    }
752
753    if (!fbPictureInit(pScreen, NULL, 0) &&
754	(serverGeneration == 1))
755      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
756		 "RENDER extension initialisation failed.\n");
757
758    xf86SetBlackWhitePixels(pScreen);
759
760    if (!pFfb->NoAccel) {
761	if (!FFBAccelInit(pScreen, pFfb))
762	    return FALSE;
763	xf86Msg(X_INFO, "%s: Using acceleration\n", pFfb->psdp->device);
764    }
765
766
767    miInitializeBackingStore(pScreen);
768    xf86SetBackingStore(pScreen);
769    xf86SetSilkenMouse(pScreen);
770
771    /* Initialise cursor functions */
772    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
773
774    /* Initialize HW cursor layer.
775     * Must follow software cursor initialization.
776     */
777    if (pFfb->HWCursor) {
778	if(!FFBHWCursorInit(pScreen)) {
779	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
780		       "Hardware cursor initialization failed\n");
781	    return(FALSE);
782	}
783	xf86SbusHideOsHwCursor(pFfb->psdp);
784    }
785
786    /* Initialise default colourmap. */
787    if (!miCreateDefColormap(pScreen))
788	return FALSE;
789
790    /* Initialize colormap layer.
791     * Must follow initialization of the default colormap.
792     */
793    if (!xf86HandleColormaps(pScreen, 256, 8,
794			     FFBDacLoadPalette, NULL,
795			     CMAP_LOAD_EVEN_IF_OFFSCREEN |
796			     CMAP_RELOAD_ON_MODE_SWITCH))
797	return FALSE;
798
799    /* Setup DGA support. */
800    if (!pFfb->NoAccel)
801	    FFB_InitDGA(pScreen);
802
803    xf86DPMSInit(pScreen, FFBDPMSSet, 0);
804
805    pFfb->CloseScreen = pScreen->CloseScreen;
806    pScreen->CloseScreen = FFBCloseScreen;
807    pScreen->SaveScreen = FFBSaveScreen;
808
809    (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
810
811    /* Report any unused options (only for the first generation) */
812    if (serverGeneration == 1) {
813	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
814    }
815
816    /* unblank the screen */
817    /* XXX since we didn't blank it we don't need to unblank it here */
818    /* FFBSaveScreen(pScreen, SCREEN_SAVER_OFF); */
819
820    /* Done */
821    return TRUE;
822}
823
824
825/* Usually mandatory */
826static Bool
827FFBSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
828{
829    return TRUE;
830}
831
832
833/*
834 * This function is used to initialize the Start Address - the first
835 * displayed location in the video memory.
836 */
837/* Usually mandatory */
838static void
839FFBAdjustFrame(int scrnIndex, int x, int y, int flags)
840{
841    /* we don't support virtual desktops */
842    return;
843}
844
845/*
846 * This is called when VT switching back to the X server.  Its job is
847 * to reinitialise the video mode.
848 */
849
850/* Mandatory */
851static Bool
852FFBEnterVT(int scrnIndex, int flags)
853{
854    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
855    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
856
857    pFfb->vtSema = FALSE;
858    if (!pFfb->NoAccel)
859	CreatorVtChange (pScrn->pScreen, TRUE);
860    if (pFfb->HWCursor)
861	xf86SbusHideOsHwCursor (pFfb->psdp);
862
863    FFBDacEnterVT(pFfb);
864
865    return TRUE;
866}
867
868
869/*
870 * This is called when VT switching away from the X server.
871 */
872
873/* Mandatory */
874static void
875FFBLeaveVT(int scrnIndex, int flags)
876{
877    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
878    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
879
880    FFBDacLeaveVT(pFfb);
881
882    if (!pFfb->NoAccel)
883	CreatorVtChange (pScrn->pScreen, FALSE);
884
885    if (pFfb->HWCursor)
886	xf86SbusHideOsHwCursor (pFfb->psdp);
887
888    pFfb->vtSema = TRUE;
889    return;
890}
891
892
893/*
894 * This is called at the end of each server generation.  It restores the
895 * original (text) mode.  It should really also unmap the video memory too.
896 */
897
898/* Mandatory */
899static Bool
900FFBCloseScreen(int scrnIndex, ScreenPtr pScreen)
901{
902	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
903	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
904
905	FFBDacCursorEnableDisable(pFfb, 0);
906	/* Restore kernel ramdac state before we unmap registers. */
907	FFBDacFini(pFfb);
908
909	pScrn->vtSema = FALSE;
910
911	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb24, 0x1000000);
912	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8r, 0x400000);
913	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8x, 0x400000);
914	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb32, 0x1000000);
915	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8r, 0x400000);
916	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8x, 0x400000);
917	xf86UnmapSbusMem(pFfb->psdp, pFfb->regs, 16384);
918	xf86UnmapSbusMem(pFfb->psdp, pFfb->dac, 8192);
919	xf86UnmapSbusMem(pFfb->psdp, (void *)pFfb->strapping_bits, 8192);
920
921	if (pFfb->HWCursor)
922		xf86SbusHideOsHwCursor (pFfb->psdp);
923
924	pScreen->CloseScreen = pFfb->CloseScreen;
925	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
926}
927
928
929/* Free up any per-generation data structures */
930
931/* Optional */
932static void
933FFBFreeScreen(int scrnIndex, int flags)
934{
935	FFBFreeRec(xf86Screens[scrnIndex]);
936}
937
938
939/* Checks if a mode is suitable for the selected chipset. */
940
941/* Optional */
942static ModeStatus
943FFBValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
944{
945	if (mode->Flags & V_INTERLACE)
946		return MODE_BAD;
947
948	return MODE_OK;
949}
950
951/* Do screen blanking */
952
953/* Mandatory */
954static Bool
955FFBSaveScreen(ScreenPtr pScreen, int mode)
956    /* This function blanks the screen when mode=SCREEN_SAVER_ON and
957       unblanks it when mode=SCREEN_SAVER_OFF.  It is used internally in the
958       FFBScreenInit code `for aesthetic reasons,' and it is used for
959       blanking if you set "xset s on s blank."  The work (such as it is) is
960       done in "ffb_dac.c" `for aesthetic reasons.'
961    */
962{
963
964    return FFBDacSaveScreen(pScreen, mode);
965}
966
967static void
968FFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
969{
970	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
971
972	FFBDacDPMSMode(pFfb, mode, 0);
973}
974
975/*
976 * This is the implementation of the Sync() function.
977 */
978void
979FFBSync(ScrnInfoPtr pScrn)
980{
981    return;
982}
983
984/*
985  Hook for DPMS Mode.
986*/
987
988static void
989FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
990{
991  FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
992}
993