ffb_driver.c revision dbbd9e4b
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
30dbbd9e4bSmacallan#include "xf86.h"
31dbbd9e4bSmacallan#include "xf86_OSproc.h"
32dbbd9e4bSmacallan#include "mipointer.h"
33dbbd9e4bSmacallan#include "mibstore.h"
34dbbd9e4bSmacallan#include "micmap.h"
35dbbd9e4bSmacallan#include "fb.h"
36dbbd9e4bSmacallan
37dbbd9e4bSmacallan#include "xf86cmap.h"
38dbbd9e4bSmacallan
39dbbd9e4bSmacallan#include "ffb.h"
40dbbd9e4bSmacallan
41dbbd9e4bSmacallanstatic const OptionInfoRec * FFBAvailableOptions(int chipid, int busid);
42dbbd9e4bSmacallanstatic void	FFBIdentify(int flags);
43dbbd9e4bSmacallanstatic Bool	FFBProbe(DriverPtr drv, int flags);
44dbbd9e4bSmacallanstatic Bool	FFBPreInit(ScrnInfoPtr pScrn, int flags);
45dbbd9e4bSmacallanstatic Bool	FFBScreenInit(int Index, ScreenPtr pScreen, int argc,
46dbbd9e4bSmacallan			      char **argv);
47dbbd9e4bSmacallanstatic Bool	FFBEnterVT(int scrnIndex, int flags);
48dbbd9e4bSmacallanstatic void	FFBLeaveVT(int scrnIndex, int flags);
49dbbd9e4bSmacallanstatic Bool	FFBCloseScreen(int scrnIndex, ScreenPtr pScreen);
50dbbd9e4bSmacallanstatic Bool	FFBSaveScreen(ScreenPtr pScreen, int mode);
51dbbd9e4bSmacallanstatic void	FFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags);
52dbbd9e4bSmacallan
53dbbd9e4bSmacallan/* Required if the driver supports mode switching */
54dbbd9e4bSmacallanstatic Bool	FFBSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
55dbbd9e4bSmacallan/* Required if the driver supports moving the viewport */
56dbbd9e4bSmacallanstatic void	FFBAdjustFrame(int scrnIndex, int x, int y, int flags);
57dbbd9e4bSmacallan
58dbbd9e4bSmacallan/* Optional functions */
59dbbd9e4bSmacallanstatic void	FFBFreeScreen(int scrnIndex, int flags);
60dbbd9e4bSmacallanstatic ModeStatus FFBValidMode(int scrnIndex, DisplayModePtr mode,
61dbbd9e4bSmacallan			       Bool verbose, int flags);
62dbbd9e4bSmacallanstatic void     FFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags);
63dbbd9e4bSmacallan/* ffb_dga.c */
64dbbd9e4bSmacallanextern void FFB_InitDGA(ScreenPtr pScreen);
65dbbd9e4bSmacallan
66dbbd9e4bSmacallanvoid FFBSync(ScrnInfoPtr pScrn);
67dbbd9e4bSmacallan
68dbbd9e4bSmacallan#define FFB_VERSION 4000
69dbbd9e4bSmacallan#define FFB_NAME "SUNFFB"
70dbbd9e4bSmacallan#define FFB_DRIVER_NAME "sunffb"
71dbbd9e4bSmacallan#define FFB_MAJOR_VERSION PACKAGE_VERSION_MAJOR
72dbbd9e4bSmacallan#define FFB_MINOR_VERSION PACKAGE_VERSION_MINOR
73dbbd9e4bSmacallan#define FFB_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
74dbbd9e4bSmacallan
75dbbd9e4bSmacallan/*
76dbbd9e4bSmacallan * This contains the functions needed by the server after loading the driver
77dbbd9e4bSmacallan * module.  It must be supplied, and gets passed back by the SetupProc
78dbbd9e4bSmacallan * function in the dynamic case.  In the static case, a reference to this
79dbbd9e4bSmacallan * is compiled in, and this requires that the name of this DriverRec be
80dbbd9e4bSmacallan * an upper-case version of the driver name.
81dbbd9e4bSmacallan */
82dbbd9e4bSmacallan
83dbbd9e4bSmacallan_X_EXPORT DriverRec SUNFFB = {
84dbbd9e4bSmacallan    FFB_VERSION,
85dbbd9e4bSmacallan    FFB_DRIVER_NAME,
86dbbd9e4bSmacallan    FFBIdentify,
87dbbd9e4bSmacallan    FFBProbe,
88dbbd9e4bSmacallan    FFBAvailableOptions,
89dbbd9e4bSmacallan    NULL,
90dbbd9e4bSmacallan    0
91dbbd9e4bSmacallan};
92dbbd9e4bSmacallan
93dbbd9e4bSmacallantypedef enum {
94dbbd9e4bSmacallan    OPTION_SW_CURSOR,
95dbbd9e4bSmacallan    OPTION_HW_CURSOR,
96dbbd9e4bSmacallan    OPTION_NOACCEL
97dbbd9e4bSmacallan} FFBOpts;
98dbbd9e4bSmacallan
99dbbd9e4bSmacallanstatic const OptionInfoRec FFBOptions[] = {
100dbbd9e4bSmacallan    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
101dbbd9e4bSmacallan    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
102dbbd9e4bSmacallan    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
103dbbd9e4bSmacallan    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
104dbbd9e4bSmacallan};
105dbbd9e4bSmacallan
106dbbd9e4bSmacallan#ifdef XFree86LOADER
107dbbd9e4bSmacallan
108dbbd9e4bSmacallanstatic MODULESETUPPROTO(ffbSetup);
109dbbd9e4bSmacallan
110dbbd9e4bSmacallanstatic XF86ModuleVersionInfo sunffbVersRec =
111dbbd9e4bSmacallan{
112dbbd9e4bSmacallan	"sunffb",
113dbbd9e4bSmacallan	MODULEVENDORSTRING,
114dbbd9e4bSmacallan	MODINFOSTRING1,
115dbbd9e4bSmacallan	MODINFOSTRING2,
116dbbd9e4bSmacallan	XORG_VERSION_CURRENT,
117dbbd9e4bSmacallan	FFB_MAJOR_VERSION, FFB_MINOR_VERSION, FFB_PATCHLEVEL,
118dbbd9e4bSmacallan	ABI_CLASS_VIDEODRV,
119dbbd9e4bSmacallan	ABI_VIDEODRV_VERSION,
120dbbd9e4bSmacallan	MOD_CLASS_VIDEODRV,
121dbbd9e4bSmacallan	{0,0,0,0}
122dbbd9e4bSmacallan};
123dbbd9e4bSmacallan
124dbbd9e4bSmacallan_X_EXPORT XF86ModuleData sunffbModuleData = { &sunffbVersRec, ffbSetup, NULL };
125dbbd9e4bSmacallan
126dbbd9e4bSmacallanpointer
127dbbd9e4bSmacallanffbSetup(pointer module, pointer opts, int *errmaj, int *errmin)
128dbbd9e4bSmacallan{
129dbbd9e4bSmacallan    static Bool setupDone = FALSE;
130dbbd9e4bSmacallan
131dbbd9e4bSmacallan    if (!setupDone) {
132dbbd9e4bSmacallan	setupDone = TRUE;
133dbbd9e4bSmacallan	xf86AddDriver(&SUNFFB, module, 0);
134dbbd9e4bSmacallan
135dbbd9e4bSmacallan	/*
136dbbd9e4bSmacallan	 * Modules that this driver always requires can be loaded here
137dbbd9e4bSmacallan	 * by calling LoadSubModule().
138dbbd9e4bSmacallan	 */
139dbbd9e4bSmacallan
140dbbd9e4bSmacallan	/*
141dbbd9e4bSmacallan	 * The return value must be non-NULL on success even though there
142dbbd9e4bSmacallan	 * is no TearDownProc.
143dbbd9e4bSmacallan	 */
144dbbd9e4bSmacallan	return (pointer)TRUE;
145dbbd9e4bSmacallan    } else {
146dbbd9e4bSmacallan	if (errmaj) *errmaj = LDR_ONCEONLY;
147dbbd9e4bSmacallan	return NULL;
148dbbd9e4bSmacallan    }
149dbbd9e4bSmacallan}
150dbbd9e4bSmacallan
151dbbd9e4bSmacallan#endif /* XFree86LOADER */
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
178dbbd9e4bSmacallan    xfree(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
248dbbd9e4bSmacallan    xfree(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	}
282dbbd9e4bSmacallan	xfree(pEnt);
283dbbd9e4bSmacallan    }
284dbbd9e4bSmacallan    xfree(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 */
359dbbd9e4bSmacallan    if (!(pFfb->Options = xalloc(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 (xf86LoadSubModule(pScrn, "xaa") == NULL) {
419dbbd9e4bSmacallan	FFBFreeRec(pScrn);
420dbbd9e4bSmacallan	return FALSE;
421dbbd9e4bSmacallan    }
422dbbd9e4bSmacallan
423dbbd9e4bSmacallan    if (pFfb->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
424dbbd9e4bSmacallan	FFBFreeRec(pScrn);
425dbbd9e4bSmacallan	return FALSE;
426dbbd9e4bSmacallan    }
427dbbd9e4bSmacallan
428dbbd9e4bSmacallan    if (xf86LoadSubModule(pScrn, "dbe") == NULL) {
429dbbd9e4bSmacallan	FFBFreeRec(pScrn);
430dbbd9e4bSmacallan	return FALSE;
431dbbd9e4bSmacallan    }
432dbbd9e4bSmacallan
433dbbd9e4bSmacallan
434dbbd9e4bSmacallan    /*********************
435dbbd9e4bSmacallan    set up clock and mode stuff
436dbbd9e4bSmacallan    *********************/
437dbbd9e4bSmacallan
438dbbd9e4bSmacallan    pScrn->progClock = TRUE;
439dbbd9e4bSmacallan
440dbbd9e4bSmacallan    if(pScrn->display->virtualX || pScrn->display->virtualY) {
441dbbd9e4bSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
442dbbd9e4bSmacallan		   "FFB does not support a virtual desktop\n");
443dbbd9e4bSmacallan	pScrn->display->virtualX = 0;
444dbbd9e4bSmacallan	pScrn->display->virtualY = 0;
445dbbd9e4bSmacallan    }
446dbbd9e4bSmacallan
447dbbd9e4bSmacallan    xf86SbusUseBuiltinMode(pScrn, pFfb->psdp);
448dbbd9e4bSmacallan    pScrn->currentMode = pScrn->modes;
449dbbd9e4bSmacallan    pScrn->displayWidth = pScrn->virtualX;
450dbbd9e4bSmacallan
451dbbd9e4bSmacallan    /* Set display resolution */
452dbbd9e4bSmacallan    xf86SetDpi(pScrn, 0, 0);
453dbbd9e4bSmacallan
454dbbd9e4bSmacallan    return TRUE;
455dbbd9e4bSmacallan}
456dbbd9e4bSmacallan
457dbbd9e4bSmacallan/* Determine the FFB/AFB board type.  We need this information even
458dbbd9e4bSmacallan * if acceleration is disabled because the ramdac support layer needs
459dbbd9e4bSmacallan * to know what kind of FFB/AFB this is.
460dbbd9e4bSmacallan */
461dbbd9e4bSmacallanstatic void
462dbbd9e4bSmacallanFFBProbeBoardType(FFBPtr pFfb)
463dbbd9e4bSmacallan{
464dbbd9e4bSmacallan	ffb_fbcPtr ffb = pFfb->regs;
465dbbd9e4bSmacallan	volatile unsigned int *afb_fem;
466dbbd9e4bSmacallan	unsigned int val;
467dbbd9e4bSmacallan
468dbbd9e4bSmacallan	afb_fem = ((volatile unsigned int *) ((char *)ffb + 0x1540));
469dbbd9e4bSmacallan	val = *afb_fem;
470dbbd9e4bSmacallan	val &= 0x7f;
471dbbd9e4bSmacallan
472dbbd9e4bSmacallan	xf86Msg(X_INFO, "%s: ", pFfb->psdp->device);
473dbbd9e4bSmacallan	if (val == 0x3f || val == 0x07 || val == 0x01) {
474dbbd9e4bSmacallan		/* When firmware has not been loaded onto AFB we
475dbbd9e4bSmacallan		 * just assume it is an M6 board.
476dbbd9e4bSmacallan		 */
477dbbd9e4bSmacallan		if (val == 0x3f || val != 0x07) {
478dbbd9e4bSmacallan			pFfb->ffb_type = afb_m6;
479dbbd9e4bSmacallan			ErrorF("AFB: Detected Elite3D/M6.\n");
480dbbd9e4bSmacallan		} else {
481dbbd9e4bSmacallan			pFfb->ffb_type = afb_m3;
482dbbd9e4bSmacallan			ErrorF("AFB: Detected Elite3D/M3.\n");
483dbbd9e4bSmacallan		}
484dbbd9e4bSmacallan
485dbbd9e4bSmacallan		/* These attributes are invariant on AFB. */
486dbbd9e4bSmacallan		pFfb->has_double_res = 0;
487dbbd9e4bSmacallan		pFfb->has_z_buffer = 1;
488dbbd9e4bSmacallan		pFfb->has_double_buffer = 1;
489dbbd9e4bSmacallan	} else {
490dbbd9e4bSmacallan		unsigned char sbits;
491dbbd9e4bSmacallan		//xf86Msg(X_ERROR,"ffb?");
492dbbd9e4bSmacallan		/* Read the board strapping bits twice, because sometimes
493dbbd9e4bSmacallan		 * the strapping pins can get misrouted to the bus interface
494dbbd9e4bSmacallan		 * on the first attempt.  The second attempt will get the
495dbbd9e4bSmacallan		 * correct value.
496dbbd9e4bSmacallan		 */
497dbbd9e4bSmacallan		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
498dbbd9e4bSmacallan		sbits = *((volatile unsigned char *)pFfb->strapping_bits);
499dbbd9e4bSmacallan		switch (sbits & 0x78) {
500dbbd9e4bSmacallan		case (0x0 << 5) | (0x0 << 3):
501dbbd9e4bSmacallan			pFfb->ffb_type = ffb1_prototype;
502dbbd9e4bSmacallan			ErrorF("Detected FFB1 pre-FCS prototype, ");
503dbbd9e4bSmacallan			break;
504dbbd9e4bSmacallan		case (0x0 << 5) | (0x1 << 3):
505dbbd9e4bSmacallan			pFfb->ffb_type = ffb1_standard;
506dbbd9e4bSmacallan			ErrorF("Detected FFB1, ");
507dbbd9e4bSmacallan			break;
508dbbd9e4bSmacallan		case (0x0 << 5) | (0x3 << 3):
509dbbd9e4bSmacallan			pFfb->ffb_type = ffb1_speedsort;
510dbbd9e4bSmacallan			ErrorF("Detected FFB1-SpeedSort, ");
511dbbd9e4bSmacallan			break;
512dbbd9e4bSmacallan		case (0x1 << 5) | (0x0 << 3):
513dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_prototype;
514dbbd9e4bSmacallan			ErrorF("Detected FFB2/vertical pre-FCS prototype, ");
515dbbd9e4bSmacallan			break;
516dbbd9e4bSmacallan		case (0x1 << 5) | (0x1 << 3):
517dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_vertical;
518dbbd9e4bSmacallan			ErrorF("Detected FFB2/vertical, ");
519dbbd9e4bSmacallan			break;
520dbbd9e4bSmacallan		case (0x1 << 5) | (0x2 << 3):
521dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_vertical_plus;
522dbbd9e4bSmacallan			ErrorF("Detected FFB2+/vertical, ");
523dbbd9e4bSmacallan			break;
524dbbd9e4bSmacallan		case (0x2 << 5) | (0x0 << 3):
525dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_horizontal;
526dbbd9e4bSmacallan			ErrorF("Detected FFB2/horizontal, ");
527dbbd9e4bSmacallan			break;
528dbbd9e4bSmacallan		case (0x2 << 5) | (0x2 << 3):
529dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_horizontal;
530dbbd9e4bSmacallan			ErrorF("Detected FFB2+/horizontal, ");
531dbbd9e4bSmacallan			break;
532dbbd9e4bSmacallan		default:
533dbbd9e4bSmacallan			pFfb->ffb_type = ffb2_vertical;
534dbbd9e4bSmacallan			ErrorF("Unknown boardID[%08x], assuming FFB2, ", sbits);
535dbbd9e4bSmacallan			break;
536dbbd9e4bSmacallan		};
537dbbd9e4bSmacallan
538dbbd9e4bSmacallan		if (sbits & (1 << 2)) {
539dbbd9e4bSmacallan			ErrorF("DoubleRES, ");
540dbbd9e4bSmacallan			pFfb->has_double_res = 1;
541dbbd9e4bSmacallan		} else {
542dbbd9e4bSmacallan			pFfb->has_double_res = 0;
543dbbd9e4bSmacallan		}
544dbbd9e4bSmacallan		if (sbits & (1 << 1)) {
545dbbd9e4bSmacallan			ErrorF("Z-buffer, ");
546dbbd9e4bSmacallan			pFfb->has_z_buffer = 1;
547dbbd9e4bSmacallan		} else {
548dbbd9e4bSmacallan			pFfb->has_z_buffer = 0;
549dbbd9e4bSmacallan		}
550dbbd9e4bSmacallan		if (sbits & (1 << 0)) {
551dbbd9e4bSmacallan			/* This state really means to the driver that the double
552dbbd9e4bSmacallan			 * buffers are available for hw accelerate Dbe.  When the
553dbbd9e4bSmacallan			 * FFB is in high-resolution mode, the buffers are combined
554dbbd9e4bSmacallan			 * into one single large framebuffer.  So in high-resolution
555dbbd9e4bSmacallan			 * hw accelerated double-buffering is not available.
556dbbd9e4bSmacallan			 */
557dbbd9e4bSmacallan			if ((ffb->fbcfg0 & FFB_FBCFG0_RES_MASK) != FFB_FBCFG0_RES_HIGH)
558dbbd9e4bSmacallan				pFfb->has_double_buffer = 1;
559dbbd9e4bSmacallan			else
560dbbd9e4bSmacallan				pFfb->has_double_buffer = 0;
561dbbd9e4bSmacallan		} else {
562dbbd9e4bSmacallan			pFfb->has_double_buffer = 0;
563dbbd9e4bSmacallan		}
564dbbd9e4bSmacallan		if (pFfb->has_double_buffer)
565dbbd9e4bSmacallan			ErrorF("Double-buffered.\n");
566dbbd9e4bSmacallan		else
567dbbd9e4bSmacallan			ErrorF("Single-buffered.\n");
568dbbd9e4bSmacallan	}
569dbbd9e4bSmacallan}
570dbbd9e4bSmacallan
571dbbd9e4bSmacallan/* Mandatory */
572dbbd9e4bSmacallan
573dbbd9e4bSmacallan/* This gets called at the start of each server generation */
574dbbd9e4bSmacallan
575dbbd9e4bSmacallanstatic Bool
576dbbd9e4bSmacallanFFBScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
577dbbd9e4bSmacallan{
578dbbd9e4bSmacallan    ScrnInfoPtr pScrn;
579dbbd9e4bSmacallan    FFBPtr pFfb;
580dbbd9e4bSmacallan    int ret;
581dbbd9e4bSmacallan    unsigned int afb_fem;
582dbbd9e4bSmacallan    VisualPtr visual;
583dbbd9e4bSmacallan
584dbbd9e4bSmacallan    /*
585dbbd9e4bSmacallan     * First get the ScrnInfoRec
586dbbd9e4bSmacallan     */
587dbbd9e4bSmacallan    pScrn = xf86Screens[pScreen->myNum];
588dbbd9e4bSmacallan
589dbbd9e4bSmacallan    pFfb = GET_FFB_FROM_SCRN(pScrn);
590dbbd9e4bSmacallan
591dbbd9e4bSmacallan    /* Map the FFB framebuffer, for each view. */
592dbbd9e4bSmacallan
593dbbd9e4bSmacallan    /* 24-bit RGB Dumb view */
594dbbd9e4bSmacallan    pFfb->fb = pFfb->dfb24 =
595dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_DFB24_VOFF, 0x1000000);
596dbbd9e4bSmacallan
597dbbd9e4bSmacallan    if (! pFfb->dfb24)
598dbbd9e4bSmacallan	return FALSE;
599dbbd9e4bSmacallan
600dbbd9e4bSmacallan    /* 8-bit R Dumb view */
601dbbd9e4bSmacallan    pFfb->dfb8r =
602dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_DFB8R_VOFF, 0x400000);
603dbbd9e4bSmacallan
604dbbd9e4bSmacallan    if (! pFfb->dfb8r)
605dbbd9e4bSmacallan	return FALSE;
606dbbd9e4bSmacallan
607dbbd9e4bSmacallan    /* 8-bit X Dumb view */
608dbbd9e4bSmacallan    pFfb->dfb8x =
609dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_DFB8X_VOFF, 0x400000);
610dbbd9e4bSmacallan
611dbbd9e4bSmacallan    if (! pFfb->dfb8x)
612dbbd9e4bSmacallan	return FALSE;
613dbbd9e4bSmacallan
614dbbd9e4bSmacallan    /* 32-bit RGB Smart view */
615dbbd9e4bSmacallan    pFfb->sfb32 =
616dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_SFB32_VOFF, 0x1000000);
617dbbd9e4bSmacallan
618dbbd9e4bSmacallan    if (!pFfb->sfb32)
619dbbd9e4bSmacallan	return FALSE;
620dbbd9e4bSmacallan
621dbbd9e4bSmacallan    /* 8-bit R Smart view */
622dbbd9e4bSmacallan    pFfb->sfb8r =
623dbbd9e4bSmacallan	xf86MapSbusMem(pFfb->psdp, FFB_SFB8R_VOFF, 0x400000);
624dbbd9e4bSmacallan
625dbbd9e4bSmacallan    if (!pFfb->sfb8r)
626dbbd9e4bSmacallan	return FALSE;
627dbbd9e4bSmacallan
628dbbd9e4bSmacallan    /* 8-bit X Smart view */
629dbbd9e4bSmacallan    pFfb->sfb8x =
630dbbd9e4bSmacallan	xf86MapSbusMem(pFfb->psdp, FFB_SFB8X_VOFF, 0x400000);
631dbbd9e4bSmacallan
632dbbd9e4bSmacallan    if (!pFfb->sfb8x)
633dbbd9e4bSmacallan	return FALSE;
634dbbd9e4bSmacallan
635dbbd9e4bSmacallan    /* Map the rendering pipeline */
636dbbd9e4bSmacallan    pFfb->regs =
637dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_FBC_REGS_VOFF, 16384);
638dbbd9e4bSmacallan
639dbbd9e4bSmacallan    if (! pFfb->regs)
640dbbd9e4bSmacallan	return FALSE;
641dbbd9e4bSmacallan
642dbbd9e4bSmacallan    /* Map the ramdac */
643dbbd9e4bSmacallan    pFfb->dac =
644dbbd9e4bSmacallan	xf86MapSbusMem (pFfb->psdp, FFB_DAC_VOFF, 8192);
645dbbd9e4bSmacallan
646dbbd9e4bSmacallan    if (! pFfb->dac)
647dbbd9e4bSmacallan	return FALSE;
648dbbd9e4bSmacallan
649dbbd9e4bSmacallan    /* Map the board strapping bits */
650dbbd9e4bSmacallan    pFfb->strapping_bits = (volatile unsigned int *)
651dbbd9e4bSmacallan	    xf86MapSbusMem(pFfb->psdp, FFB_EXP_VOFF, 8192);
652dbbd9e4bSmacallan
653dbbd9e4bSmacallan    if (! pFfb->strapping_bits)
654dbbd9e4bSmacallan	return FALSE;
655dbbd9e4bSmacallan    /* Probe for the type of FFB/AFB we have. */
656dbbd9e4bSmacallan    FFBProbeBoardType(pFfb);
657dbbd9e4bSmacallan
658dbbd9e4bSmacallan    /* Now that we have the board type, we can init the ramdac layer. */
659dbbd9e4bSmacallan    if (FFBDacInit(pFfb) == FALSE)
660dbbd9e4bSmacallan	return FALSE;
661dbbd9e4bSmacallan
662dbbd9e4bSmacallan    /* OK, a fun gross hack to detect if this is
663dbbd9e4bSmacallan     * AFB and if so whether the correct firmware
664dbbd9e4bSmacallan     * has been loaded.  The machine will flatline
665dbbd9e4bSmacallan     * if you try to use certain acceleration features
666dbbd9e4bSmacallan     * without the full firmware loaded.
667dbbd9e4bSmacallan     *
668dbbd9e4bSmacallan     * The bootup Elite3D/AFB firmware is minimal, and
669dbbd9e4bSmacallan     * will leave the FloatEnableMask register at a
670dbbd9e4bSmacallan     * value of 0x01.  Creator{,3D} lacks the FEM register
671dbbd9e4bSmacallan     * and will return a "nonsense" value on attempts to
672dbbd9e4bSmacallan     * read this location.  After experimentation, an
673dbbd9e4bSmacallan     * appropriate definition for "nonsense" seems to
674dbbd9e4bSmacallan     * be anything with all low 7 bits not 0x3f, 0x07,
675dbbd9e4bSmacallan     * of 0x01.
676dbbd9e4bSmacallan     *
677dbbd9e4bSmacallan     * If the FEM register is non-zero and is some value
678dbbd9e4bSmacallan     * other than 0x1 (usually 0x3f or 0x7 depending upon
679dbbd9e4bSmacallan     * whether the card has 3 or 6 floats) we can assume
680dbbd9e4bSmacallan     * the correct firmware has been loaded. -DaveM
681dbbd9e4bSmacallan     */
682dbbd9e4bSmacallan    afb_fem = *(unsigned int *)((char *)pFfb->regs + 0x1540);
683dbbd9e4bSmacallan    if ((afb_fem & 0x7f) != 0x3f &&
684dbbd9e4bSmacallan	(afb_fem & 0x7f) != 0x07 &&
685dbbd9e4bSmacallan	(afb_fem & 0x7f) != 0x01)
686dbbd9e4bSmacallan	xf86Msg(X_INFO, "%s: Detected Creator/Creator3D\n", pFfb->psdp->device);
687dbbd9e4bSmacallan    else {
688dbbd9e4bSmacallan	xf86Msg(X_INFO, "%s: Detected Elite3D M3/M6, checking firmware...\n", pFfb->psdp->device);
689dbbd9e4bSmacallan	if (afb_fem == 0x1) {
690dbbd9e4bSmacallan	    xf86Msg(X_INFO, "%s: ... AFB firmware not loaded\n", pFfb->psdp->device);
691dbbd9e4bSmacallan	    if (!pFfb->NoAccel) {
692dbbd9e4bSmacallan		xf86Msg(X_WARNING, "%s: Forcing no acceleration on Elite3D M3/M6\n", pFfb->psdp->device);
693dbbd9e4bSmacallan		pFfb->NoAccel = TRUE;
694dbbd9e4bSmacallan	    }
695dbbd9e4bSmacallan	} else
696dbbd9e4bSmacallan	    xf86Msg(X_INFO, "%s: ... AFB firmware is loaded\n", pFfb->psdp->device);
697dbbd9e4bSmacallan    }
698dbbd9e4bSmacallan
699dbbd9e4bSmacallan    /* Darken the screen for aesthetic reasons and set the viewport */
700dbbd9e4bSmacallan    FFBSaveScreen(pScreen, SCREEN_SAVER_ON);
701dbbd9e4bSmacallan
702dbbd9e4bSmacallan    /*
703dbbd9e4bSmacallan     * The next step is to setup the screen's visuals, and initialise the
704dbbd9e4bSmacallan     * framebuffer code.  In cases where the framebuffer's default
705dbbd9e4bSmacallan     * choices for things like visual layouts and bits per RGB are OK,
706dbbd9e4bSmacallan     * this may be as simple as calling the framebuffer's ScreenInit()
707dbbd9e4bSmacallan     * function.  If not, the visuals will need to be setup before calling
708dbbd9e4bSmacallan     * a fb ScreenInit() function and fixed up after.
709dbbd9e4bSmacallan     */
710dbbd9e4bSmacallan
711dbbd9e4bSmacallan    /*
712dbbd9e4bSmacallan     * Reset visual list.
713dbbd9e4bSmacallan     */
714dbbd9e4bSmacallan    miClearVisualTypes();
715dbbd9e4bSmacallan
716dbbd9e4bSmacallan    /* Setup the visuals we support. */
717dbbd9e4bSmacallan    if (!miSetVisualTypes(24, TrueColorMask,
718dbbd9e4bSmacallan			  pScrn->rgbBits, TrueColor))
719dbbd9e4bSmacallan	    return FALSE;
720dbbd9e4bSmacallan
721dbbd9e4bSmacallan    if (!miSetPixmapDepths())
722dbbd9e4bSmacallan        return FALSE;
723dbbd9e4bSmacallan
724dbbd9e4bSmacallan    /*
725dbbd9e4bSmacallan     * Call the framebuffer layer's ScreenInit function, and fill in other
726dbbd9e4bSmacallan     * pScreen fields.
727dbbd9e4bSmacallan     */
728dbbd9e4bSmacallan    ret = fbScreenInit(pScreen, (pFfb->NoAccel ? pFfb->dfb24 : pFfb->sfb32),
729dbbd9e4bSmacallan		       pScrn->virtualX, pScrn->virtualY,
730dbbd9e4bSmacallan		       pScrn->xDpi, pScrn->yDpi,
731dbbd9e4bSmacallan		       2048, 32);
732dbbd9e4bSmacallan
733dbbd9e4bSmacallan    if (!ret)
734dbbd9e4bSmacallan	return FALSE;
735dbbd9e4bSmacallan
736dbbd9e4bSmacallan    if (pScrn->bitsPerPixel > 8) {
737dbbd9e4bSmacallan        /* Fixup RGB ordering */
738dbbd9e4bSmacallan        visual = pScreen->visuals + pScreen->numVisuals;
739dbbd9e4bSmacallan        while (--visual >= pScreen->visuals) {
740dbbd9e4bSmacallan	    if ((visual->class | DynamicClass) == DirectColor) {
741dbbd9e4bSmacallan		visual->offsetRed = pScrn->offset.red;
742dbbd9e4bSmacallan		visual->offsetGreen = pScrn->offset.green;
743dbbd9e4bSmacallan		visual->offsetBlue = pScrn->offset.blue;
744dbbd9e4bSmacallan		visual->redMask = pScrn->mask.red;
745dbbd9e4bSmacallan		visual->greenMask = pScrn->mask.green;
746dbbd9e4bSmacallan		visual->blueMask = pScrn->mask.blue;
747dbbd9e4bSmacallan	    }
748dbbd9e4bSmacallan	}
749dbbd9e4bSmacallan    }
750dbbd9e4bSmacallan
751dbbd9e4bSmacallan    if (!fbPictureInit(pScreen, NULL, 0) &&
752dbbd9e4bSmacallan	(serverGeneration == 1))
753dbbd9e4bSmacallan      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
754dbbd9e4bSmacallan		 "RENDER extension initialisation failed.\n");
755dbbd9e4bSmacallan
756dbbd9e4bSmacallan    xf86SetBlackWhitePixels(pScreen);
757dbbd9e4bSmacallan
758dbbd9e4bSmacallan    if (!pFfb->NoAccel) {
759dbbd9e4bSmacallan	if (!FFBAccelInit(pScreen, pFfb))
760dbbd9e4bSmacallan	    return FALSE;
761dbbd9e4bSmacallan	xf86Msg(X_INFO, "%s: Using acceleration\n", pFfb->psdp->device);
762dbbd9e4bSmacallan    }
763dbbd9e4bSmacallan
764dbbd9e4bSmacallan
765dbbd9e4bSmacallan    miInitializeBackingStore(pScreen);
766dbbd9e4bSmacallan    xf86SetBackingStore(pScreen);
767dbbd9e4bSmacallan    xf86SetSilkenMouse(pScreen);
768dbbd9e4bSmacallan
769dbbd9e4bSmacallan    /* Initialise cursor functions */
770dbbd9e4bSmacallan    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
771dbbd9e4bSmacallan
772dbbd9e4bSmacallan    /* Initialize HW cursor layer.
773dbbd9e4bSmacallan     * Must follow software cursor initialization.
774dbbd9e4bSmacallan     */
775dbbd9e4bSmacallan    if (pFfb->HWCursor) {
776dbbd9e4bSmacallan	if(!FFBHWCursorInit(pScreen)) {
777dbbd9e4bSmacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
778dbbd9e4bSmacallan		       "Hardware cursor initialization failed\n");
779dbbd9e4bSmacallan	    return(FALSE);
780dbbd9e4bSmacallan	}
781dbbd9e4bSmacallan	xf86SbusHideOsHwCursor(pFfb->psdp);
782dbbd9e4bSmacallan    }
783dbbd9e4bSmacallan
784dbbd9e4bSmacallan    /* Initialise default colourmap. */
785dbbd9e4bSmacallan    if (!miCreateDefColormap(pScreen))
786dbbd9e4bSmacallan	return FALSE;
787dbbd9e4bSmacallan
788dbbd9e4bSmacallan    /* Initialize colormap layer.
789dbbd9e4bSmacallan     * Must follow initialization of the default colormap.
790dbbd9e4bSmacallan     */
791dbbd9e4bSmacallan    if (!xf86HandleColormaps(pScreen, 256, 8,
792dbbd9e4bSmacallan			     FFBDacLoadPalette, NULL,
793dbbd9e4bSmacallan			     CMAP_LOAD_EVEN_IF_OFFSCREEN |
794dbbd9e4bSmacallan			     CMAP_RELOAD_ON_MODE_SWITCH))
795dbbd9e4bSmacallan	return FALSE;
796dbbd9e4bSmacallan
797dbbd9e4bSmacallan    /* Setup DGA support. */
798dbbd9e4bSmacallan    if (!pFfb->NoAccel)
799dbbd9e4bSmacallan	    FFB_InitDGA(pScreen);
800dbbd9e4bSmacallan
801dbbd9e4bSmacallan    xf86DPMSInit(pScreen, FFBDPMSSet, 0);
802dbbd9e4bSmacallan
803dbbd9e4bSmacallan    pFfb->CloseScreen = pScreen->CloseScreen;
804dbbd9e4bSmacallan    pScreen->CloseScreen = FFBCloseScreen;
805dbbd9e4bSmacallan    pScreen->SaveScreen = FFBSaveScreen;
806dbbd9e4bSmacallan
807dbbd9e4bSmacallan    (void) xf86DPMSInit(pScreen, FFBDPMSMode, 0);
808dbbd9e4bSmacallan
809dbbd9e4bSmacallan    /* Report any unused options (only for the first generation) */
810dbbd9e4bSmacallan    if (serverGeneration == 1) {
811dbbd9e4bSmacallan	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
812dbbd9e4bSmacallan    }
813dbbd9e4bSmacallan
814dbbd9e4bSmacallan    /* unblank the screen */
815dbbd9e4bSmacallan    FFBSaveScreen(pScreen, SCREEN_SAVER_OFF);
816dbbd9e4bSmacallan
817dbbd9e4bSmacallan    /* Done */
818dbbd9e4bSmacallan    return TRUE;
819dbbd9e4bSmacallan}
820dbbd9e4bSmacallan
821dbbd9e4bSmacallan
822dbbd9e4bSmacallan/* Usually mandatory */
823dbbd9e4bSmacallanstatic Bool
824dbbd9e4bSmacallanFFBSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
825dbbd9e4bSmacallan{
826dbbd9e4bSmacallan    return TRUE;
827dbbd9e4bSmacallan}
828dbbd9e4bSmacallan
829dbbd9e4bSmacallan
830dbbd9e4bSmacallan/*
831dbbd9e4bSmacallan * This function is used to initialize the Start Address - the first
832dbbd9e4bSmacallan * displayed location in the video memory.
833dbbd9e4bSmacallan */
834dbbd9e4bSmacallan/* Usually mandatory */
835dbbd9e4bSmacallanstatic void
836dbbd9e4bSmacallanFFBAdjustFrame(int scrnIndex, int x, int y, int flags)
837dbbd9e4bSmacallan{
838dbbd9e4bSmacallan    /* we don't support virtual desktops */
839dbbd9e4bSmacallan    return;
840dbbd9e4bSmacallan}
841dbbd9e4bSmacallan
842dbbd9e4bSmacallan/*
843dbbd9e4bSmacallan * This is called when VT switching back to the X server.  Its job is
844dbbd9e4bSmacallan * to reinitialise the video mode.
845dbbd9e4bSmacallan */
846dbbd9e4bSmacallan
847dbbd9e4bSmacallan/* Mandatory */
848dbbd9e4bSmacallanstatic Bool
849dbbd9e4bSmacallanFFBEnterVT(int scrnIndex, int flags)
850dbbd9e4bSmacallan{
851dbbd9e4bSmacallan    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
852dbbd9e4bSmacallan    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
853dbbd9e4bSmacallan
854dbbd9e4bSmacallan    pFfb->vtSema = FALSE;
855dbbd9e4bSmacallan    if (!pFfb->NoAccel)
856dbbd9e4bSmacallan	CreatorVtChange (pScrn->pScreen, TRUE);
857dbbd9e4bSmacallan    if (pFfb->HWCursor)
858dbbd9e4bSmacallan	xf86SbusHideOsHwCursor (pFfb->psdp);
859dbbd9e4bSmacallan
860dbbd9e4bSmacallan    FFBDacEnterVT(pFfb);
861dbbd9e4bSmacallan
862dbbd9e4bSmacallan    return TRUE;
863dbbd9e4bSmacallan}
864dbbd9e4bSmacallan
865dbbd9e4bSmacallan
866dbbd9e4bSmacallan/*
867dbbd9e4bSmacallan * This is called when VT switching away from the X server.
868dbbd9e4bSmacallan */
869dbbd9e4bSmacallan
870dbbd9e4bSmacallan/* Mandatory */
871dbbd9e4bSmacallanstatic void
872dbbd9e4bSmacallanFFBLeaveVT(int scrnIndex, int flags)
873dbbd9e4bSmacallan{
874dbbd9e4bSmacallan    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
875dbbd9e4bSmacallan    FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
876dbbd9e4bSmacallan
877dbbd9e4bSmacallan    FFBDacLeaveVT(pFfb);
878dbbd9e4bSmacallan
879dbbd9e4bSmacallan    if (!pFfb->NoAccel)
880dbbd9e4bSmacallan	CreatorVtChange (pScrn->pScreen, FALSE);
881dbbd9e4bSmacallan
882dbbd9e4bSmacallan    if (pFfb->HWCursor)
883dbbd9e4bSmacallan	xf86SbusHideOsHwCursor (pFfb->psdp);
884dbbd9e4bSmacallan
885dbbd9e4bSmacallan    pFfb->vtSema = TRUE;
886dbbd9e4bSmacallan    return;
887dbbd9e4bSmacallan}
888dbbd9e4bSmacallan
889dbbd9e4bSmacallan
890dbbd9e4bSmacallan/*
891dbbd9e4bSmacallan * This is called at the end of each server generation.  It restores the
892dbbd9e4bSmacallan * original (text) mode.  It should really also unmap the video memory too.
893dbbd9e4bSmacallan */
894dbbd9e4bSmacallan
895dbbd9e4bSmacallan/* Mandatory */
896dbbd9e4bSmacallanstatic Bool
897dbbd9e4bSmacallanFFBCloseScreen(int scrnIndex, ScreenPtr pScreen)
898dbbd9e4bSmacallan{
899dbbd9e4bSmacallan	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
900dbbd9e4bSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
901dbbd9e4bSmacallan
902dbbd9e4bSmacallan	/* Restore kernel ramdac state before we unmap registers. */
903dbbd9e4bSmacallan	FFBDacFini(pFfb);
904dbbd9e4bSmacallan
905dbbd9e4bSmacallan	pScrn->vtSema = FALSE;
906dbbd9e4bSmacallan
907dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb24, 0x1000000);
908dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8r, 0x400000);
909dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->dfb8x, 0x400000);
910dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb32, 0x1000000);
911dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8r, 0x400000);
912dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->sfb8x, 0x400000);
913dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->regs, 16384);
914dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, pFfb->dac, 8192);
915dbbd9e4bSmacallan	xf86UnmapSbusMem(pFfb->psdp, (void *)pFfb->strapping_bits, 8192);
916dbbd9e4bSmacallan
917dbbd9e4bSmacallan	if (pFfb->HWCursor)
918dbbd9e4bSmacallan		xf86SbusHideOsHwCursor (pFfb->psdp);
919dbbd9e4bSmacallan
920dbbd9e4bSmacallan	pScreen->CloseScreen = pFfb->CloseScreen;
921dbbd9e4bSmacallan	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
922dbbd9e4bSmacallan}
923dbbd9e4bSmacallan
924dbbd9e4bSmacallan
925dbbd9e4bSmacallan/* Free up any per-generation data structures */
926dbbd9e4bSmacallan
927dbbd9e4bSmacallan/* Optional */
928dbbd9e4bSmacallanstatic void
929dbbd9e4bSmacallanFFBFreeScreen(int scrnIndex, int flags)
930dbbd9e4bSmacallan{
931dbbd9e4bSmacallan	FFBFreeRec(xf86Screens[scrnIndex]);
932dbbd9e4bSmacallan}
933dbbd9e4bSmacallan
934dbbd9e4bSmacallan
935dbbd9e4bSmacallan/* Checks if a mode is suitable for the selected chipset. */
936dbbd9e4bSmacallan
937dbbd9e4bSmacallan/* Optional */
938dbbd9e4bSmacallanstatic ModeStatus
939dbbd9e4bSmacallanFFBValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
940dbbd9e4bSmacallan{
941dbbd9e4bSmacallan	if (mode->Flags & V_INTERLACE)
942dbbd9e4bSmacallan		return MODE_BAD;
943dbbd9e4bSmacallan
944dbbd9e4bSmacallan	return MODE_OK;
945dbbd9e4bSmacallan}
946dbbd9e4bSmacallan
947dbbd9e4bSmacallan/* Do screen blanking */
948dbbd9e4bSmacallan
949dbbd9e4bSmacallan/* Mandatory */
950dbbd9e4bSmacallanstatic Bool
951dbbd9e4bSmacallanFFBSaveScreen(ScreenPtr pScreen, int mode)
952dbbd9e4bSmacallan    /* This function blanks the screen when mode=SCREEN_SAVER_ON and
953dbbd9e4bSmacallan       unblanks it when mode=SCREEN_SAVER_OFF.  It is used internally in the
954dbbd9e4bSmacallan       FFBScreenInit code `for aesthetic reasons,' and it is used for
955dbbd9e4bSmacallan       blanking if you set "xset s on s blank."  The work (such as it is) is
956dbbd9e4bSmacallan       done in "ffb_dac.c" `for aesthetic reasons.'
957dbbd9e4bSmacallan    */
958dbbd9e4bSmacallan{
959dbbd9e4bSmacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
960dbbd9e4bSmacallan
961dbbd9e4bSmacallan    return FFBDacSaveScreen(GET_FFB_FROM_SCRN(pScrn), mode);
962dbbd9e4bSmacallan}
963dbbd9e4bSmacallan
964dbbd9e4bSmacallanstatic void
965dbbd9e4bSmacallanFFBDPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
966dbbd9e4bSmacallan{
967dbbd9e4bSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
968dbbd9e4bSmacallan
969dbbd9e4bSmacallan	FFBDacDPMSMode(pFfb, mode, 0);
970dbbd9e4bSmacallan}
971dbbd9e4bSmacallan
972dbbd9e4bSmacallan/*
973dbbd9e4bSmacallan * This is the implementation of the Sync() function.
974dbbd9e4bSmacallan */
975dbbd9e4bSmacallanvoid
976dbbd9e4bSmacallanFFBSync(ScrnInfoPtr pScrn)
977dbbd9e4bSmacallan{
978dbbd9e4bSmacallan    return;
979dbbd9e4bSmacallan}
980dbbd9e4bSmacallan
981dbbd9e4bSmacallan/*
982dbbd9e4bSmacallan  Hook for DPMS Mode.
983dbbd9e4bSmacallan*/
984dbbd9e4bSmacallan
985dbbd9e4bSmacallanstatic void
986dbbd9e4bSmacallanFFBDPMSMode(ScrnInfoPtr pScrn, int DPMSMode, int flags)
987dbbd9e4bSmacallan{
988dbbd9e4bSmacallan  FFBDacDPMSMode(GET_FFB_FROM_SCRN(pScrn), DPMSMode, flags);
989dbbd9e4bSmacallan}
990