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