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