cg14_driver.c revision 1a3e96b4
1/*
2 * CG14 framebuffer driver.
3 *
4 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <string.h>
29
30#include "xf86.h"
31#include "xf86_OSproc.h"
32#include "mipointer.h"
33#include "mibstore.h"
34#include "micmap.h"
35
36#include "fb.h"
37#include "xf86cmap.h"
38#include "shadow.h"
39#include "cg14.h"
40
41#define static
42
43static const OptionInfoRec * CG14AvailableOptions(int chipid, int busid);
44static void	CG14Identify(int flags);
45static Bool	CG14Probe(DriverPtr drv, int flags);
46static Bool	CG14PreInit(ScrnInfoPtr pScrn, int flags);
47static Bool	CG14ScreenInit(int Index, ScreenPtr pScreen, int argc,
48			      char **argv);
49static Bool	CG14EnterVT(int scrnIndex, int flags);
50static void	CG14LeaveVT(int scrnIndex, int flags);
51static Bool	CG14CloseScreen(int scrnIndex, ScreenPtr pScreen);
52static Bool	CG14SaveScreen(ScreenPtr pScreen, int mode);
53static void	CG14InitCplane24(ScrnInfoPtr pScrn);
54static void	CG14ExitCplane24(ScrnInfoPtr pScrn);
55static void    *CG14WindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *,
56			      void *);
57
58/* Required if the driver supports mode switching */
59static Bool	CG14SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
60/* Required if the driver supports moving the viewport */
61static void	CG14AdjustFrame(int scrnIndex, int x, int y, int flags);
62
63/* Optional functions */
64static void	CG14FreeScreen(int scrnIndex, int flags);
65static ModeStatus CG14ValidMode(int scrnIndex, DisplayModePtr mode,
66				Bool verbose, int flags);
67
68void CG14Sync(ScrnInfoPtr pScrn);
69
70#define CG14_VERSION 4000
71#define CG14_NAME "SUNCG14"
72#define CG14_DRIVER_NAME "suncg14"
73#define CG14_MAJOR_VERSION PACKAGE_VERSION_MAJOR
74#define CG14_MINOR_VERSION PACKAGE_VERSION_MINOR
75#define CG14_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
76
77/*
78 * This contains the functions needed by the server after loading the driver
79 * module.  It must be supplied, and gets passed back by the SetupProc
80 * function in the dynamic case.  In the static case, a reference to this
81 * is compiled in, and this requires that the name of this DriverRec be
82 * an upper-case version of the driver name.
83 */
84
85_X_EXPORT DriverRec SUNCG14 = {
86    CG14_VERSION,
87    CG14_DRIVER_NAME,
88    CG14Identify,
89    CG14Probe,
90    CG14AvailableOptions,
91    NULL,
92    0
93};
94
95typedef enum {
96	OPTION_SHADOW_FB,
97	OPTION_HW_CURSOR,
98	OPTION_SW_CURSOR
99} CG14Opts;
100
101static const OptionInfoRec CG14Options[] = {
102    { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, TRUE},
103    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
104};
105
106#ifdef XFree86LOADER
107
108static MODULESETUPPROTO(cg14Setup);
109
110static XF86ModuleVersionInfo suncg14VersRec =
111{
112	"suncg14",
113	MODULEVENDORSTRING,
114	MODINFOSTRING1,
115	MODINFOSTRING2,
116	XORG_VERSION_CURRENT,
117	CG14_MAJOR_VERSION, CG14_MINOR_VERSION, CG14_PATCHLEVEL,
118	ABI_CLASS_VIDEODRV,
119	ABI_VIDEODRV_VERSION,
120	MOD_CLASS_VIDEODRV,
121	{0,0,0,0}
122};
123
124_X_EXPORT XF86ModuleData suncg14ModuleData = {
125	&suncg14VersRec,
126	cg14Setup,
127	NULL
128};
129
130pointer
131cg14Setup(pointer module, pointer opts, int *errmaj, int *errmin)
132{
133    static Bool setupDone = FALSE;
134
135    if (!setupDone) {
136	setupDone = TRUE;
137	xf86AddDriver(&SUNCG14, module, 0);
138
139	/*
140	 * Modules that this driver always requires can be loaded here
141	 * by calling LoadSubModule().
142	 */
143
144	/*
145	 * The return value must be non-NULL on success even though there
146	 * is no TearDownProc.
147	 */
148	return (pointer)TRUE;
149    } else {
150	if (errmaj) *errmaj = LDR_ONCEONLY;
151	return NULL;
152    }
153}
154
155#endif /* XFree86LOADER */
156
157static Bool
158CG14GetRec(ScrnInfoPtr pScrn)
159{
160    /*
161     * Allocate an Cg14Rec, and hook it into pScrn->driverPrivate.
162     * pScrn->driverPrivate is initialised to NULL, so we can check if
163     * the allocation has already been done.
164     */
165    if (pScrn->driverPrivate != NULL)
166	return TRUE;
167
168    pScrn->driverPrivate = xnfcalloc(sizeof(Cg14Rec), 1);
169    return TRUE;
170}
171
172static void
173CG14FreeRec(ScrnInfoPtr pScrn)
174{
175    Cg14Ptr pCg14;
176
177    if (pScrn->driverPrivate == NULL)
178	return;
179
180    pCg14 = GET_CG14_FROM_SCRN(pScrn);
181
182    xfree(pScrn->driverPrivate);
183    pScrn->driverPrivate = NULL;
184
185    return;
186}
187
188static const OptionInfoRec *
189CG14AvailableOptions(int chipid, int busid)
190{
191    return CG14Options;
192}
193
194/* Mandatory */
195static void
196CG14Identify(int flags)
197{
198    xf86Msg(X_INFO, "%s: driver for CG14\n", CG14_NAME);
199}
200
201
202/* Mandatory */
203static Bool
204CG14Probe(DriverPtr drv, int flags)
205{
206    int i;
207    GDevPtr *devSections;
208    int *usedChips;
209    int numDevSections;
210    int numUsed;
211    Bool foundScreen = FALSE;
212    EntityInfoPtr pEnt;
213
214    /*
215     * The aim here is to find all cards that this driver can handle,
216     * and for the ones not already claimed by another driver, claim the
217     * slot, and allocate a ScrnInfoRec.
218     *
219     * This should be a minimal probe, and it should under no circumstances
220     * change the state of the hardware.  Because a device is found, don't
221     * assume that it will be used.  Don't do any initialisations other than
222     * the required ScrnInfoRec initialisations.  Don't allocate any new
223     * data structures.
224     */
225
226    /*
227     * Next we check, if there has been a chipset override in the config file.
228     * For this we must find out if there is an active device section which
229     * is relevant, i.e., which has no driver specified or has THIS driver
230     * specified.
231     */
232
233    if ((numDevSections = xf86MatchDevice(CG14_DRIVER_NAME,
234					  &devSections)) <= 0) {
235	/*
236	 * There's no matching device section in the config file, so quit
237	 * now.
238	 */
239	return FALSE;
240    }
241
242    /*
243     * We need to probe the hardware first.  We then need to see how this
244     * fits in with what is given in the config file, and allow the config
245     * file info to override any contradictions.
246     */
247
248    numUsed = xf86MatchSbusInstances(CG14_NAME, SBUS_DEVICE_CG14,
249		   devSections, numDevSections,
250		   drv, &usedChips);
251
252    xfree(devSections);
253    if (numUsed <= 0)
254	return FALSE;
255
256    if (flags & PROBE_DETECT)
257	foundScreen = TRUE;
258    else for (i = 0; i < numUsed; i++) {
259	pEnt = xf86GetEntityInfo(usedChips[i]);
260
261	/*
262	 * Check that nothing else has claimed the slots.
263	 */
264	if(pEnt->active) {
265	    ScrnInfoPtr pScrn;
266
267	    /* Allocate a ScrnInfoRec and claim the slot */
268	    pScrn = xf86AllocateScreen(drv, 0);
269
270	    /* Fill in what we can of the ScrnInfoRec */
271	    pScrn->driverVersion = CG14_VERSION;
272	    pScrn->driverName	 = CG14_DRIVER_NAME;
273	    pScrn->name		 = CG14_NAME;
274	    pScrn->Probe	 = CG14Probe;
275	    pScrn->PreInit	 = CG14PreInit;
276	    pScrn->ScreenInit	 = CG14ScreenInit;
277  	    pScrn->SwitchMode	 = CG14SwitchMode;
278  	    pScrn->AdjustFrame	 = CG14AdjustFrame;
279	    pScrn->EnterVT	 = CG14EnterVT;
280	    pScrn->LeaveVT	 = CG14LeaveVT;
281	    pScrn->FreeScreen	 = CG14FreeScreen;
282	    pScrn->ValidMode	 = CG14ValidMode;
283	    xf86AddEntityToScreen(pScrn, pEnt->index);
284	    foundScreen = TRUE;
285	}
286	xfree(pEnt);
287    }
288    xfree(usedChips);
289    return foundScreen;
290}
291
292/* Mandatory */
293static Bool
294CG14PreInit(ScrnInfoPtr pScrn, int flags)
295{
296    Cg14Ptr pCg14;
297    sbusDevicePtr psdp = NULL;
298    int i, from;
299
300    if (flags & PROBE_DETECT) return FALSE;
301
302    /*
303     * Note: This function is only called once at server startup, and
304     * not at the start of each server generation.  This means that
305     * only things that are persistent across server generations can
306     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
307     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
308     * are too, and should be used for data that must persist across
309     * server generations.
310     *
311     * Per-generation data should be allocated with
312     * AllocateScreenPrivateIndex() from the ScreenInit() function.
313     */
314
315    /* Allocate the Cg14Rec driverPrivate */
316    if (!CG14GetRec(pScrn)) {
317	return FALSE;
318    }
319    pCg14 = GET_CG14_FROM_SCRN(pScrn);
320
321    /* Set pScrn->monitor */
322    pScrn->monitor = pScrn->confScreen->monitor;
323
324    /* This driver doesn't expect more than one entity per screen */
325    if (pScrn->numEntities > 1)
326	return FALSE;
327    /* This is the general case */
328    for (i = 0; i < pScrn->numEntities; i++) {
329	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
330
331	/* CG14 is purely AFX, but we handle it like SBUS */
332	if (pEnt->location.type == BUS_SBUS) {
333	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
334	    pCg14->psdp = psdp;
335	} else
336	    return FALSE;
337    }
338    if (psdp == NULL)
339	return FALSE;
340
341    /*********************
342    deal with depth
343    *********************/
344
345    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb|Support32bppFb))
346		return FALSE;
347    /* Check that the returned depth is one we support */
348    switch (pScrn->depth) {
349	case 32:
350	case 24:
351	    /* OK */
352	    break;
353	default:
354	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
355		       "Given depth (%d) is not supported by this driver\n",
356		       pScrn->depth);
357	    return FALSE;
358    }
359
360    /* Collect all of the relevant option flags (fill in pScrn->options) */
361    xf86CollectOptions(pScrn, NULL);
362    /* Process the options */
363    if (!(pCg14->Options = xalloc(sizeof(CG14Options))))
364	return FALSE;
365    memcpy(pCg14->Options, CG14Options, sizeof(CG14Options));
366    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCg14->Options);
367    pCg14->use_shadow = xf86ReturnOptValBool(pCg14->Options, OPTION_SHADOW_FB,
368        TRUE);
369
370    /*
371     * This must happen after pScrn->display has been set because
372     * xf86SetWeight references it.
373     */
374    if (pScrn->depth > 8) {
375	rgb weight = {0, 0, 0};
376	rgb mask = {0xff, 0xff00, 0xff0000};
377
378	if (!xf86SetWeight(pScrn, weight, mask)) {
379	    return FALSE;
380	}
381    }
382
383    if (!xf86SetDefaultVisual(pScrn, -1))
384	return FALSE;
385    else if (pScrn->depth > 8) {
386	/* We don't currently support DirectColor */
387	if (pScrn->defaultVisual != TrueColor) {
388	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
389		       " (%s) is not supported\n",
390		       xf86GetVisualName(pScrn->defaultVisual));
391	    return FALSE;
392	}
393    }
394
395    /*
396     * The new cmap code requires this to be initialised.
397     */
398
399    {
400	Gamma zeros = {0.0, 0.0, 0.0};
401
402	if (!xf86SetGamma(pScrn, zeros)) {
403	    return FALSE;
404	}
405    }
406
407    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
408	CG14FreeRec(pScrn);
409	return FALSE;
410    }
411
412    if (pCg14->use_shadow) {
413	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using shadow framebuffer\n");
414	if (xf86LoadSubModule(pScrn, "shadow") == NULL) {
415	    CG14FreeRec(pScrn);
416	    return FALSE;
417	}
418    }
419
420    from = X_DEFAULT;
421    pCg14->HWCursor = TRUE;
422    if (xf86GetOptValBool(pCg14->Options, OPTION_HW_CURSOR, &pCg14->HWCursor))
423	from = X_CONFIG;
424    if (xf86ReturnOptValBool(pCg14->Options, OPTION_SW_CURSOR, FALSE)) {
425	from = X_CONFIG;
426	pCg14->HWCursor = FALSE;
427    }
428    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
429		pCg14->HWCursor ? "HW" : "SW");
430
431    /*********************
432    set up clock and mode stuff
433    *********************/
434
435    pScrn->progClock = TRUE;
436
437    if(pScrn->display->virtualX || pScrn->display->virtualY) {
438	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
439		   "CG14 does not support a virtual desktop\n");
440	pScrn->display->virtualX = 0;
441	pScrn->display->virtualY = 0;
442    }
443
444    xf86SbusUseBuiltinMode(pScrn, pCg14->psdp);
445    pScrn->currentMode = pScrn->modes;
446    pScrn->displayWidth = pScrn->virtualX;
447
448    /* Set display resolution */
449    xf86SetDpi(pScrn, 0, 0);
450
451    return TRUE;
452}
453
454static Bool
455CG14CreateScreenResources(ScreenPtr pScreen)
456{
457    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
458    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
459    PixmapPtr pPixmap;
460    Bool ret;
461
462    pScreen->CreateScreenResources = pCg14->CreateScreenResources;
463    ret = pScreen->CreateScreenResources(pScreen);
464    pScreen->CreateScreenResources = CG14CreateScreenResources;
465
466    if (!ret)
467	return FALSE;
468
469    pPixmap = pScreen->GetScreenPixmap(pScreen);
470
471    if (!shadowAdd(pScreen, pPixmap, shadowUpdatePackedWeak(),
472	CG14WindowLinear, 0, NULL)) {
473	return FALSE;
474    }
475    return TRUE;
476}
477
478
479static Bool
480CG14ShadowInit(ScreenPtr pScreen)
481{
482    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
483    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
484
485    if (!shadowSetup(pScreen)) {
486	return FALSE;
487    }
488
489    pCg14->CreateScreenResources = pScreen->CreateScreenResources;
490    pScreen->CreateScreenResources = CG14CreateScreenResources;
491
492    return TRUE;
493}
494/* Mandatory */
495
496/* This gets called at the start of each server generation */
497
498static Bool
499CG14ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
500{
501    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
502    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
503    VisualPtr visual;
504    int ret;
505
506    /* Map the CG14 memory */
507    pCg14->fb = xf86MapSbusMem (pCg14->psdp, CG14_BGR_VOFF, 4 *
508				(pCg14->psdp->width * pCg14->psdp->height));
509    pCg14->x32 = xf86MapSbusMem (pCg14->psdp, CG14_X32_VOFF,
510				 (pCg14->psdp->width * pCg14->psdp->height));
511    pCg14->xlut = xf86MapSbusMem (pCg14->psdp, CG14_XLUT_VOFF, 4096);
512    pCg14->curs = xf86MapSbusMem (pCg14->psdp, CG14_CURSOR_VOFF, 4096);
513
514    pCg14->width = pCg14->psdp->width;
515    pCg14->height = pCg14->psdp->height;
516
517    if (! pCg14->fb || !pCg14->x32 || !pCg14->xlut || !pCg14->curs) {
518    	xf86Msg(X_ERROR,
519	    "can't mmap something: fd %08x  x32 %08x xlut %08x cursor %08x\n",
520	    (uint32_t)pCg14->fb, (uint32_t)pCg14->x32, (uint32_t)pCg14->xlut,
521	    (uint32_t)pCg14->curs);
522	return FALSE;
523    }
524
525    /* Darken the screen for aesthetic reasons and set the viewport */
526    CG14SaveScreen(pScreen, SCREEN_SAVER_ON);
527
528    /*
529     * The next step is to setup the screen's visuals, and initialise the
530     * framebuffer code.  In cases where the framebuffer's default
531     * choices for things like visual layouts and bits per RGB are OK,
532     * this may be as simple as calling the framebuffer's ScreenInit()
533     * function.  If not, the visuals will need to be setup before calling
534     * a fb ScreenInit() function and fixed up after.
535     */
536
537    /*
538     * Reset visual list.
539     */
540    miClearVisualTypes();
541
542    /* Setup the visuals we support. */
543
544    if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
545			  pScrn->rgbBits, pScrn->defaultVisual))
546	return FALSE;
547
548    miSetPixmapDepths ();
549
550    if (pCg14->use_shadow) {
551	pCg14->shadow = xcalloc(1, pScrn->virtualX * pScrn->virtualY * 4);
552
553	if (!pCg14->shadow) {
554	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
555	        "Failed to allocate shadow framebuffer\n");
556	    return FALSE;
557	}
558    }
559
560    /*
561     * Call the framebuffer layer's ScreenInit function, and fill in other
562     * pScreen fields.
563     */
564
565    CG14InitCplane24(pScrn);
566    ret = fbScreenInit(pScreen, pCg14->use_shadow ? pCg14->shadow : pCg14->fb,
567    		       pScrn->virtualX,
568		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
569		       pScrn->virtualX, pScrn->bitsPerPixel);
570
571    if (!ret)
572	return FALSE;
573
574    /* must be after RGB ordering fixed */
575    fbPictureInit (pScreen, 0, 0);
576
577xf86DrvMsg(scrnIndex, X_ERROR, "calling CG14ShadowInit\n");
578    if (pCg14->use_shadow && !CG14ShadowInit(pScreen)) {
579	xf86DrvMsg(scrnIndex, X_ERROR,
580		    "shadow framebuffer initialization failed\n");
581	return FALSE;
582    }
583
584    miInitializeBackingStore(pScreen);
585    xf86SetBackingStore(pScreen);
586    xf86SetSilkenMouse(pScreen);
587
588    xf86SetBlackWhitePixels(pScreen);
589
590    if (pScrn->bitsPerPixel > 8) {
591	/* Fixup RGB ordering */
592	visual = pScreen->visuals + pScreen->numVisuals;
593	while (--visual >= pScreen->visuals) {
594	    if ((visual->class | DynamicClass) == DirectColor) {
595		visual->offsetRed = pScrn->offset.red;
596		visual->offsetGreen = pScrn->offset.green;
597		visual->offsetBlue = pScrn->offset.blue;
598		visual->redMask = pScrn->mask.red;
599		visual->greenMask = pScrn->mask.green;
600		visual->blueMask = pScrn->mask.blue;
601	    }
602	}
603    }
604
605    /* Initialise cursor functions */
606    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
607
608    /* check for hardware cursor support */
609    if (pCg14->HWCursor)
610	CG14SetupCursor(pScreen);
611
612    /* Initialise default colourmap */
613    if (!miCreateDefColormap(pScreen))
614	return FALSE;
615
616    pCg14->CloseScreen = pScreen->CloseScreen;
617    pScreen->CloseScreen = CG14CloseScreen;
618    pScreen->SaveScreen = CG14SaveScreen;
619
620    /* Report any unused options (only for the first generation) */
621    if (serverGeneration == 1) {
622	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
623    }
624
625    /* unblank the screen */
626    CG14SaveScreen(pScreen, SCREEN_SAVER_OFF);
627
628    /* Done */
629    return TRUE;
630}
631
632
633/* Usually mandatory */
634static Bool
635CG14SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
636{
637    xf86Msg(X_ERROR, "CG14SwitchMode\n");
638    return TRUE;
639}
640
641
642/*
643 * This function is used to initialize the Start Address - the first
644 * displayed location in the video memory.
645 */
646/* Usually mandatory */
647static void
648CG14AdjustFrame(int scrnIndex, int x, int y, int flags)
649{
650    /* we don't support virtual desktops */
651    return;
652}
653
654/*
655 * This is called when VT switching back to the X server.  Its job is
656 * to reinitialise the video mode.
657 */
658
659/* Mandatory */
660static Bool
661CG14EnterVT(int scrnIndex, int flags)
662{
663    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
664
665    CG14InitCplane24 (pScrn);
666    return TRUE;
667}
668
669
670/*
671 * This is called when VT switching away from the X server.
672 */
673
674/* Mandatory */
675static void
676CG14LeaveVT(int scrnIndex, int flags)
677{
678    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
679
680    CG14ExitCplane24 (pScrn);
681    return;
682}
683
684
685/*
686 * This is called at the end of each server generation.  It restores the
687 * original (text) mode.  It should really also unmap the video memory too.
688 */
689
690/* Mandatory */
691static Bool
692CG14CloseScreen(int scrnIndex, ScreenPtr pScreen)
693{
694    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
695    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
696    PixmapPtr pPixmap;
697
698    if (pCg14->use_shadow) {
699
700	pPixmap = pScreen->GetScreenPixmap(pScreen);
701	shadowRemove(pScreen, pPixmap);
702	pCg14->use_shadow = FALSE;
703    }
704
705    pScrn->vtSema = FALSE;
706    CG14ExitCplane24 (pScrn);
707    xf86UnmapSbusMem(pCg14->psdp, pCg14->fb,
708		     (pCg14->psdp->width * pCg14->psdp->height * 4));
709    xf86UnmapSbusMem(pCg14->psdp, pCg14->x32,
710		     (pCg14->psdp->width * pCg14->psdp->height));
711    xf86UnmapSbusMem(pCg14->psdp, pCg14->xlut, 4096);
712    xf86UnmapSbusMem(pCg14->psdp, pCg14->curs, 4096);
713
714    pScreen->CloseScreen = pCg14->CloseScreen;
715    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
716}
717
718static void *
719CG14WindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
720		CARD32 *size, void *closure)
721{
722    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
723    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
724
725    *size = pCg14->width << 2;
726    return (CARD8 *)pCg14->fb + row * (pCg14->width << 2) + offset;
727}
728
729/* Free up any per-generation data structures */
730
731/* Optional */
732static void
733CG14FreeScreen(int scrnIndex, int flags)
734{
735    CG14FreeRec(xf86Screens[scrnIndex]);
736}
737
738
739/* Checks if a mode is suitable for the selected chipset. */
740
741/* Optional */
742static ModeStatus
743CG14ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
744{
745    if (mode->Flags & V_INTERLACE)
746	return(MODE_BAD);
747
748    return(MODE_OK);
749}
750
751/* Do screen blanking */
752
753/* Mandatory */
754static Bool
755CG14SaveScreen(ScreenPtr pScreen, int mode)
756{
757    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
758    Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
759    int state;
760    switch(mode) {
761	case SCREEN_SAVER_ON:
762	case SCREEN_SAVER_CYCLE:
763		state = FBVIDEO_OFF;
764		ioctl(pCg14->psdp->fd, FBIOSVIDEO, &state);
765		break;
766	case SCREEN_SAVER_OFF:
767	case SCREEN_SAVER_FORCER:
768		state = FBVIDEO_ON;
769		ioctl(pCg14->psdp->fd, FBIOSVIDEO, &state);
770		break;
771	default:
772		return FALSE;
773    }
774    return TRUE;
775}
776
777/*
778 * This is the implementation of the Sync() function.
779 */
780void
781CG14Sync(ScrnInfoPtr pScrn)
782{
783    return;
784}
785
786/*
787 * This initializes the card for 24 bit mode.
788 */
789static void
790CG14InitCplane24(ScrnInfoPtr pScrn)
791{
792  Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
793  int size, bpp;
794
795  size = pScrn->virtualX * pScrn->virtualY;
796  bpp = 32;
797  ioctl (pCg14->psdp->fd, CG14_SET_PIXELMODE, &bpp);
798  memset (pCg14->fb, 0, size * 4);
799  memset (pCg14->x32, 0, size);
800  memset (pCg14->xlut, 0, 0x200);
801}
802
803/*
804 * This initializes the card for 8 bit mode.
805 */
806static void
807CG14ExitCplane24(ScrnInfoPtr pScrn)
808{
809  Cg14Ptr pCg14 = GET_CG14_FROM_SCRN(pScrn);
810  int bpp = 8;
811
812  ioctl (pCg14->psdp->fd, CG14_SET_PIXELMODE, &bpp);
813}
814