1f7ec340bSmacallan/*
2f7ec340bSmacallan * CG14 framebuffer driver.
3f7ec340bSmacallan *
4f7ec340bSmacallan * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
5f7ec340bSmacallan *
6f7ec340bSmacallan * Permission is hereby granted, free of charge, to any person obtaining a copy
7f7ec340bSmacallan * of this software and associated documentation files (the "Software"), to deal
8f7ec340bSmacallan * in the Software without restriction, including without limitation the rights
9f7ec340bSmacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10f7ec340bSmacallan * copies of the Software, and to permit persons to whom the Software is
11f7ec340bSmacallan * furnished to do so, subject to the following conditions:
12f7ec340bSmacallan *
13f7ec340bSmacallan * The above copyright notice and this permission notice shall be included in
14f7ec340bSmacallan * all copies or substantial portions of the Software.
15f7ec340bSmacallan *
16f7ec340bSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f7ec340bSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f7ec340bSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19f7ec340bSmacallan * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20f7ec340bSmacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21f7ec340bSmacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22f7ec340bSmacallan */
23f7ec340bSmacallan
24f7ec340bSmacallan#ifdef HAVE_CONFIG_H
25f7ec340bSmacallan#include "config.h"
26f7ec340bSmacallan#endif
27f7ec340bSmacallan
2825ad54caSmrg#include <unistd.h>
297a5333bcSmrg#include <sys/ioctl.h>
30f7ec340bSmacallan#include <string.h>
310d3fa27dSmacallan#include <sys/ioctl.h>
32f7ec340bSmacallan
33f7ec340bSmacallan#include "xf86.h"
34f7ec340bSmacallan#include "xf86_OSproc.h"
35f7ec340bSmacallan#include "mipointer.h"
36f7ec340bSmacallan#include "micmap.h"
37f7ec340bSmacallan
38f7ec340bSmacallan#include "fb.h"
39f7ec340bSmacallan#include "xf86cmap.h"
401a3e96b4Smacallan#include "shadow.h"
41f7ec340bSmacallan#include "cg14.h"
42f7ec340bSmacallan
437a5333bcSmrg#if 0
441a3e96b4Smacallan#define static
457a5333bcSmrg#endif
467a5333bcSmrg
477a5333bcSmrg#include "compat-api.h"
481a3e96b4Smacallan
49f7ec340bSmacallanstatic const OptionInfoRec * CG14AvailableOptions(int chipid, int busid);
50f7ec340bSmacallanstatic void	CG14Identify(int flags);
51f7ec340bSmacallanstatic Bool	CG14Probe(DriverPtr drv, int flags);
52f7ec340bSmacallanstatic Bool	CG14PreInit(ScrnInfoPtr pScrn, int flags);
537a5333bcSmrgstatic Bool	CG14ScreenInit(SCREEN_INIT_ARGS_DECL);
547a5333bcSmrgstatic Bool	CG14EnterVT(VT_FUNC_ARGS_DECL);
557a5333bcSmrgstatic void	CG14LeaveVT(VT_FUNC_ARGS_DECL);
567a5333bcSmrgstatic Bool	CG14CloseScreen(CLOSE_SCREEN_ARGS_DECL);
57f7ec340bSmacallanstatic Bool	CG14SaveScreen(ScreenPtr pScreen, int mode);
58f7ec340bSmacallanstatic void	CG14InitCplane24(ScrnInfoPtr pScrn);
59f7ec340bSmacallanstatic void	CG14ExitCplane24(ScrnInfoPtr pScrn);
601a3e96b4Smacallanstatic void    *CG14WindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *,
611a3e96b4Smacallan			      void *);
62c88c16f8Smacallanstatic Bool	CG14DriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
63c88c16f8Smacallan				pointer ptr);
64f7ec340bSmacallan
65f7ec340bSmacallan/* Required if the driver supports mode switching */
667a5333bcSmrgstatic Bool	CG14SwitchMode(SWITCH_MODE_ARGS_DECL);
67f7ec340bSmacallan/* Required if the driver supports moving the viewport */
687a5333bcSmrgstatic void	CG14AdjustFrame(ADJUST_FRAME_ARGS_DECL);
69f7ec340bSmacallan
70f7ec340bSmacallan/* Optional functions */
717a5333bcSmrgstatic void	CG14FreeScreen(FREE_SCREEN_ARGS_DECL);
727a5333bcSmrgstatic ModeStatus CG14ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
73f7ec340bSmacallan				Bool verbose, int flags);
74f7ec340bSmacallan
75f7ec340bSmacallanvoid CG14Sync(ScrnInfoPtr pScrn);
76f7ec340bSmacallan
77f7ec340bSmacallan#define CG14_VERSION 4000
78f7ec340bSmacallan#define CG14_NAME "SUNCG14"
79f7ec340bSmacallan#define CG14_DRIVER_NAME "suncg14"
80766a8447Smrg#define CG14_MAJOR_VERSION PACKAGE_VERSION_MAJOR
81766a8447Smrg#define CG14_MINOR_VERSION PACKAGE_VERSION_MINOR
82766a8447Smrg#define CG14_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
83f7ec340bSmacallan
84f7ec340bSmacallan/*
85f7ec340bSmacallan * This contains the functions needed by the server after loading the driver
86f7ec340bSmacallan * module.  It must be supplied, and gets passed back by the SetupProc
87f7ec340bSmacallan * function in the dynamic case.  In the static case, a reference to this
88f7ec340bSmacallan * is compiled in, and this requires that the name of this DriverRec be
89f7ec340bSmacallan * an upper-case version of the driver name.
90f7ec340bSmacallan */
91f7ec340bSmacallan
92f7ec340bSmacallan_X_EXPORT DriverRec SUNCG14 = {
93f7ec340bSmacallan    CG14_VERSION,
94f7ec340bSmacallan    CG14_DRIVER_NAME,
95f7ec340bSmacallan    CG14Identify,
96f7ec340bSmacallan    CG14Probe,
97f7ec340bSmacallan    CG14AvailableOptions,
98f7ec340bSmacallan    NULL,
99c88c16f8Smacallan    0,
100c88c16f8Smacallan    CG14DriverFunc
101f7ec340bSmacallan};
102f7ec340bSmacallan
1031a3e96b4Smacallantypedef enum {
1041a3e96b4Smacallan	OPTION_SHADOW_FB,
1051a3e96b4Smacallan	OPTION_HW_CURSOR,
1064261fa58Smacallan	OPTION_SW_CURSOR,
1074261fa58Smacallan	OPTION_ACCEL,
1084261fa58Smacallan	OPTION_XRENDER
1091a3e96b4Smacallan} CG14Opts;
1101a3e96b4Smacallan
111f7ec340bSmacallanstatic const OptionInfoRec CG14Options[] = {
1124261fa58Smacallan    { OPTION_SHADOW_FB,	"ShadowFB", OPTV_BOOLEAN, {0}, TRUE},
1134261fa58Smacallan    { OPTION_ACCEL, 	"Accel",    OPTV_BOOLEAN, {0}, TRUE},
1144261fa58Smacallan    { OPTION_XRENDER,	"XRender",  OPTV_BOOLEAN, {0}, FALSE},
115f7ec340bSmacallan    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
116f7ec340bSmacallan};
117f7ec340bSmacallan
118f7ec340bSmacallanstatic MODULESETUPPROTO(cg14Setup);
119f7ec340bSmacallan
120f7ec340bSmacallanstatic XF86ModuleVersionInfo suncg14VersRec =
121f7ec340bSmacallan{
122f7ec340bSmacallan	"suncg14",
123f7ec340bSmacallan	MODULEVENDORSTRING,
124f7ec340bSmacallan	MODINFOSTRING1,
125f7ec340bSmacallan	MODINFOSTRING2,
126f7ec340bSmacallan	XORG_VERSION_CURRENT,
127f7ec340bSmacallan	CG14_MAJOR_VERSION, CG14_MINOR_VERSION, CG14_PATCHLEVEL,
128f7ec340bSmacallan	ABI_CLASS_VIDEODRV,
129f7ec340bSmacallan	ABI_VIDEODRV_VERSION,
130f7ec340bSmacallan	MOD_CLASS_VIDEODRV,
131f7ec340bSmacallan	{0,0,0,0}
132f7ec340bSmacallan};
133f7ec340bSmacallan
134f7ec340bSmacallan_X_EXPORT XF86ModuleData suncg14ModuleData = {
135f7ec340bSmacallan	&suncg14VersRec,
136f7ec340bSmacallan	cg14Setup,
137f7ec340bSmacallan	NULL
138f7ec340bSmacallan};
139f7ec340bSmacallan
140f7ec340bSmacallanpointer
141f7ec340bSmacallancg14Setup(pointer module, pointer opts, int *errmaj, int *errmin)
142f7ec340bSmacallan{
143f7ec340bSmacallan    static Bool setupDone = FALSE;
144f7ec340bSmacallan
145f7ec340bSmacallan    if (!setupDone) {
146f7ec340bSmacallan	setupDone = TRUE;
147c88c16f8Smacallan	xf86AddDriver(&SUNCG14, module, HaveDriverFuncs);
148f7ec340bSmacallan
149f7ec340bSmacallan	/*
150f7ec340bSmacallan	 * Modules that this driver always requires can be loaded here
151f7ec340bSmacallan	 * by calling LoadSubModule().
152f7ec340bSmacallan	 */
153f7ec340bSmacallan
154f7ec340bSmacallan	/*
155f7ec340bSmacallan	 * The return value must be non-NULL on success even though there
156f7ec340bSmacallan	 * is no TearDownProc.
157f7ec340bSmacallan	 */
158f7ec340bSmacallan	return (pointer)TRUE;
159f7ec340bSmacallan    } else {
160f7ec340bSmacallan	if (errmaj) *errmaj = LDR_ONCEONLY;
161f7ec340bSmacallan	return NULL;
162f7ec340bSmacallan    }
163f7ec340bSmacallan}
164f7ec340bSmacallan
165f7ec340bSmacallanstatic Bool
166f7ec340bSmacallanCG14GetRec(ScrnInfoPtr pScrn)
167f7ec340bSmacallan{
168f7ec340bSmacallan    /*
169f7ec340bSmacallan     * Allocate an Cg14Rec, and hook it into pScrn->driverPrivate.
170f7ec340bSmacallan     * pScrn->driverPrivate is initialised to NULL, so we can check if
171f7ec340bSmacallan     * the allocation has already been done.
172f7ec340bSmacallan     */
173f7ec340bSmacallan    if (pScrn->driverPrivate != NULL)
174f7ec340bSmacallan	return TRUE;
175f7ec340bSmacallan
176f7ec340bSmacallan    pScrn->driverPrivate = xnfcalloc(sizeof(Cg14Rec), 1);
177f7ec340bSmacallan    return TRUE;
178f7ec340bSmacallan}
179f7ec340bSmacallan
180f7ec340bSmacallanstatic void
181f7ec340bSmacallanCG14FreeRec(ScrnInfoPtr pScrn)
182f7ec340bSmacallan{
183f7ec340bSmacallan    Cg14Ptr pCg14;
184f7ec340bSmacallan
185f7ec340bSmacallan    if (pScrn->driverPrivate == NULL)
186f7ec340bSmacallan	return;
187f7ec340bSmacallan
188f7ec340bSmacallan    pCg14 = GET_CG14_FROM_SCRN(pScrn);
189f7ec340bSmacallan
1907a5333bcSmrg    free(pScrn->driverPrivate);
191f7ec340bSmacallan    pScrn->driverPrivate = NULL;
192f7ec340bSmacallan
193f7ec340bSmacallan    return;
194f7ec340bSmacallan}
195f7ec340bSmacallan
196f7ec340bSmacallanstatic const OptionInfoRec *
197f7ec340bSmacallanCG14AvailableOptions(int chipid, int busid)
198f7ec340bSmacallan{
199f7ec340bSmacallan    return CG14Options;
200f7ec340bSmacallan}
201f7ec340bSmacallan
202f7ec340bSmacallan/* Mandatory */
203f7ec340bSmacallanstatic void
204f7ec340bSmacallanCG14Identify(int flags)
205f7ec340bSmacallan{
206f7ec340bSmacallan    xf86Msg(X_INFO, "%s: driver for CG14\n", CG14_NAME);
207f7ec340bSmacallan}
208f7ec340bSmacallan
209f7ec340bSmacallan
210f7ec340bSmacallan/* Mandatory */
211f7ec340bSmacallanstatic Bool
212f7ec340bSmacallanCG14Probe(DriverPtr drv, int flags)
213f7ec340bSmacallan{
214f7ec340bSmacallan    int i;
215f7ec340bSmacallan    GDevPtr *devSections;
216f7ec340bSmacallan    int *usedChips;
217f7ec340bSmacallan    int numDevSections;
218f7ec340bSmacallan    int numUsed;
219f7ec340bSmacallan    Bool foundScreen = FALSE;
220f7ec340bSmacallan    EntityInfoPtr pEnt;
221f7ec340bSmacallan
222f7ec340bSmacallan    /*
223f7ec340bSmacallan     * The aim here is to find all cards that this driver can handle,
224f7ec340bSmacallan     * and for the ones not already claimed by another driver, claim the
225f7ec340bSmacallan     * slot, and allocate a ScrnInfoRec.
226f7ec340bSmacallan     *
227f7ec340bSmacallan     * This should be a minimal probe, and it should under no circumstances
228f7ec340bSmacallan     * change the state of the hardware.  Because a device is found, don't
229f7ec340bSmacallan     * assume that it will be used.  Don't do any initialisations other than
230f7ec340bSmacallan     * the required ScrnInfoRec initialisations.  Don't allocate any new
231f7ec340bSmacallan     * data structures.
232f7ec340bSmacallan     */
233f7ec340bSmacallan
234f7ec340bSmacallan    /*
235f7ec340bSmacallan     * Next we check, if there has been a chipset override in the config file.
236f7ec340bSmacallan     * For this we must find out if there is an active device section which
237f7ec340bSmacallan     * is relevant, i.e., which has no driver specified or has THIS driver
238f7ec340bSmacallan     * specified.
239f7ec340bSmacallan     */
240f7ec340bSmacallan
241f7ec340bSmacallan    if ((numDevSections = xf86MatchDevice(CG14_DRIVER_NAME,
242f7ec340bSmacallan					  &devSections)) <= 0) {
243f7ec340bSmacallan	/*
244f7ec340bSmacallan	 * There's no matching device section in the config file, so quit
245f7ec340bSmacallan	 * now.
246f7ec340bSmacallan	 */
247f7ec340bSmacallan	return FALSE;
248f7ec340bSmacallan    }
249f7ec340bSmacallan
250f7ec340bSmacallan    /*
251f7ec340bSmacallan     * We need to probe the hardware first.  We then need to see how this
252f7ec340bSmacallan     * fits in with what is given in the config file, and allow the config
253f7ec340bSmacallan     * file info to override any contradictions.
254f7ec340bSmacallan     */
255f7ec340bSmacallan
256f7ec340bSmacallan    numUsed = xf86MatchSbusInstances(CG14_NAME, SBUS_DEVICE_CG14,
257f7ec340bSmacallan		   devSections, numDevSections,
258f7ec340bSmacallan		   drv, &usedChips);
259f7ec340bSmacallan
2607a5333bcSmrg    free(devSections);
261f7ec340bSmacallan    if (numUsed <= 0)
262f7ec340bSmacallan	return FALSE;
263f7ec340bSmacallan
264f7ec340bSmacallan    if (flags & PROBE_DETECT)
265f7ec340bSmacallan	foundScreen = TRUE;
266f7ec340bSmacallan    else for (i = 0; i < numUsed; i++) {
267f7ec340bSmacallan	pEnt = xf86GetEntityInfo(usedChips[i]);
268f7ec340bSmacallan
269f7ec340bSmacallan	/*
270f7ec340bSmacallan	 * Check that nothing else has claimed the slots.
271f7ec340bSmacallan	 */
272f7ec340bSmacallan	if(pEnt->active) {
273f7ec340bSmacallan	    ScrnInfoPtr pScrn;
274f7ec340bSmacallan
275f7ec340bSmacallan	    /* Allocate a ScrnInfoRec and claim the slot */
276f7ec340bSmacallan	    pScrn = xf86AllocateScreen(drv, 0);
277f7ec340bSmacallan
278f7ec340bSmacallan	    /* Fill in what we can of the ScrnInfoRec */
279f7ec340bSmacallan	    pScrn->driverVersion = CG14_VERSION;
280f7ec340bSmacallan	    pScrn->driverName	 = CG14_DRIVER_NAME;
281f7ec340bSmacallan	    pScrn->name		 = CG14_NAME;
282f7ec340bSmacallan	    pScrn->Probe	 = CG14Probe;
283f7ec340bSmacallan	    pScrn->PreInit	 = CG14PreInit;
284f7ec340bSmacallan	    pScrn->ScreenInit	 = CG14ScreenInit;
285f7ec340bSmacallan  	    pScrn->SwitchMode	 = CG14SwitchMode;
286f7ec340bSmacallan  	    pScrn->AdjustFrame	 = CG14AdjustFrame;
287f7ec340bSmacallan	    pScrn->EnterVT	 = CG14EnterVT;
288f7ec340bSmacallan	    pScrn->LeaveVT	 = CG14LeaveVT;
289f7ec340bSmacallan	    pScrn->FreeScreen	 = CG14FreeScreen;
290f7ec340bSmacallan	    pScrn->ValidMode	 = CG14ValidMode;
291f7ec340bSmacallan	    xf86AddEntityToScreen(pScrn, pEnt->index);
292f7ec340bSmacallan	    foundScreen = TRUE;
293f7ec340bSmacallan	}
2947a5333bcSmrg	free(pEnt);
295f7ec340bSmacallan    }
2967a5333bcSmrg    free(usedChips);
297f7ec340bSmacallan    return foundScreen;
298f7ec340bSmacallan}
299f7ec340bSmacallan
300f7ec340bSmacallan/* Mandatory */
301f7ec340bSmacallanstatic Bool
302f7ec340bSmacallanCG14PreInit(ScrnInfoPtr pScrn, int flags)
303f7ec340bSmacallan{
304f7ec340bSmacallan    Cg14Ptr pCg14;
305f7ec340bSmacallan    sbusDevicePtr psdp = NULL;
306c88c16f8Smacallan    int i, from, size, len, reg[6], prom;
307c88c16f8Smacallan    char *ptr;
308f7ec340bSmacallan
309f7ec340bSmacallan    if (flags & PROBE_DETECT) return FALSE;
310f7ec340bSmacallan
311f7ec340bSmacallan    /*
312f7ec340bSmacallan     * Note: This function is only called once at server startup, and
313f7ec340bSmacallan     * not at the start of each server generation.  This means that
314f7ec340bSmacallan     * only things that are persistent across server generations can
315f7ec340bSmacallan     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
316f7ec340bSmacallan     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
317f7ec340bSmacallan     * are too, and should be used for data that must persist across
318f7ec340bSmacallan     * server generations.
319f7ec340bSmacallan     *
320f7ec340bSmacallan     * Per-generation data should be allocated with
321f7ec340bSmacallan     * AllocateScreenPrivateIndex() from the ScreenInit() function.
322f7ec340bSmacallan     */
323f7ec340bSmacallan
324f7ec340bSmacallan    /* Allocate the Cg14Rec driverPrivate */
325f7ec340bSmacallan    if (!CG14GetRec(pScrn)) {
326f7ec340bSmacallan	return FALSE;
327f7ec340bSmacallan    }
328f7ec340bSmacallan    pCg14 = GET_CG14_FROM_SCRN(pScrn);
329f7ec340bSmacallan
330f7ec340bSmacallan    /* Set pScrn->monitor */
331f7ec340bSmacallan    pScrn->monitor = pScrn->confScreen->monitor;
332f7ec340bSmacallan
333f7ec340bSmacallan    /* This driver doesn't expect more than one entity per screen */
334f7ec340bSmacallan    if (pScrn->numEntities > 1)
335f7ec340bSmacallan	return FALSE;
336f7ec340bSmacallan    /* This is the general case */
337f7ec340bSmacallan    for (i = 0; i < pScrn->numEntities; i++) {
338f7ec340bSmacallan	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
339f7ec340bSmacallan
340f7ec340bSmacallan	/* CG14 is purely AFX, but we handle it like SBUS */
341f7ec340bSmacallan	if (pEnt->location.type == BUS_SBUS) {
342f7ec340bSmacallan	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
343f7ec340bSmacallan	    pCg14->psdp = psdp;
344f7ec340bSmacallan	} else
345f7ec340bSmacallan	    return FALSE;
346f7ec340bSmacallan    }
347f7ec340bSmacallan    if (psdp == NULL)
348f7ec340bSmacallan	return FALSE;
349f7ec340bSmacallan
3504261fa58Smacallan    pCg14->memsize = 4 * 1024 * 1024;	/* always safe */
351c88c16f8Smacallan    len = 24;
352c88c16f8Smacallan    prom = sparcPromInit();
353a332beb9Sjoerg    if ((ptr = sparcPromGetProperty(&psdp->node, "reg", &len))) {
354c88c16f8Smacallan    	if (len >= 24) {
355c88c16f8Smacallan    	    memcpy(reg, ptr, 24);
356c88c16f8Smacallan    	    size = reg[5];
357a94eab53Schristos    	    xf86Msg(X_INFO, "memsize from reg: %d MB\n", size >> 20);
358c88c16f8Smacallan	    if (size > pCg14->memsize)
359c88c16f8Smacallan    		pCg14->memsize = size;
360c88c16f8Smacallan    	}
361c88c16f8Smacallan    }
3624261fa58Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "found %d MB video memory\n",
3634261fa58Smacallan      pCg14->memsize >> 20);
364f7ec340bSmacallan    /*********************
365f7ec340bSmacallan    deal with depth
366f7ec340bSmacallan    *********************/
367f7ec340bSmacallan
368b73528caSmacallan    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb|Support32bppFb))
369b73528caSmacallan		return FALSE;
370a61c6651Smacallan
371b73528caSmacallan    /* Check that the returned depth is one we support */
372b73528caSmacallan    switch (pScrn->depth) {
373f7ec340bSmacallan	case 32:
374b73528caSmacallan	case 24:
375a61c6651Smacallan	case 16:
3762870aaa1Smacallan	case 8:
377f7ec340bSmacallan	    /* OK */
378f7ec340bSmacallan	    break;
379f7ec340bSmacallan	default:
380f7ec340bSmacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
381f7ec340bSmacallan		       "Given depth (%d) is not supported by this driver\n",
382f7ec340bSmacallan		       pScrn->depth);
383f7ec340bSmacallan	    return FALSE;
384f7ec340bSmacallan    }
385f7ec340bSmacallan
386f7ec340bSmacallan    /* Collect all of the relevant option flags (fill in pScrn->options) */
387f7ec340bSmacallan    xf86CollectOptions(pScrn, NULL);
388f7ec340bSmacallan    /* Process the options */
3897a5333bcSmrg    if (!(pCg14->Options = malloc(sizeof(CG14Options))))
390f7ec340bSmacallan	return FALSE;
391f7ec340bSmacallan    memcpy(pCg14->Options, CG14Options, sizeof(CG14Options));
392f7ec340bSmacallan    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCg14->Options);
3931a3e96b4Smacallan    pCg14->use_shadow = xf86ReturnOptValBool(pCg14->Options, OPTION_SHADOW_FB,
3941a3e96b4Smacallan        TRUE);
3954261fa58Smacallan    pCg14->use_accel = xf86ReturnOptValBool(pCg14->Options, OPTION_ACCEL,
3964261fa58Smacallan        TRUE);
3974261fa58Smacallan    pCg14->use_xrender = xf86ReturnOptValBool(pCg14->Options, OPTION_XRENDER,
3984261fa58Smacallan        FALSE);
399f7ec340bSmacallan
4006fdc29e9Smacallan    if (pScrn->depth < 24) {
4016fdc29e9Smacallan	if (pCg14->use_xrender)
4026fdc29e9Smacallan	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling xrender on depth < 24\n");
4036fdc29e9Smacallan	pCg14->use_xrender = FALSE;
4046fdc29e9Smacallan    }
4056fdc29e9Smacallan
406f7ec340bSmacallan    /*
407f7ec340bSmacallan     * This must happen after pScrn->display has been set because
408f7ec340bSmacallan     * xf86SetWeight references it.
409f7ec340bSmacallan     */
410a61c6651Smacallan    if (pScrn->depth > 16) {
411b73528caSmacallan	rgb weight = {0, 0, 0};
412f7ec340bSmacallan	rgb mask = {0xff, 0xff00, 0xff0000};
413f7ec340bSmacallan
414f7ec340bSmacallan	if (!xf86SetWeight(pScrn, weight, mask)) {
415f7ec340bSmacallan	    return FALSE;
416f7ec340bSmacallan	}
417a61c6651Smacallan    } else if (pScrn->depth > 8) {
418a61c6651Smacallan  	rgb zeroes = {0, 0, 0};
419a61c6651Smacallan
420a61c6651Smacallan	if (!xf86SetWeight(pScrn, zeroes, zeroes)) {
421a61c6651Smacallan	    return FALSE;
422a61c6651Smacallan	}
423a61c6651Smacallan    }
424f7ec340bSmacallan    if (!xf86SetDefaultVisual(pScrn, -1))
425f7ec340bSmacallan	return FALSE;
426f7ec340bSmacallan    else if (pScrn->depth > 8) {
427f7ec340bSmacallan	/* We don't currently support DirectColor */
428f7ec340bSmacallan	if (pScrn->defaultVisual != TrueColor) {
429f7ec340bSmacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
430f7ec340bSmacallan		       " (%s) is not supported\n",
431f7ec340bSmacallan		       xf86GetVisualName(pScrn->defaultVisual));
432f7ec340bSmacallan	    return FALSE;
433f7ec340bSmacallan	}
434f7ec340bSmacallan    }
435f7ec340bSmacallan
436f7ec340bSmacallan    /*
437f7ec340bSmacallan     * The new cmap code requires this to be initialised.
438f7ec340bSmacallan     */
439f7ec340bSmacallan
440f7ec340bSmacallan    {
441f7ec340bSmacallan	Gamma zeros = {0.0, 0.0, 0.0};
442f7ec340bSmacallan
443f7ec340bSmacallan	if (!xf86SetGamma(pScrn, zeros)) {
444f7ec340bSmacallan	    return FALSE;
445f7ec340bSmacallan	}
446f7ec340bSmacallan    }
447f7ec340bSmacallan
448f7ec340bSmacallan    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
449f7ec340bSmacallan	CG14FreeRec(pScrn);
450f7ec340bSmacallan	return FALSE;
451f7ec340bSmacallan    }
452f7ec340bSmacallan
4531a3e96b4Smacallan    if (pCg14->use_shadow) {
4541a3e96b4Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using shadow framebuffer\n");
4551a3e96b4Smacallan	if (xf86LoadSubModule(pScrn, "shadow") == NULL) {
4561a3e96b4Smacallan	    CG14FreeRec(pScrn);
4571a3e96b4Smacallan	    return FALSE;
4581a3e96b4Smacallan	}
4591a3e96b4Smacallan    }
4601a3e96b4Smacallan
4611a3e96b4Smacallan    from = X_DEFAULT;
4621a3e96b4Smacallan    pCg14->HWCursor = TRUE;
4631a3e96b4Smacallan    if (xf86GetOptValBool(pCg14->Options, OPTION_HW_CURSOR, &pCg14->HWCursor))
4641a3e96b4Smacallan	from = X_CONFIG;
4651a3e96b4Smacallan    if (xf86ReturnOptValBool(pCg14->Options, OPTION_SW_CURSOR, FALSE)) {
4661a3e96b4Smacallan	from = X_CONFIG;
4671a3e96b4Smacallan	pCg14->HWCursor = FALSE;
4681a3e96b4Smacallan    }
4691a3e96b4Smacallan    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
4701a3e96b4Smacallan		pCg14->HWCursor ? "HW" : "SW");
4711a3e96b4Smacallan
472f7ec340bSmacallan    /*********************
473f7ec340bSmacallan    set up clock and mode stuff
474f7ec340bSmacallan    *********************/
475f7ec340bSmacallan
476f7ec340bSmacallan    pScrn->progClock = TRUE;
477f7ec340bSmacallan
478f7ec340bSmacallan    if(pScrn->display->virtualX || pScrn->display->virtualY) {
479f7ec340bSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
480f7ec340bSmacallan		   "CG14 does not support a virtual desktop\n");
481f7ec340bSmacallan	pScrn->display->virtualX = 0;
482f7ec340bSmacallan	pScrn->display->virtualY = 0;
483f7ec340bSmacallan    }
484f7ec340bSmacallan
485f7ec340bSmacallan    xf86SbusUseBuiltinMode(pScrn, pCg14->psdp);
486f7ec340bSmacallan    pScrn->currentMode = pScrn->modes;
487f7ec340bSmacallan    pScrn->displayWidth = pScrn->virtualX;
488f7ec340bSmacallan
489f7ec340bSmacallan    /* Set display resolution */
490f7ec340bSmacallan    xf86SetDpi(pScrn, 0, 0);
491f7ec340bSmacallan
492f7ec340bSmacallan    return TRUE;
493f7ec340bSmacallan}
494f7ec340bSmacallan
495fe196524Smrgstatic void
496fe196524SmrgCG14UpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
497fe196524Smrg{
498fe196524Smrg	shadowUpdatePacked(pScreen, pBuf);
499fe196524Smrg}
500fe196524Smrg
5011a3e96b4Smacallanstatic Bool
5021a3e96b4SmacallanCG14CreateScreenResources(ScreenPtr pScreen)
5031a3e96b4Smacallan{
5041a3e96b4Smacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
5051a3e96b4Smacallan    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
5061a3e96b4Smacallan    PixmapPtr pPixmap;
5071a3e96b4Smacallan    Bool ret;
5081a3e96b4Smacallan
5091a3e96b4Smacallan    pScreen->CreateScreenResources = pCg14->CreateScreenResources;
5101a3e96b4Smacallan    ret = pScreen->CreateScreenResources(pScreen);
5111a3e96b4Smacallan    pScreen->CreateScreenResources = CG14CreateScreenResources;
5121a3e96b4Smacallan
5131a3e96b4Smacallan    if (!ret)
5141a3e96b4Smacallan	return FALSE;
5151a3e96b4Smacallan
5161a3e96b4Smacallan    pPixmap = pScreen->GetScreenPixmap(pScreen);
5171a3e96b4Smacallan
518fe196524Smrg    if (!shadowAdd(pScreen, pPixmap, CG14UpdatePacked,
5191a3e96b4Smacallan	CG14WindowLinear, 0, NULL)) {
5201a3e96b4Smacallan	return FALSE;
5211a3e96b4Smacallan    }
5221a3e96b4Smacallan    return TRUE;
5231a3e96b4Smacallan}
5241a3e96b4Smacallan
5251a3e96b4Smacallan
5261a3e96b4Smacallanstatic Bool
5271a3e96b4SmacallanCG14ShadowInit(ScreenPtr pScreen)
5281a3e96b4Smacallan{
5291a3e96b4Smacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
5301a3e96b4Smacallan    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
5311a3e96b4Smacallan
5321a3e96b4Smacallan    if (!shadowSetup(pScreen)) {
5331a3e96b4Smacallan	return FALSE;
5341a3e96b4Smacallan    }
5351a3e96b4Smacallan
5361a3e96b4Smacallan    pCg14->CreateScreenResources = pScreen->CreateScreenResources;
5371a3e96b4Smacallan    pScreen->CreateScreenResources = CG14CreateScreenResources;
5381a3e96b4Smacallan
5391a3e96b4Smacallan    return TRUE;
5401a3e96b4Smacallan}
541f7ec340bSmacallan/* Mandatory */
542f7ec340bSmacallan
543f7ec340bSmacallan/* This gets called at the start of each server generation */
544f7ec340bSmacallan
545f7ec340bSmacallanstatic Bool
5467a5333bcSmrgCG14ScreenInit(SCREEN_INIT_ARGS_DECL)
547f7ec340bSmacallan{
5487a5333bcSmrg    ScrnInfoPtr pScrn;
5497a5333bcSmrg    Cg14Ptr pCg14;
550f7ec340bSmacallan    VisualPtr visual;
5514261fa58Smacallan    int ret, have_accel = 0;
552f7ec340bSmacallan
5537a5333bcSmrg    /*
5547a5333bcSmrg     * First get the ScrnInfoRec
5557a5333bcSmrg     */
5567a5333bcSmrg    pScrn = xf86ScreenToScrn(pScreen);
5577a5333bcSmrg
5587a5333bcSmrg    pCg14 = GET_CG14_FROM_SCRN(pScrn);
5597a5333bcSmrg
560f7ec340bSmacallan    /* Map the CG14 memory */
5614261fa58Smacallan    pCg14->fb = xf86MapSbusMem (pCg14->psdp, CG14_DIRECT_VOFF, pCg14->memsize);
562f7ec340bSmacallan    pCg14->x32 = xf86MapSbusMem (pCg14->psdp, CG14_X32_VOFF,
563f7ec340bSmacallan				 (pCg14->psdp->width * pCg14->psdp->height));
564f7ec340bSmacallan    pCg14->xlut = xf86MapSbusMem (pCg14->psdp, CG14_XLUT_VOFF, 4096);
5651a3e96b4Smacallan    pCg14->curs = xf86MapSbusMem (pCg14->psdp, CG14_CURSOR_VOFF, 4096);
566f7ec340bSmacallan
5674261fa58Smacallan    pCg14->sxreg = xf86MapSbusMem (pCg14->psdp, CG14_SXREG_VOFF, 4096);
5684261fa58Smacallan    pCg14->sxio = xf86MapSbusMem (pCg14->psdp, CG14_SXIO_VOFF, 0x04000000);
5694261fa58Smacallan    have_accel = (pCg14->sxreg != NULL) && (pCg14->sxio != NULL);
5704261fa58Smacallan
5714261fa58Smacallan    if (have_accel) {
5724261fa58Smacallan    	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
5734261fa58Smacallan    	  "found kernel support for SX acceleration\n");
5744261fa58Smacallan    }
5754261fa58Smacallan    have_accel = have_accel & pCg14->use_accel;
5764261fa58Smacallan    if (have_accel) {
5774261fa58Smacallan    	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "using acceleration\n");
5784261fa58Smacallan    	if (pCg14->use_shadow)
5794261fa58Smacallan    	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "disabling shadow\n");
5804261fa58Smacallan    	pCg14->use_shadow = FALSE;
5814261fa58Smacallan    }
5824261fa58Smacallan
5831a3e96b4Smacallan    pCg14->width = pCg14->psdp->width;
5841a3e96b4Smacallan    pCg14->height = pCg14->psdp->height;
5851a3e96b4Smacallan
5861a3e96b4Smacallan    if (! pCg14->fb || !pCg14->x32 || !pCg14->xlut || !pCg14->curs) {
5871a3e96b4Smacallan    	xf86Msg(X_ERROR,
5881a3e96b4Smacallan	    "can't mmap something: fd %08x  x32 %08x xlut %08x cursor %08x\n",
5891a3e96b4Smacallan	    (uint32_t)pCg14->fb, (uint32_t)pCg14->x32, (uint32_t)pCg14->xlut,
5901a3e96b4Smacallan	    (uint32_t)pCg14->curs);
591f7ec340bSmacallan	return FALSE;
592b73528caSmacallan    }
593f7ec340bSmacallan
594f7ec340bSmacallan    /* Darken the screen for aesthetic reasons and set the viewport */
595f7ec340bSmacallan    CG14SaveScreen(pScreen, SCREEN_SAVER_ON);
596f7ec340bSmacallan
597f7ec340bSmacallan    /*
598f7ec340bSmacallan     * The next step is to setup the screen's visuals, and initialise the
599f7ec340bSmacallan     * framebuffer code.  In cases where the framebuffer's default
600f7ec340bSmacallan     * choices for things like visual layouts and bits per RGB are OK,
601f7ec340bSmacallan     * this may be as simple as calling the framebuffer's ScreenInit()
602f7ec340bSmacallan     * function.  If not, the visuals will need to be setup before calling
603f7ec340bSmacallan     * a fb ScreenInit() function and fixed up after.
604f7ec340bSmacallan     */
605f7ec340bSmacallan
606f7ec340bSmacallan    /*
607f7ec340bSmacallan     * Reset visual list.
608f7ec340bSmacallan     */
609f7ec340bSmacallan    miClearVisualTypes();
610f7ec340bSmacallan
6112870aaa1Smacallan    /* Set the bits per RGB for 8bpp mode */
6122870aaa1Smacallan    pScrn->rgbBits = 8;
613f7ec340bSmacallan
6142870aaa1Smacallan    /* Setup the visuals we support. */
6152870aaa1Smacallan    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
616f7ec340bSmacallan			  pScrn->rgbBits, pScrn->defaultVisual))
617f7ec340bSmacallan	return FALSE;
618f7ec340bSmacallan
619f7ec340bSmacallan    miSetPixmapDepths ();
620f7ec340bSmacallan
6211a3e96b4Smacallan    if (pCg14->use_shadow) {
622c88c16f8Smacallan	pCg14->shadow = malloc(pScrn->virtualX * pScrn->virtualY * 4);
6231a3e96b4Smacallan
6241a3e96b4Smacallan	if (!pCg14->shadow) {
6251a3e96b4Smacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
6261a3e96b4Smacallan	        "Failed to allocate shadow framebuffer\n");
6271a3e96b4Smacallan	    return FALSE;
6281a3e96b4Smacallan	}
6291a3e96b4Smacallan    }
6301a3e96b4Smacallan
631f7ec340bSmacallan    /*
632f7ec340bSmacallan     * Call the framebuffer layer's ScreenInit function, and fill in other
633f7ec340bSmacallan     * pScreen fields.
634f7ec340bSmacallan     */
635f7ec340bSmacallan
636f7ec340bSmacallan    CG14InitCplane24(pScrn);
6372870aaa1Smacallan
6381a3e96b4Smacallan    ret = fbScreenInit(pScreen, pCg14->use_shadow ? pCg14->shadow : pCg14->fb,
6391a3e96b4Smacallan    		       pScrn->virtualX,
640f7ec340bSmacallan		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
641f7ec340bSmacallan		       pScrn->virtualX, pScrn->bitsPerPixel);
642f7ec340bSmacallan
643f7ec340bSmacallan    if (!ret)
644f7ec340bSmacallan	return FALSE;
645f7ec340bSmacallan
6461a3e96b4Smacallan    /* must be after RGB ordering fixed */
6471a3e96b4Smacallan    fbPictureInit (pScreen, 0, 0);
6481a3e96b4Smacallan
6491a3e96b4Smacallan    if (pCg14->use_shadow && !CG14ShadowInit(pScreen)) {
6504261fa58Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
6511a3e96b4Smacallan		    "shadow framebuffer initialization failed\n");
6521a3e96b4Smacallan	return FALSE;
6531a3e96b4Smacallan    }
6541a3e96b4Smacallan
655f7ec340bSmacallan    xf86SetBackingStore(pScreen);
656f7ec340bSmacallan    xf86SetSilkenMouse(pScreen);
657f7ec340bSmacallan
658f7ec340bSmacallan    xf86SetBlackWhitePixels(pScreen);
659f7ec340bSmacallan
660f7ec340bSmacallan    if (pScrn->bitsPerPixel > 8) {
661f7ec340bSmacallan	/* Fixup RGB ordering */
662f7ec340bSmacallan	visual = pScreen->visuals + pScreen->numVisuals;
663f7ec340bSmacallan	while (--visual >= pScreen->visuals) {
664f7ec340bSmacallan	    if ((visual->class | DynamicClass) == DirectColor) {
665f7ec340bSmacallan		visual->offsetRed = pScrn->offset.red;
666f7ec340bSmacallan		visual->offsetGreen = pScrn->offset.green;
667f7ec340bSmacallan		visual->offsetBlue = pScrn->offset.blue;
668f7ec340bSmacallan		visual->redMask = pScrn->mask.red;
669f7ec340bSmacallan		visual->greenMask = pScrn->mask.green;
670f7ec340bSmacallan		visual->blueMask = pScrn->mask.blue;
671f7ec340bSmacallan	    }
672f7ec340bSmacallan	}
673f7ec340bSmacallan    }
674f7ec340bSmacallan
6754261fa58Smacallan    /* setup acceleration */
6764261fa58Smacallan    if (have_accel) {
6774261fa58Smacallan	XF86ModReqInfo req;
6784261fa58Smacallan	int errmaj, errmin;
6794261fa58Smacallan
6804261fa58Smacallan	memset(&req, 0, sizeof(XF86ModReqInfo));
6814261fa58Smacallan	req.majorversion = 2;
6824261fa58Smacallan	req.minorversion = 0;
6834261fa58Smacallan	if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
6844261fa58Smacallan	    &errmaj, &errmin)) {
6854261fa58Smacallan		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
6864261fa58Smacallan		return FALSE;
6874261fa58Smacallan	}
6884261fa58Smacallan	if (!CG14InitAccel(pScreen))
6894261fa58Smacallan	    have_accel = FALSE;
6904261fa58Smacallan    }
6914261fa58Smacallan
6924261fa58Smacallan
693f7ec340bSmacallan    /* Initialise cursor functions */
694f7ec340bSmacallan    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
695f7ec340bSmacallan
6961a3e96b4Smacallan    /* check for hardware cursor support */
6971a3e96b4Smacallan    if (pCg14->HWCursor)
6981a3e96b4Smacallan	CG14SetupCursor(pScreen);
6991a3e96b4Smacallan
700f7ec340bSmacallan    /* Initialise default colourmap */
701f7ec340bSmacallan    if (!miCreateDefColormap(pScreen))
702f7ec340bSmacallan	return FALSE;
703f7ec340bSmacallan
7042870aaa1Smacallan    if(!xf86SbusHandleColormaps(pScreen, pCg14->psdp))
7052870aaa1Smacallan	return FALSE;
7062870aaa1Smacallan
707f7ec340bSmacallan    pCg14->CloseScreen = pScreen->CloseScreen;
708f7ec340bSmacallan    pScreen->CloseScreen = CG14CloseScreen;
709f7ec340bSmacallan    pScreen->SaveScreen = CG14SaveScreen;
710f7ec340bSmacallan
711f7ec340bSmacallan    /* Report any unused options (only for the first generation) */
712f7ec340bSmacallan    if (serverGeneration == 1) {
713f7ec340bSmacallan	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
714f7ec340bSmacallan    }
715f7ec340bSmacallan
716f7ec340bSmacallan    /* unblank the screen */
717f7ec340bSmacallan    CG14SaveScreen(pScreen, SCREEN_SAVER_OFF);
718f7ec340bSmacallan
719f7ec340bSmacallan    /* Done */
720f7ec340bSmacallan    return TRUE;
721f7ec340bSmacallan}
722f7ec340bSmacallan
723f7ec340bSmacallan
724f7ec340bSmacallan/* Usually mandatory */
725f7ec340bSmacallanstatic Bool
7267a5333bcSmrgCG14SwitchMode(SWITCH_MODE_ARGS_DECL)
727f7ec340bSmacallan{
728b73528caSmacallan    xf86Msg(X_ERROR, "CG14SwitchMode\n");
729f7ec340bSmacallan    return TRUE;
730f7ec340bSmacallan}
731f7ec340bSmacallan
732f7ec340bSmacallan
733f7ec340bSmacallan/*
734f7ec340bSmacallan * This function is used to initialize the Start Address - the first
735f7ec340bSmacallan * displayed location in the video memory.
736f7ec340bSmacallan */
737f7ec340bSmacallan/* Usually mandatory */
738f7ec340bSmacallanstatic void
7397a5333bcSmrgCG14AdjustFrame(ADJUST_FRAME_ARGS_DECL)
740f7ec340bSmacallan{
741f7ec340bSmacallan    /* we don't support virtual desktops */
742f7ec340bSmacallan    return;
743f7ec340bSmacallan}
744f7ec340bSmacallan
745f7ec340bSmacallan/*
746f7ec340bSmacallan * This is called when VT switching back to the X server.  Its job is
747f7ec340bSmacallan * to reinitialise the video mode.
748f7ec340bSmacallan */
749f7ec340bSmacallan
750f7ec340bSmacallan/* Mandatory */
751f7ec340bSmacallanstatic Bool
7527a5333bcSmrgCG14EnterVT(VT_FUNC_ARGS_DECL)
753f7ec340bSmacallan{
7547a5333bcSmrg    SCRN_INFO_PTR(arg);
755f7ec340bSmacallan
756f7ec340bSmacallan    CG14InitCplane24 (pScrn);
757f7ec340bSmacallan    return TRUE;
758f7ec340bSmacallan}
759f7ec340bSmacallan
760f7ec340bSmacallan
761f7ec340bSmacallan/*
762f7ec340bSmacallan * This is called when VT switching away from the X server.
763f7ec340bSmacallan */
764f7ec340bSmacallan
765f7ec340bSmacallan/* Mandatory */
766f7ec340bSmacallanstatic void
7677a5333bcSmrgCG14LeaveVT(VT_FUNC_ARGS_DECL)
768f7ec340bSmacallan{
7697a5333bcSmrg    SCRN_INFO_PTR(arg);
770f7ec340bSmacallan
771f7ec340bSmacallan    CG14ExitCplane24 (pScrn);
772f7ec340bSmacallan    return;
773f7ec340bSmacallan}
774f7ec340bSmacallan
775f7ec340bSmacallan
776f7ec340bSmacallan/*
777f7ec340bSmacallan * This is called at the end of each server generation.  It restores the
778f7ec340bSmacallan * original (text) mode.  It should really also unmap the video memory too.
779f7ec340bSmacallan */
780f7ec340bSmacallan
781f7ec340bSmacallan/* Mandatory */
782f7ec340bSmacallanstatic Bool
7837a5333bcSmrgCG14CloseScreen(CLOSE_SCREEN_ARGS_DECL)
784f7ec340bSmacallan{
7857a5333bcSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
786f7ec340bSmacallan    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
7871a3e96b4Smacallan    PixmapPtr pPixmap;
7881a3e96b4Smacallan
7891a3e96b4Smacallan    if (pCg14->use_shadow) {
7901a3e96b4Smacallan
7911a3e96b4Smacallan	pPixmap = pScreen->GetScreenPixmap(pScreen);
7921a3e96b4Smacallan	shadowRemove(pScreen, pPixmap);
7931a3e96b4Smacallan	pCg14->use_shadow = FALSE;
7941a3e96b4Smacallan    }
795f7ec340bSmacallan
796f7ec340bSmacallan    pScrn->vtSema = FALSE;
797b73528caSmacallan    CG14ExitCplane24 (pScrn);
7982870aaa1Smacallan    xf86UnmapSbusMem(pCg14->psdp, pCg14->fb, pCg14->memsize);
799f7ec340bSmacallan    xf86UnmapSbusMem(pCg14->psdp, pCg14->x32,
800f7ec340bSmacallan		     (pCg14->psdp->width * pCg14->psdp->height));
801f7ec340bSmacallan    xf86UnmapSbusMem(pCg14->psdp, pCg14->xlut, 4096);
8021a3e96b4Smacallan    xf86UnmapSbusMem(pCg14->psdp, pCg14->curs, 4096);
803f7ec340bSmacallan
804f7ec340bSmacallan    pScreen->CloseScreen = pCg14->CloseScreen;
8057a5333bcSmrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
806f7ec340bSmacallan}
807f7ec340bSmacallan
8081a3e96b4Smacallanstatic void *
8091a3e96b4SmacallanCG14WindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
8101a3e96b4Smacallan		CARD32 *size, void *closure)
8111a3e96b4Smacallan{
8121a3e96b4Smacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
8131a3e96b4Smacallan    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
814a61c6651Smacallan    int mul = (pScrn->bitsPerPixel >> 3);
8151a3e96b4Smacallan
816a61c6651Smacallan    *size = pCg14->width * mul;
817a61c6651Smacallan    return (CARD8 *)pCg14->fb + row * (pCg14->width * mul) + offset;
8181a3e96b4Smacallan}
819f7ec340bSmacallan
820f7ec340bSmacallan/* Free up any per-generation data structures */
821f7ec340bSmacallan
822f7ec340bSmacallan/* Optional */
823f7ec340bSmacallanstatic void
8247a5333bcSmrgCG14FreeScreen(FREE_SCREEN_ARGS_DECL)
825f7ec340bSmacallan{
8267a5333bcSmrg    SCRN_INFO_PTR(arg);
8277a5333bcSmrg    CG14FreeRec(pScrn);
828f7ec340bSmacallan}
829f7ec340bSmacallan
830f7ec340bSmacallan
831f7ec340bSmacallan/* Checks if a mode is suitable for the selected chipset. */
832f7ec340bSmacallan
833f7ec340bSmacallan/* Optional */
834f7ec340bSmacallanstatic ModeStatus
8357a5333bcSmrgCG14ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
836f7ec340bSmacallan{
837f7ec340bSmacallan    if (mode->Flags & V_INTERLACE)
838f7ec340bSmacallan	return(MODE_BAD);
839f7ec340bSmacallan
840f7ec340bSmacallan    return(MODE_OK);
841f7ec340bSmacallan}
842f7ec340bSmacallan
843f7ec340bSmacallan/* Do screen blanking */
844f7ec340bSmacallan
845f7ec340bSmacallan/* Mandatory */
846f7ec340bSmacallanstatic Bool
847f7ec340bSmacallanCG14SaveScreen(ScreenPtr pScreen, int mode)
848f7ec340bSmacallan{
8491bd6d369Smacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
8501bd6d369Smacallan    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
8511bd6d369Smacallan    int state;
8521bd6d369Smacallan    switch(mode) {
8531bd6d369Smacallan	case SCREEN_SAVER_ON:
8541bd6d369Smacallan	case SCREEN_SAVER_CYCLE:
8551bd6d369Smacallan		state = FBVIDEO_OFF;
8561bd6d369Smacallan		ioctl(pCg14->psdp->fd, FBIOSVIDEO, &state);
8571bd6d369Smacallan		break;
8581bd6d369Smacallan	case SCREEN_SAVER_OFF:
8591bd6d369Smacallan	case SCREEN_SAVER_FORCER:
8601bd6d369Smacallan		state = FBVIDEO_ON;
8611bd6d369Smacallan		ioctl(pCg14->psdp->fd, FBIOSVIDEO, &state);
8621bd6d369Smacallan		break;
8631bd6d369Smacallan	default:
8641bd6d369Smacallan		return FALSE;
8651bd6d369Smacallan    }
866f7ec340bSmacallan    return TRUE;
867f7ec340bSmacallan}
868f7ec340bSmacallan
869f7ec340bSmacallan/*
870f7ec340bSmacallan * This is the implementation of the Sync() function.
871f7ec340bSmacallan */
872f7ec340bSmacallanvoid
873f7ec340bSmacallanCG14Sync(ScrnInfoPtr pScrn)
874f7ec340bSmacallan{
875f7ec340bSmacallan    return;
876f7ec340bSmacallan}
877f7ec340bSmacallan
878f7ec340bSmacallan/*
879f7ec340bSmacallan * This initializes the card for 24 bit mode.
880f7ec340bSmacallan */
881f7ec340bSmacallanstatic void
882f7ec340bSmacallanCG14InitCplane24(ScrnInfoPtr pScrn)
883f7ec340bSmacallan{
884f7ec340bSmacallan  Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
885a61c6651Smacallan  int size, bpp = 0;
886a61c6651Smacallan
887f7ec340bSmacallan  size = pScrn->virtualX * pScrn->virtualY;
888a61c6651Smacallan  switch (pScrn->bitsPerPixel) {
889a61c6651Smacallan  	case 8:
890a61c6651Smacallan  	case 16:
891a61c6651Smacallan  	    bpp = pScrn->bitsPerPixel;
892a61c6651Smacallan  	    break;
893a61c6651Smacallan  	case 24:
894a61c6651Smacallan  	case 32:
895a61c6651Smacallan  	    bpp = 32;
896a61c6651Smacallan  	default:
897a61c6651Smacallan  	    xf86Msg(X_ERROR, "Unsupported depth %d\n", pScrn->bitsPerPixel);
898a61c6651Smacallan  }
899a61c6651Smacallan  if (bpp == 0) return;
900f7ec340bSmacallan  ioctl (pCg14->psdp->fd, CG14_SET_PIXELMODE, &bpp);
9012870aaa1Smacallan  memset (pCg14->fb, 0, size * (bpp >> 3));
902f7ec340bSmacallan  memset (pCg14->x32, 0, size);
903a61c6651Smacallan#ifndef __NetBSD__
904f7ec340bSmacallan  memset (pCg14->xlut, 0, 0x200);
905a61c6651Smacallan#endif
906f7ec340bSmacallan}
907f7ec340bSmacallan
908f7ec340bSmacallan/*
909f7ec340bSmacallan * This initializes the card for 8 bit mode.
910f7ec340bSmacallan */
911f7ec340bSmacallanstatic void
912f7ec340bSmacallanCG14ExitCplane24(ScrnInfoPtr pScrn)
913f7ec340bSmacallan{
914f7ec340bSmacallan  Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
915f7ec340bSmacallan  int bpp = 8;
916f7ec340bSmacallan
917f7ec340bSmacallan  ioctl (pCg14->psdp->fd, CG14_SET_PIXELMODE, &bpp);
9181bd6d369Smacallan}
919c88c16f8Smacallan
920c88c16f8Smacallan
921c88c16f8Smacallanstatic Bool
922c88c16f8SmacallanCG14DriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
923c88c16f8Smacallan    pointer ptr)
924c88c16f8Smacallan{
925c88c16f8Smacallan	xorgHWFlags *flag;
926c88c16f8Smacallan
927c88c16f8Smacallan	switch (op) {
928c88c16f8Smacallan	case GET_REQUIRED_HW_INTERFACES:
929c88c16f8Smacallan		flag = (CARD32*)ptr;
930c88c16f8Smacallan		(*flag) = HW_MMIO;
931c88c16f8Smacallan		return TRUE;
932c88c16f8Smacallan	default:
933c88c16f8Smacallan		return FALSE;
934c88c16f8Smacallan	}
935c88c16f8Smacallan}
936