tcx_driver.c revision ce2d3770
1/*
2 * TCX 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 <fcntl.h>
29#include <sys/types.h>
30#include <sys/time.h>
31#include <string.h>
32#include <sys/ioctl.h>
33#include <dev/sun/fbio.h>
34#include <dev/wscons/wsconsio.h>
35
36#include "xf86.h"
37#include "xf86_OSproc.h"
38#include "mipointer.h"
39#include "micmap.h"
40
41#include "fb.h"
42#include "xf86cmap.h"
43#include "tcx.h"
44
45static const OptionInfoRec * TCXAvailableOptions(int chipid, int busid);
46static void	TCXIdentify(int flags);
47static Bool	TCXProbe(DriverPtr drv, int flags);
48static Bool	TCXPreInit(ScrnInfoPtr pScrn, int flags);
49static Bool	TCXScreenInit(SCREEN_INIT_ARGS_DECL);
50static Bool	TCXEnterVT(VT_FUNC_ARGS_DECL);
51static void	TCXLeaveVT(VT_FUNC_ARGS_DECL);
52static Bool	TCXCloseScreen(CLOSE_SCREEN_ARGS_DECL);
53static Bool	TCXSaveScreen(ScreenPtr pScreen, int mode);
54static void	TCXInitCplane24(ScrnInfoPtr pScrn);
55
56/* Required if the driver supports mode switching */
57static Bool	TCXSwitchMode(SWITCH_MODE_ARGS_DECL);
58/* Required if the driver supports moving the viewport */
59static void	TCXAdjustFrame(ADJUST_FRAME_ARGS_DECL);
60
61/* Optional functions */
62static void	TCXFreeScreen(FREE_SCREEN_ARGS_DECL);
63static ModeStatus TCXValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
64			       Bool verbose, int flags);
65
66void TCXSync(ScrnInfoPtr pScrn);
67
68#define TCX_VERSION 4000
69#define TCX_NAME "SUNTCX"
70#define TCX_DRIVER_NAME "suntcx"
71#define TCX_MAJOR_VERSION PACKAGE_VERSION_MAJOR
72#define TCX_MINOR_VERSION PACKAGE_VERSION_MINOR
73#define TCX_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
74
75/*
76 * This contains the functions needed by the server after loading the driver
77 * module.  It must be supplied, and gets passed back by the SetupProc
78 * function in the dynamic case.  In the static case, a reference to this
79 * is compiled in, and this requires that the name of this DriverRec be
80 * an upper-case version of the driver name.
81 */
82
83_X_EXPORT DriverRec SUNTCX = {
84    TCX_VERSION,
85    TCX_DRIVER_NAME,
86    TCXIdentify,
87    TCXProbe,
88    TCXAvailableOptions,
89    NULL,
90    0
91};
92
93typedef enum {
94    OPTION_SW_CURSOR,
95    OPTION_HW_CURSOR,
96    OPTION_NOACCEL
97} TCXOpts;
98
99static const OptionInfoRec TCXOptions[] = {
100    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
101    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, TRUE  },
102    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
103    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
104};
105
106#ifdef XFree86LOADER
107
108static MODULESETUPPROTO(tcxSetup);
109
110static XF86ModuleVersionInfo suntcxVersRec =
111{
112	"suntcx",
113	MODULEVENDORSTRING,
114	MODINFOSTRING1,
115	MODINFOSTRING2,
116	XORG_VERSION_CURRENT,
117	TCX_MAJOR_VERSION, TCX_MINOR_VERSION, TCX_PATCHLEVEL,
118	ABI_CLASS_VIDEODRV,
119	ABI_VIDEODRV_VERSION,
120	MOD_CLASS_VIDEODRV,
121	{0,0,0,0}
122};
123
124_X_EXPORT XF86ModuleData suntcxModuleData = { &suntcxVersRec, tcxSetup, NULL };
125
126pointer
127tcxSetup(pointer module, pointer opts, int *errmaj, int *errmin)
128{
129    static Bool setupDone = FALSE;
130
131    if (!setupDone) {
132	setupDone = TRUE;
133	xf86AddDriver(&SUNTCX, module, 0);
134
135	/*
136	 * Modules that this driver always requires can be loaded here
137	 * by calling LoadSubModule().
138	 */
139
140	/*
141	 * The return value must be non-NULL on success even though there
142	 * is no TearDownProc.
143	 */
144	return (pointer)TRUE;
145    } else {
146	if (errmaj) *errmaj = LDR_ONCEONLY;
147	return NULL;
148    }
149}
150
151#endif /* XFree86LOADER */
152
153static Bool
154TCXGetRec(ScrnInfoPtr pScrn)
155{
156    /*
157     * Allocate an TcxRec, and hook it into pScrn->driverPrivate.
158     * pScrn->driverPrivate is initialised to NULL, so we can check if
159     * the allocation has already been done.
160     */
161    if (pScrn->driverPrivate != NULL)
162	return TRUE;
163
164    pScrn->driverPrivate = xnfcalloc(sizeof(TcxRec), 1);
165    return TRUE;
166}
167
168static void
169TCXFreeRec(ScrnInfoPtr pScrn)
170{
171    TcxPtr pTcx;
172
173    if (pScrn->driverPrivate == NULL)
174	return;
175
176    pTcx = GET_TCX_FROM_SCRN(pScrn);
177
178    free(pScrn->driverPrivate);
179    pScrn->driverPrivate = NULL;
180
181    return;
182}
183
184static const OptionInfoRec *
185TCXAvailableOptions(int chipid, int busid)
186{
187    return TCXOptions;
188}
189
190/* Mandatory */
191static void
192TCXIdentify(int flags)
193{
194    xf86Msg(X_INFO, "%s: driver for TCX\n", TCX_NAME);
195}
196
197
198/* Mandatory */
199static Bool
200TCXProbe(DriverPtr drv, int flags)
201{
202    int i;
203    GDevPtr *devSections;
204    int *usedChips;
205    int numDevSections;
206    int numUsed;
207    Bool foundScreen = FALSE;
208    EntityInfoPtr pEnt;
209
210    /*
211     * The aim here is to find all cards that this driver can handle,
212     * and for the ones not already claimed by another driver, claim the
213     * slot, and allocate a ScrnInfoRec.
214     *
215     * This should be a minimal probe, and it should under no circumstances
216     * change the state of the hardware.  Because a device is found, don't
217     * assume that it will be used.  Don't do any initialisations other than
218     * the required ScrnInfoRec initialisations.  Don't allocate any new
219     * data structures.
220     */
221
222    /*
223     * Next we check, if there has been a chipset override in the config file.
224     * For this we must find out if there is an active device section which
225     * is relevant, i.e., which has no driver specified or has THIS driver
226     * specified.
227     */
228
229    if ((numDevSections = xf86MatchDevice(TCX_DRIVER_NAME,
230					  &devSections)) <= 0) {
231	/*
232	 * There's no matching device section in the config file, so quit
233	 * now.
234	 */
235	return FALSE;
236    }
237
238    /*
239     * We need to probe the hardware first.  We then need to see how this
240     * fits in with what is given in the config file, and allow the config
241     * file info to override any contradictions.
242     */
243
244    numUsed = xf86MatchSbusInstances(TCX_NAME, SBUS_DEVICE_TCX,
245		   devSections, numDevSections,
246		   drv, &usedChips);
247
248    free(devSections);
249    if (numUsed <= 0)
250	return FALSE;
251
252    if (flags & PROBE_DETECT)
253	foundScreen = TRUE;
254    else for (i = 0; i < numUsed; i++) {
255	pEnt = xf86GetEntityInfo(usedChips[i]);
256
257	/*
258	 * Check that nothing else has claimed the slots.
259	 */
260	if(pEnt->active) {
261	    ScrnInfoPtr pScrn;
262
263	    /* Allocate a ScrnInfoRec and claim the slot */
264	    pScrn = xf86AllocateScreen(drv, 0);
265
266	    /* Fill in what we can of the ScrnInfoRec */
267	    pScrn->driverVersion = TCX_VERSION;
268	    pScrn->driverName	 = TCX_DRIVER_NAME;
269	    pScrn->name		 = TCX_NAME;
270	    pScrn->Probe	 = TCXProbe;
271	    pScrn->PreInit	 = TCXPreInit;
272	    pScrn->ScreenInit	 = TCXScreenInit;
273  	    pScrn->SwitchMode	 = TCXSwitchMode;
274  	    pScrn->AdjustFrame	 = TCXAdjustFrame;
275	    pScrn->EnterVT	 = TCXEnterVT;
276	    pScrn->LeaveVT	 = TCXLeaveVT;
277	    pScrn->FreeScreen	 = TCXFreeScreen;
278	    pScrn->ValidMode	 = TCXValidMode;
279	    xf86AddEntityToScreen(pScrn, pEnt->index);
280	    foundScreen = TRUE;
281	}
282	free(pEnt);
283    }
284    free(usedChips);
285    return foundScreen;
286}
287
288/* Mandatory */
289static Bool
290TCXPreInit(ScrnInfoPtr pScrn, int flags)
291{
292    TcxPtr pTcx;
293    sbusDevicePtr psdp = NULL;
294    MessageType from;
295    int i, prom;
296    int hwCursor, lowDepth;
297
298    if (flags & PROBE_DETECT) return FALSE;
299
300    /*
301     * Note: This function is only called once at server startup, and
302     * not at the start of each server generation.  This means that
303     * only things that are persistent across server generations can
304     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
305     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
306     * are too, and should be used for data that must persist across
307     * server generations.
308     *
309     * Per-generation data should be allocated with
310     * AllocateScreenPrivateIndex() from the ScreenInit() function.
311     */
312
313    /* Allocate the TcxRec driverPrivate */
314    if (!TCXGetRec(pScrn)) {
315	return FALSE;
316    }
317    pTcx = GET_TCX_FROM_SCRN(pScrn);
318
319    /* Set pScrn->monitor */
320    pScrn->monitor = pScrn->confScreen->monitor;
321
322    /* This driver doesn't expect more than one entity per screen */
323    if (pScrn->numEntities > 1)
324	return FALSE;
325    /* This is the general case */
326    for (i = 0; i < pScrn->numEntities; i++) {
327	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
328
329	/* TCX is purely AFX, but we handle it like SBUS */
330	if (pEnt->location.type == BUS_SBUS) {
331	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
332	    pTcx->psdp = psdp;
333	} else
334	    return FALSE;
335    }
336    if (psdp == NULL)
337	return FALSE;
338
339    /**********************
340    check card capabilities
341    **********************/
342    hwCursor = 0;
343    lowDepth = 1;
344
345    prom = sparcPromInit();
346    hwCursor = sparcPromGetBool(&psdp->node, "hw-cursor");
347    lowDepth = sparcPromGetBool(&psdp->node, "tcx-8-bit");
348    if (pTcx->HasStipROP = sparcPromGetBool(&psdp->node, "stip-rop")) {
349	xf86Msg(X_PROBED, "stipple space supports ROPs\n");
350    }
351    pTcx->Is8bit = (lowDepth != 0);
352    /* all S24 support a hardware cursor */
353    if (!lowDepth) {
354	hwCursor = 1;
355	pTcx->vramsize = 0x100000;	/* size of the 8bit fb */
356    } else {
357	char *b;
358	int len = 4, v = 0;
359
360    	/* see if we have more than 1MB vram */
361	pTcx->vramsize = 0x100000;
362	if ((b = sparcPromGetProperty(&psdp->node, "vram", &len)) != NULL) {
363	    memcpy(&v, b, 4);
364	    if ((v > 0) && (v < 3))
365	    	pTcx->vramsize = 0x100000 * v;
366	}
367	xf86Msg(X_PROBED, "found %d MB video memory\n", v);
368
369    }
370    if (prom)
371    	sparcPromClose();
372
373    xf86Msg(X_PROBED, "hardware cursor support %s\n",
374      hwCursor ? "found" : "not found");
375
376    /*********************
377    deal with depth
378    *********************/
379
380    if (!xf86SetDepthBpp(pScrn, lowDepth ? 8 : 0, 0, 0,
381			 lowDepth ? NoDepth24Support : Support32bppFb)) {
382	return FALSE;
383    } else {
384	/* Check that the returned depth is one we support */
385	switch (pScrn->depth) {
386	case 8:
387	    /* OK */
388	    break;
389	case 32:
390	case 24:
391	    /* unless lowDepth OK */
392	    if (lowDepth) {
393		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
394			   "Given depth (32) not supported by hardware\n");
395		return FALSE;
396	    }
397	    break;
398	default:
399	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
400		       "Given depth (%d) is not supported by this driver\n",
401		       pScrn->depth);
402	    return FALSE;
403	}
404    }
405
406    /* Collect all of the relevant option flags (fill in pScrn->options) */
407    xf86CollectOptions(pScrn, NULL);
408    /* Process the options */
409    if (!(pTcx->Options = malloc(sizeof(TCXOptions))))
410	return FALSE;
411    memcpy(pTcx->Options, TCXOptions, sizeof(TCXOptions));
412    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTcx->Options);
413
414    /*
415     * This must happen after pScrn->display has been set because
416     * xf86SetWeight references it.
417     */
418    if (pScrn->depth > 8) {
419	rgb weight = {0, 0, 0};
420	rgb mask = {0xff, 0xff00, 0xff0000};
421
422	if (!xf86SetWeight(pScrn, weight, mask)) {
423	    return FALSE;
424	}
425    }
426
427    if (!xf86SetDefaultVisual(pScrn, -1))
428	return FALSE;
429    else if (pScrn->depth > 8) {
430	/* We don't currently support DirectColor */
431	if (pScrn->defaultVisual != TrueColor) {
432	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
433		       " (%s) is not supported\n",
434		       xf86GetVisualName(pScrn->defaultVisual));
435	    return FALSE;
436	}
437    }
438
439    /*
440     * The new cmap code requires this to be initialised.
441     */
442
443    {
444	Gamma zeros = {0.0, 0.0, 0.0};
445
446	if (!xf86SetGamma(pScrn, zeros)) {
447	    return FALSE;
448	}
449    }
450
451    /* determine whether we use hardware or software cursor */
452
453    from = X_PROBED;
454    pTcx->HWCursor = FALSE;
455    if (hwCursor) {
456	from = X_DEFAULT;
457	pTcx->HWCursor = TRUE;
458	if (xf86GetOptValBool(pTcx->Options, OPTION_HW_CURSOR, &pTcx->HWCursor))
459	    from = X_CONFIG;
460	if (xf86ReturnOptValBool(pTcx->Options, OPTION_SW_CURSOR, FALSE)) {
461	    from = X_CONFIG;
462	    pTcx->HWCursor = FALSE;
463	}
464    }
465
466    pTcx->NoAccel = FALSE;
467    if (xf86ReturnOptValBool(pTcx->Options, OPTION_NOACCEL, FALSE)) {
468	pTcx->NoAccel = TRUE;
469	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
470    }
471
472    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
473		pTcx->HWCursor ? "HW" : "SW");
474
475    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
476	TCXFreeRec(pScrn);
477	return FALSE;
478    }
479
480    if (pTcx->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
481	TCXFreeRec(pScrn);
482	return FALSE;
483    }
484
485    /*********************
486    set up clock and mode stuff
487    *********************/
488
489    pScrn->progClock = TRUE;
490
491    if(pScrn->display->virtualX || pScrn->display->virtualY) {
492	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
493		   "TCX does not support a virtual desktop\n");
494	pScrn->display->virtualX = 0;
495	pScrn->display->virtualY = 0;
496    }
497
498    xf86SbusUseBuiltinMode(pScrn, pTcx->psdp);
499    pScrn->currentMode = pScrn->modes;
500    pScrn->displayWidth = pScrn->virtualX;
501
502    /* Set display resolution */
503    xf86SetDpi(pScrn, 0, 0);
504
505    return TRUE;
506}
507
508/* Mandatory */
509
510/* This gets called at the start of each server generation */
511
512static Bool
513TCXScreenInit(SCREEN_INIT_ARGS_DECL)
514{
515    ScrnInfoPtr pScrn;
516    TcxPtr pTcx;
517    VisualPtr visual;
518    int ret;
519
520    /*
521     * First get the ScrnInfoRec
522     */
523    pScrn = xf86ScreenToScrn(pScreen);
524
525    pTcx = GET_TCX_FROM_SCRN(pScrn);
526
527    /* Map the TCX memory */
528    if (pScrn->depth == 8) {
529	pTcx->fb =
530	    xf86MapSbusMem (pTcx->psdp, TCX_RAM8_VOFF, pTcx->vramsize);
531	pTcx->pitchshift = 0;
532    } else {
533	pTcx->fb =
534	    xf86MapSbusMem (pTcx->psdp, TCX_RAM24_VOFF, 1024 * 1024 * 4);
535	pTcx->cplane =
536	    xf86MapSbusMem (pTcx->psdp, TCX_CPLANE_VOFF, 1024 * 1024 * 4);
537	pTcx->pitchshift = 2;
538	if (! pTcx->cplane)
539	    return FALSE;
540    }
541    if (pTcx->HWCursor == TRUE) {
542	pTcx->thc = xf86MapSbusMem (pTcx->psdp, TCX_THC_VOFF, 8192);
543	if (! pTcx->thc)
544	    return FALSE;
545    }
546
547    if (pTcx->Is8bit) {
548    	/* use STIP and BLIT on tcx */
549        pTcx->rblit = xf86MapSbusMem(pTcx->psdp, TCX_BLIT_VOFF, 8 * pTcx->vramsize);
550        if (pTcx->rblit == NULL) {
551	    xf86Msg(X_ERROR, "Couldn't map BLIT space\n");
552	    return FALSE;
553        }
554        pTcx->rstip = xf86MapSbusMem(pTcx->psdp, TCX_STIP_VOFF, 8 * pTcx->vramsize);
555        if (pTcx->rstip == NULL) {
556	    xf86Msg(X_ERROR, "Couldn't map STIP space\n");
557	    return FALSE;
558	}
559    } else {
560    	/* use RSTIP and RBLIT on S24 */
561        pTcx->rblit = xf86MapSbusMem(pTcx->psdp, TCX_RBLIT_VOFF, 8 * 1024 * 1024);
562        if (pTcx->rblit == NULL) {
563	    xf86Msg(X_ERROR, "Couldn't map RBLIT space\n");
564	    return FALSE;
565        }
566        pTcx->rstip = xf86MapSbusMem(pTcx->psdp, TCX_RSTIP_VOFF, 8 * 1024 * 1024);
567        if (pTcx->rstip == NULL) {
568	    xf86Msg(X_ERROR, "Couldn't map RSTIP space\n");
569	    return FALSE;
570	}
571    }
572
573    if (! pTcx->fb)
574	return FALSE;
575
576    /* Darken the screen for aesthetic reasons and set the viewport */
577    TCXSaveScreen(pScreen, SCREEN_SAVER_ON);
578
579    /*
580     * The next step is to setup the screen's visuals, and initialise the
581     * framebuffer code.  In cases where the framebuffer's default
582     * choices for things like visual layouts and bits per RGB are OK,
583     * this may be as simple as calling the framebuffer's ScreenInit()
584     * function.  If not, the visuals will need to be setup before calling
585     * a fb ScreenInit() function and fixed up after.
586     */
587
588    /*
589     * Reset visual list.
590     */
591    miClearVisualTypes();
592
593    if (pScrn->depth == 8)
594	/* Set the bits per RGB for 8bpp mode */
595	pScrn->rgbBits = 8;
596
597    /* Setup the visuals we support. */
598
599    if (!miSetVisualTypes(pScrn->depth,
600			  pScrn->depth != 8 ? TrueColorMask :
601				miGetDefaultVisualMask(pScrn->depth),
602			  pScrn->rgbBits, pScrn->defaultVisual))
603	return FALSE;
604
605    miSetPixmapDepths ();
606
607    /*
608     * Call the framebuffer layer's ScreenInit function, and fill in other
609     * pScreen fields.
610     */
611
612    if (pScrn->bitsPerPixel != 8)
613	TCXInitCplane24(pScrn);
614    ret = fbScreenInit(pScreen, pTcx->fb, pScrn->virtualX,
615		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
616		       pScrn->virtualX, pScrn->bitsPerPixel);
617
618    if (!ret)
619	return FALSE;
620
621    xf86SetBlackWhitePixels(pScreen);
622
623    if (pScrn->bitsPerPixel > 8) {
624	/* Fixup RGB ordering */
625	visual = pScreen->visuals + pScreen->numVisuals;
626	while (--visual >= pScreen->visuals) {
627	    if ((visual->class | DynamicClass) == DirectColor) {
628		visual->offsetRed = pScrn->offset.red;
629		visual->offsetGreen = pScrn->offset.green;
630		visual->offsetBlue = pScrn->offset.blue;
631		visual->redMask = pScrn->mask.red;
632		visual->greenMask = pScrn->mask.green;
633		visual->blueMask = pScrn->mask.blue;
634	    }
635	}
636    }
637
638#ifdef RENDER
639    /* must be after RGB ordering fixed */
640    fbPictureInit (pScreen, 0, 0);
641#endif
642
643    if (!pTcx->NoAccel) {
644        XF86ModReqInfo req;
645        int errmaj, errmin;
646
647        memset(&req, 0, sizeof(XF86ModReqInfo));
648        req.majorversion = 2;
649        req.minorversion = 0;
650        if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
651            &errmaj, &errmin))
652        {
653            LoaderErrorMsg(NULL, "exa", errmaj, errmin);
654            return FALSE;
655        }
656	if (!TcxInitAccel(pScreen))
657	    return FALSE;
658    }
659
660    xf86SetBackingStore(pScreen);
661    xf86SetSilkenMouse(pScreen);
662
663    /* Initialise cursor functions */
664    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
665
666    /* Initialize HW cursor layer.
667       Must follow software cursor initialization*/
668    if (pTcx->HWCursor) {
669	extern Bool TCXHWCursorInit(ScreenPtr pScreen);
670
671	if(!TCXHWCursorInit(pScreen)) {
672	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
673		       "Hardware cursor initialization failed\n");
674	    return(FALSE);
675	}
676	xf86SbusHideOsHwCursor(pTcx->psdp);
677    }
678
679    /* Initialise default colourmap */
680    if (!miCreateDefColormap(pScreen))
681	return FALSE;
682
683    if(pScrn->depth == 8 && !xf86SbusHandleColormaps(pScreen, pTcx->psdp))
684	return FALSE;
685
686    pTcx->CloseScreen = pScreen->CloseScreen;
687    pScreen->CloseScreen = TCXCloseScreen;
688    pScreen->SaveScreen = TCXSaveScreen;
689
690    /* Report any unused options (only for the first generation) */
691    if (serverGeneration == 1) {
692	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
693    }
694
695    /* unblank the screen */
696    TCXSaveScreen(pScreen, SCREEN_SAVER_OFF);
697
698    /* Done */
699    return TRUE;
700}
701
702
703/* Usually mandatory */
704static Bool
705TCXSwitchMode(SWITCH_MODE_ARGS_DECL)
706{
707    return TRUE;
708}
709
710
711/*
712 * This function is used to initialize the Start Address - the first
713 * displayed location in the video memory.
714 */
715/* Usually mandatory */
716static void
717TCXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
718{
719    /* we don't support virtual desktops */
720    return;
721}
722
723/*
724 * This is called when VT switching back to the X server.  Its job is
725 * to reinitialise the video mode.
726 */
727
728/* Mandatory */
729static Bool
730TCXEnterVT(VT_FUNC_ARGS_DECL)
731{
732    SCRN_INFO_PTR(arg);
733    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
734
735    if (pTcx->HWCursor) {
736	xf86SbusHideOsHwCursor (pTcx->psdp);
737	pTcx->CursorFg = 0;
738	pTcx->CursorBg = 0;
739    }
740    if (pTcx->cplane) {
741	TCXInitCplane24 (pScrn);
742    }
743    return TRUE;
744}
745
746
747/*
748 * This is called when VT switching away from the X server.
749 */
750
751/* Mandatory */
752static void
753TCXLeaveVT(VT_FUNC_ARGS_DECL)
754{
755    return;
756}
757
758
759/*
760 * This is called at the end of each server generation.  It restores the
761 * original (text) mode.  It should really also unmap the video memory too.
762 */
763
764/* Mandatory */
765static Bool
766TCXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
767{
768    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
769    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
770
771    pScrn->vtSema = FALSE;
772    if (pScrn->depth == 8)
773	xf86UnmapSbusMem(pTcx->psdp, pTcx->fb,
774			 (pTcx->psdp->width * pTcx->psdp->height));
775    else {
776	xf86UnmapSbusMem(pTcx->psdp, pTcx->fb,
777			 (pTcx->psdp->width * pTcx->psdp->height * 4));
778	xf86UnmapSbusMem(pTcx->psdp, pTcx->cplane,
779			 (pTcx->psdp->width * pTcx->psdp->height * 4));
780    }
781    if (pTcx->thc)
782	xf86UnmapSbusMem(pTcx->psdp, pTcx->thc, 8192);
783
784    if (pTcx->HWCursor)
785	xf86SbusHideOsHwCursor (pTcx->psdp);
786
787    pScreen->CloseScreen = pTcx->CloseScreen;
788    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
789}
790
791
792/* Free up any per-generation data structures */
793
794/* Optional */
795static void
796TCXFreeScreen(FREE_SCREEN_ARGS_DECL)
797{
798    SCRN_INFO_PTR(arg);
799    TCXFreeRec(pScrn);
800}
801
802
803/* Checks if a mode is suitable for the selected chipset. */
804
805/* Optional */
806static ModeStatus
807TCXValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
808{
809    if (mode->Flags & V_INTERLACE)
810	return(MODE_BAD);
811
812    return(MODE_OK);
813}
814
815/* Do screen blanking */
816
817/* Mandatory */
818static Bool
819TCXSaveScreen(ScreenPtr pScreen, int mode)
820    /* this function should blank the screen when unblank is FALSE and
821       unblank it when unblank is TRUE -- it doesn't actually seem to be
822       used for much though */
823{
824    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
825    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
826    int fd = pTcx->psdp->fd, state;
827
828    /*
829     * we're using ioctl() instead of just whacking the DAC because the
830     * underlying driver will also turn off the backlight which we couldn't do
831     * from here without adding lots more hardware dependencies
832     */
833    switch(mode)
834    {
835	case SCREEN_SAVER_ON:
836	case SCREEN_SAVER_CYCLE:
837    		state = 0;
838		if(ioctl(fd, FBIOSVIDEO, &state) == -1)
839		{
840			/* complain */
841		}
842		break;
843	case SCREEN_SAVER_OFF:
844	case SCREEN_SAVER_FORCER:
845    		state = 1;
846		if(ioctl(fd, FBIOSVIDEO, &state) == -1)
847		{
848			/* complain */
849		}
850		break;
851	default:
852		return FALSE;
853    }
854
855    return TRUE;
856}
857
858/*
859 * This is the implementation of the Sync() function.
860 */
861void
862TCXSync(ScrnInfoPtr pScrn)
863{
864    return;
865}
866
867/*
868 * This initializes CPLANE for 24 bit mode.
869 */
870static void
871TCXInitCplane24(ScrnInfoPtr pScrn)
872{
873    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
874    int size;
875    unsigned int *p, *q;
876
877    if (!pTcx->cplane)
878	return;
879
880    size = pScrn->virtualX * pScrn->virtualY;
881    memset (pTcx->fb, 0, size * 4);
882    p = pTcx->cplane;
883    for (q = pTcx->cplane + size; p != q; p++)
884	*p = (*p & 0xffffff) | TCX_CPLANE_MODE;
885}
886