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