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