198bb403aSmacallan/*
298bb403aSmacallan * Fujitsu AG-10e framebuffer driver.
398bb403aSmacallan *
498bb403aSmacallan * Copyright (C) 2007 Michael Lorenz
598bb403aSmacallan *
698bb403aSmacallan * Permission is hereby granted, free of charge, to any person obtaining a copy
798bb403aSmacallan * of this software and associated documentation files (the "Software"), to deal
898bb403aSmacallan * in the Software without restriction, including without limitation the rights
998bb403aSmacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1098bb403aSmacallan * copies of the Software, and to permit persons to whom the Software is
1198bb403aSmacallan * furnished to do so, subject to the following conditions:
1298bb403aSmacallan *
1398bb403aSmacallan * The above copyright notice and this permission notice shall be included in
1498bb403aSmacallan * all copies or substantial portions of the Software.
1598bb403aSmacallan *
1698bb403aSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1798bb403aSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1898bb403aSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1998bb403aSmacallan * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
2098bb403aSmacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2198bb403aSmacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2298bb403aSmacallan */
2398bb403aSmacallan/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/suncg6/cg6_driver.c,v 1.12 2005/02/18 02:55:09 dawes Exp $ */
2498bb403aSmacallan
2598bb403aSmacallan/* need this for PRIxPTR macro */
2698bb403aSmacallan
2798bb403aSmacallan#ifdef HAVE_CONFIG_H
2898bb403aSmacallan#include "config.h"
2998bb403aSmacallan#endif
3098bb403aSmacallan
3198bb403aSmacallan#include <fcntl.h>
3298bb403aSmacallan#include <sys/time.h>
3398bb403aSmacallan#include <sys/types.h>
34e8736c93Schristos#include <sys/ioctl.h>
3598bb403aSmacallan#include <dev/sun/fbio.h>
3698bb403aSmacallan#include <dev/wscons/wsconsio.h>
3798bb403aSmacallan
3898bb403aSmacallan#include <machine/int_fmtio.h>
3998bb403aSmacallan#include "xf86.h"
4098bb403aSmacallan#include "xf86_OSproc.h"
4198bb403aSmacallan#include "mipointer.h"
4298bb403aSmacallan#include "micmap.h"
4398bb403aSmacallan
4498bb403aSmacallan#include "fb.h"
4598bb403aSmacallan#include "xf86cmap.h"
4698bb403aSmacallan#include "ag10e.h"
4798bb403aSmacallan#include "xf86sbusBus.h"
4898bb403aSmacallan
49c59a3c9dSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 6
501b41fcf5Smrg#define xf86LoaderReqSymLists(...) do {} while (0)
511b41fcf5Smrg#define LoaderRefSymLists(...) do {} while (0)
521b41fcf5Smrg#endif
531b41fcf5Smrg
5498bb403aSmacallanstatic const OptionInfoRec * AG10EAvailableOptions(int chipid, int busid);
5598bb403aSmacallanstatic void	AG10EIdentify(int flags);
5698bb403aSmacallanstatic Bool	AG10EProbe(DriverPtr drv, int flags);
5798bb403aSmacallanstatic Bool	AG10EPreInit(ScrnInfoPtr pScrn, int flags);
5898bb403aSmacallanstatic Bool	AG10EScreenInit(int Index, ScreenPtr pScreen, int argc,
5998bb403aSmacallan			      char **argv);
6098bb403aSmacallanstatic Bool	AG10EEnterVT(int scrnIndex, int flags);
6198bb403aSmacallanstatic void	AG10ELeaveVT(int scrnIndex, int flags);
6298bb403aSmacallanstatic Bool	AG10ECloseScreen(int scrnIndex, ScreenPtr pScreen);
6398bb403aSmacallanstatic Bool	AG10ESaveScreen(ScreenPtr pScreen, int mode);
6498bb403aSmacallan
6598bb403aSmacallan/* Required if the driver supports mode switching */
6698bb403aSmacallanstatic Bool	AG10ESwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
6798bb403aSmacallan/* Required if the driver supports moving the viewport */
6898bb403aSmacallanstatic void	AG10EAdjustFrame(int scrnIndex, int x, int y, int flags);
6998bb403aSmacallan
7098bb403aSmacallan/* Optional functions */
7198bb403aSmacallanstatic void	AG10EFreeScreen(int scrnIndex, int flags);
7298bb403aSmacallanstatic ModeStatus AG10EValidMode(int scrnIndex, DisplayModePtr mode,
7398bb403aSmacallan			       Bool verbose, int flags);
7498bb403aSmacallan
7598bb403aSmacallan#define VERSION 4000
7698bb403aSmacallan#define AG10E_NAME "AG10E"
7798bb403aSmacallan#define AG10E_DRIVER_NAME "ag10e"
7898bb403aSmacallan#define AG10E_MAJOR_VERSION 1
7998bb403aSmacallan#define AG10E_MINOR_VERSION 0
8098bb403aSmacallan#define AG10E_PATCHLEVEL 0
8198bb403aSmacallan
8298bb403aSmacallan/*
8398bb403aSmacallan * This contains the functions needed by the server after loading the driver
8498bb403aSmacallan * module.  It must be supplied, and gets passed back by the SetupProc
8598bb403aSmacallan * function in the dynamic case.  In the static case, a reference to this
8698bb403aSmacallan * is compiled in, and this requires that the name of this DriverRec be
8798bb403aSmacallan * an upper-case version of the driver name.
8898bb403aSmacallan */
8998bb403aSmacallan
9098bb403aSmacallanDriverRec AG10E = {
9198bb403aSmacallan    VERSION,
9298bb403aSmacallan    AG10E_DRIVER_NAME,
9398bb403aSmacallan    AG10EIdentify,
9498bb403aSmacallan    AG10EProbe,
9598bb403aSmacallan    AG10EAvailableOptions,
9698bb403aSmacallan    NULL,
9798bb403aSmacallan    0
9898bb403aSmacallan};
9998bb403aSmacallan
10098bb403aSmacallantypedef enum {
10198bb403aSmacallan    OPTION_SW_CURSOR,
10298bb403aSmacallan    OPTION_HW_CURSOR,
10398bb403aSmacallan    OPTION_NOACCEL
10498bb403aSmacallan} AG10EOpts;
10598bb403aSmacallan
10698bb403aSmacallanstatic const OptionInfoRec AG10EOptions[] = {
10798bb403aSmacallan    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
10898bb403aSmacallan    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
10998bb403aSmacallan    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
11098bb403aSmacallan    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
11198bb403aSmacallan};
11298bb403aSmacallan
11398bb403aSmacallanstatic const char *xaaSymbols[] =
11498bb403aSmacallan{
11598bb403aSmacallan    "XAACreateInfoRec",
11698bb403aSmacallan    "XAADestroyInfoRec",
11798bb403aSmacallan    "XAAInit",
11898bb403aSmacallan    NULL
11998bb403aSmacallan};
12098bb403aSmacallan
12198bb403aSmacallan#ifdef XFree86LOADER
12298bb403aSmacallan
12398bb403aSmacallanstatic MODULESETUPPROTO(AG10ESetup);
12498bb403aSmacallan
12598bb403aSmacallanstatic XF86ModuleVersionInfo AG10EVersRec =
12698bb403aSmacallan{
12798bb403aSmacallan	"ag10e",
12898bb403aSmacallan	MODULEVENDORSTRING,
12998bb403aSmacallan	MODINFOSTRING1,
13098bb403aSmacallan	MODINFOSTRING2,
13198bb403aSmacallan	XORG_VERSION_CURRENT,
13298bb403aSmacallan	AG10E_MAJOR_VERSION, AG10E_MINOR_VERSION, AG10E_PATCHLEVEL,
13398bb403aSmacallan	ABI_CLASS_VIDEODRV,
13498bb403aSmacallan	ABI_VIDEODRV_VERSION,
13598bb403aSmacallan	MOD_CLASS_VIDEODRV,
13698bb403aSmacallan	{0,0,0,0}
13798bb403aSmacallan};
13898bb403aSmacallan
13998bb403aSmacallan_X_EXPORT XF86ModuleData ag10eModuleData = { &AG10EVersRec, AG10ESetup, NULL };
14098bb403aSmacallan
14198bb403aSmacallanstatic pointer
14298bb403aSmacallanAG10ESetup(pointer module, pointer opts, int *errmaj, int *errmin)
14398bb403aSmacallan{
14498bb403aSmacallan    static Bool setupDone = FALSE;
14598bb403aSmacallan
14698bb403aSmacallan    if (!setupDone) {
14798bb403aSmacallan	setupDone = TRUE;
14898bb403aSmacallan	xf86AddDriver(&AG10E, module, 0);
14998bb403aSmacallan
15098bb403aSmacallan	/*
15198bb403aSmacallan	 * Modules that this driver always requires can be loaded here
15298bb403aSmacallan	 * by calling LoadSubModule().
15398bb403aSmacallan	 */
15498bb403aSmacallan	LoaderRefSymLists(xaaSymbols, NULL);
15598bb403aSmacallan
15698bb403aSmacallan	/*
15798bb403aSmacallan	 * The return value must be non-NULL on success even though there
15898bb403aSmacallan	 * is no TearDownProc.
15998bb403aSmacallan	 */
16098bb403aSmacallan	return (pointer)TRUE;
16198bb403aSmacallan    } else {
16298bb403aSmacallan	if (errmaj) *errmaj = LDR_ONCEONLY;
16398bb403aSmacallan	return NULL;
16498bb403aSmacallan    }
16598bb403aSmacallan}
16698bb403aSmacallan
16798bb403aSmacallan#endif /* XFree86LOADER */
16898bb403aSmacallan
16998bb403aSmacallanstatic Bool
17098bb403aSmacallanAG10EGetRec(ScrnInfoPtr pScrn)
17198bb403aSmacallan{
17298bb403aSmacallan    /*
17398bb403aSmacallan     * Allocate an AG10ERec, and hook it into pScrn->driverPrivate.
17498bb403aSmacallan     * pScrn->driverPrivate is initialised to NULL, so we can check if
17598bb403aSmacallan     * the allocation has already been done.
17698bb403aSmacallan     */
17798bb403aSmacallan    if (pScrn->driverPrivate != NULL)
17898bb403aSmacallan	return TRUE;
17998bb403aSmacallan
18098bb403aSmacallan    pScrn->driverPrivate = xnfcalloc(sizeof(AG10ERec), 1);
18198bb403aSmacallan    return TRUE;
18298bb403aSmacallan}
18398bb403aSmacallan
18498bb403aSmacallanstatic void
18598bb403aSmacallanAG10EFreeRec(ScrnInfoPtr pScrn)
18698bb403aSmacallan{
18798bb403aSmacallan    AG10EPtr pAG10E;
18898bb403aSmacallan
18998bb403aSmacallan    if (pScrn->driverPrivate == NULL)
19098bb403aSmacallan	return;
19198bb403aSmacallan
19298bb403aSmacallan    pAG10E = GET_AG10E_FROM_SCRN(pScrn);
19398bb403aSmacallan
19498bb403aSmacallan    xfree(pScrn->driverPrivate);
19598bb403aSmacallan    pScrn->driverPrivate = NULL;
19698bb403aSmacallan
19798bb403aSmacallan    return;
19898bb403aSmacallan}
19998bb403aSmacallan
20098bb403aSmacallanstatic const OptionInfoRec *
20198bb403aSmacallanAG10EAvailableOptions(int chipid, int busid)
20298bb403aSmacallan{
20398bb403aSmacallan    return AG10EOptions;
20498bb403aSmacallan}
20598bb403aSmacallan
20698bb403aSmacallan/* Mandatory */
20798bb403aSmacallanstatic void
20898bb403aSmacallanAG10EIdentify(int flags)
20998bb403aSmacallan{
21098bb403aSmacallan    xf86Msg(X_INFO, "%s: driver for Fujitsu AG-10e\n", AG10E_NAME);
21198bb403aSmacallan}
21298bb403aSmacallan
21398bb403aSmacallan
21498bb403aSmacallan/* Mandatory */
21598bb403aSmacallanstatic Bool
21698bb403aSmacallanAG10EProbe(DriverPtr drv, int flags)
21798bb403aSmacallan{
21898bb403aSmacallan    int i;
21998bb403aSmacallan    GDevPtr *devSections;
22098bb403aSmacallan    int *usedChips;
22198bb403aSmacallan    int numDevSections;
22298bb403aSmacallan    int numUsed;
22398bb403aSmacallan    Bool foundScreen = FALSE;
22498bb403aSmacallan    EntityInfoPtr pEnt;
22598bb403aSmacallan
22698bb403aSmacallan    /*
22798bb403aSmacallan     * The aim here is to find all cards that this driver can handle,
22898bb403aSmacallan     * and for the ones not already claimed by another driver, claim the
22998bb403aSmacallan     * slot, and allocate a ScrnInfoRec.
23098bb403aSmacallan     *
23198bb403aSmacallan     * This should be a minimal probe, and it should under no circumstances
23298bb403aSmacallan     * change the state of the hardware.  Because a device is found, don't
23398bb403aSmacallan     * assume that it will be used.  Don't do any initialisations other than
23498bb403aSmacallan     * the required ScrnInfoRec initialisations.  Don't allocate any new
23598bb403aSmacallan     * data structures.
23698bb403aSmacallan     */
23798bb403aSmacallan
23898bb403aSmacallan    /*
23998bb403aSmacallan     * Next we check, if there has been a chipset override in the config file.
24098bb403aSmacallan     * For this we must find out if there is an active device section which
24198bb403aSmacallan     * is relevant, i.e., which has no driver specified or has THIS driver
24298bb403aSmacallan     * specified.
24398bb403aSmacallan     */
24498bb403aSmacallan
24598bb403aSmacallan    if ((numDevSections = xf86MatchDevice(AG10E_DRIVER_NAME,
24698bb403aSmacallan					  &devSections)) <= 0) {
24798bb403aSmacallan	/*
24898bb403aSmacallan	 * There's no matching device section in the config file, so quit
24998bb403aSmacallan	 * now.
25098bb403aSmacallan	 */
25198bb403aSmacallan	return FALSE;
25298bb403aSmacallan    }
25398bb403aSmacallan
25498bb403aSmacallan    /*
25598bb403aSmacallan     * We need to probe the hardware first.  We then need to see how this
25698bb403aSmacallan     * fits in with what is given in the config file, and allow the config
25798bb403aSmacallan     * file info to override any contradictions.
25898bb403aSmacallan     */
25998bb403aSmacallan
26098bb403aSmacallan    numUsed = xf86MatchSbusInstances(AG10E_NAME, SBUS_DEVICE_AG10E,
26198bb403aSmacallan		   devSections, numDevSections,
26298bb403aSmacallan		   drv, &usedChips);
26398bb403aSmacallan
26498bb403aSmacallan    xfree(devSections);
26598bb403aSmacallan    if (numUsed <= 0)
26698bb403aSmacallan	return FALSE;
26798bb403aSmacallan
26898bb403aSmacallan    if (flags & PROBE_DETECT)
26998bb403aSmacallan	foundScreen = TRUE;
27098bb403aSmacallan    else for (i = 0; i < numUsed; i++) {
27198bb403aSmacallan	pEnt = xf86GetEntityInfo(usedChips[i]);
27298bb403aSmacallan
27398bb403aSmacallan	/*
27498bb403aSmacallan	 * Check that nothing else has claimed the slots.
27598bb403aSmacallan	 */
27698bb403aSmacallan	if(pEnt->active) {
27798bb403aSmacallan	    ScrnInfoPtr pScrn;
27898bb403aSmacallan
27998bb403aSmacallan	    /* Allocate a ScrnInfoRec and claim the slot */
28098bb403aSmacallan	    pScrn = xf86AllocateScreen(drv, 0);
28198bb403aSmacallan
28298bb403aSmacallan	    /* Fill in what we can of the ScrnInfoRec */
28398bb403aSmacallan	    pScrn->driverVersion = VERSION;
28498bb403aSmacallan	    pScrn->driverName	 = AG10E_DRIVER_NAME;
28598bb403aSmacallan	    pScrn->name		 = AG10E_NAME;
28698bb403aSmacallan	    pScrn->Probe	 = AG10EProbe;
28798bb403aSmacallan	    pScrn->PreInit	 = AG10EPreInit;
28898bb403aSmacallan	    pScrn->ScreenInit	 = AG10EScreenInit;
28998bb403aSmacallan	    pScrn->SwitchMode	 = AG10ESwitchMode;
29098bb403aSmacallan	    pScrn->AdjustFrame	 = AG10EAdjustFrame;
29198bb403aSmacallan	    pScrn->EnterVT	 = AG10EEnterVT;
29298bb403aSmacallan	    pScrn->LeaveVT	 = AG10ELeaveVT;
29398bb403aSmacallan	    pScrn->FreeScreen	 = AG10EFreeScreen;
29498bb403aSmacallan	    pScrn->ValidMode	 = AG10EValidMode;
29598bb403aSmacallan	    xf86AddEntityToScreen(pScrn, pEnt->index);
29698bb403aSmacallan	    foundScreen = TRUE;
29798bb403aSmacallan	}
29898bb403aSmacallan	xfree(pEnt);
29998bb403aSmacallan    }
30098bb403aSmacallan    xfree(usedChips);
30198bb403aSmacallan    return foundScreen;
30298bb403aSmacallan}
30398bb403aSmacallan
30498bb403aSmacallan/* Mandatory */
30598bb403aSmacallanstatic Bool
30698bb403aSmacallanAG10EPreInit(ScrnInfoPtr pScrn, int flags)
30798bb403aSmacallan{
30898bb403aSmacallan    AG10EPtr pAG10E;
30998bb403aSmacallan    sbusDevicePtr psdp;
31098bb403aSmacallan    rgb defaultWeight = {0, 0, 0};
31198bb403aSmacallan    MessageType from;
31298bb403aSmacallan    int i;
31398bb403aSmacallan
31498bb403aSmacallan    if (flags & PROBE_DETECT) return FALSE;
31598bb403aSmacallan
31698bb403aSmacallan    /*
31798bb403aSmacallan     * Note: This function is only called once at server startup, and
31898bb403aSmacallan     * not at the start of each server generation.  This means that
31998bb403aSmacallan     * only things that are persistent across server generations can
32098bb403aSmacallan     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
32198bb403aSmacallan     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
32298bb403aSmacallan     * are too, and should be used for data that must persist across
32398bb403aSmacallan     * server generations.
32498bb403aSmacallan     *
32598bb403aSmacallan     * Per-generation data should be allocated with
32698bb403aSmacallan     * AllocateScreenPrivateIndex() from the ScreenInit() function.
32798bb403aSmacallan     */
32898bb403aSmacallan
32998bb403aSmacallan    /* Allocate the AG10ERec driverPrivate */
33098bb403aSmacallan    if (!AG10EGetRec(pScrn)) {
33198bb403aSmacallan	return FALSE;
33298bb403aSmacallan    }
33398bb403aSmacallan    pAG10E = GET_AG10E_FROM_SCRN(pScrn);
33498bb403aSmacallan
33598bb403aSmacallan    /* Set pScrn->monitor */
33698bb403aSmacallan    pScrn->monitor = pScrn->confScreen->monitor;
33798bb403aSmacallan
33898bb403aSmacallan    /* This driver doesn't expect more than one entity per screen */
33998bb403aSmacallan    if (pScrn->numEntities > 1)
34098bb403aSmacallan	return FALSE;
34198bb403aSmacallan    /* This is the general case */
34298bb403aSmacallan    for (i = 0; i < pScrn->numEntities; i++) {
34398bb403aSmacallan	EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
34498bb403aSmacallan
34598bb403aSmacallan	/* AG10E is purely SBUS */
34698bb403aSmacallan	if (pEnt->location.type == BUS_SBUS) {
34798bb403aSmacallan	    psdp = xf86GetSbusInfoForEntity(pEnt->index);
34898bb403aSmacallan	    pAG10E->psdp = psdp;
34998bb403aSmacallan	} else
35098bb403aSmacallan	    return FALSE;
35198bb403aSmacallan    }
35298bb403aSmacallan
35398bb403aSmacallan    /*********************
35498bb403aSmacallan    deal with depth
35598bb403aSmacallan    *********************/
35698bb403aSmacallan
35798bb403aSmacallan    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
35898bb403aSmacallan	return FALSE;
35998bb403aSmacallan    } else {
36098bb403aSmacallan	/* Check that the returned depth is one we support */
36198bb403aSmacallan	switch (pScrn->depth) {
36298bb403aSmacallan	case 24:
36398bb403aSmacallan	    /* OK */
36498bb403aSmacallan	    break;
36598bb403aSmacallan	default:
36698bb403aSmacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
36798bb403aSmacallan		       "Given depth (%d) is not supported by this driver\n",
36898bb403aSmacallan		       pScrn->depth);
36998bb403aSmacallan	    return FALSE;
37098bb403aSmacallan	}
37198bb403aSmacallan    }
37298bb403aSmacallan
37398bb403aSmacallan    /* Collect all of the relevant option flags (fill in pScrn->options) */
37498bb403aSmacallan    xf86CollectOptions(pScrn, NULL);
37598bb403aSmacallan    /* Process the options */
37698bb403aSmacallan    if (!(pAG10E->Options = xalloc(sizeof(AG10EOptions))))
37798bb403aSmacallan	return FALSE;
37898bb403aSmacallan    memcpy(pAG10E->Options, AG10EOptions, sizeof(AG10EOptions));
37998bb403aSmacallan    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pAG10E->Options);
38098bb403aSmacallan
38198bb403aSmacallan    /*
38298bb403aSmacallan     * The new cmap code requires this to be initialised.
38398bb403aSmacallan     * this card supports HW gamma correction with 10 bit resolution - maybe
38498bb403aSmacallan     * we should figure out how to use it
38598bb403aSmacallan     */
38698bb403aSmacallan
38798bb403aSmacallan    {
38898bb403aSmacallan	Gamma zeros = {0.0, 0.0, 0.0};
38998bb403aSmacallan
39098bb403aSmacallan	if (!xf86SetGamma(pScrn, zeros)) {
39198bb403aSmacallan	    return FALSE;
39298bb403aSmacallan	}
39398bb403aSmacallan    }
39498bb403aSmacallan
39598bb403aSmacallan    from = X_DEFAULT;
39698bb403aSmacallan    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
39798bb403aSmacallan      return FALSE;
39898bb403aSmacallan
39998bb403aSmacallan    if (!xf86SetDefaultVisual(pScrn, -1))
40098bb403aSmacallan	return FALSE;
40198bb403aSmacallan
40298bb403aSmacallan    /* determine whether we use hardware or software cursor */
40398bb403aSmacallan
40498bb403aSmacallan    pAG10E->HWCursor = TRUE;
40598bb403aSmacallan    if (xf86GetOptValBool(pAG10E->Options, OPTION_HW_CURSOR, &pAG10E->HWCursor))
40698bb403aSmacallan	from = X_CONFIG;
40798bb403aSmacallan    if (xf86ReturnOptValBool(pAG10E->Options, OPTION_SW_CURSOR, FALSE)) {
40898bb403aSmacallan	from = X_CONFIG;
40998bb403aSmacallan	pAG10E->HWCursor = FALSE;
41098bb403aSmacallan    }
41198bb403aSmacallan
41298bb403aSmacallan    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
41398bb403aSmacallan		pAG10E->HWCursor ? "HW" : "SW");
41498bb403aSmacallan
41598bb403aSmacallan    if (xf86ReturnOptValBool(pAG10E->Options, OPTION_NOACCEL, FALSE)) {
41698bb403aSmacallan	pAG10E->NoAccel = TRUE;
41798bb403aSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
41898bb403aSmacallan    }
41998bb403aSmacallan
42098bb403aSmacallan    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
42198bb403aSmacallan	AG10EFreeRec(pScrn);
42298bb403aSmacallan	return FALSE;
42398bb403aSmacallan    }
42498bb403aSmacallan
42598bb403aSmacallan    if (pAG10E->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) {
42698bb403aSmacallan	AG10EFreeRec(pScrn);
42798bb403aSmacallan	return FALSE;
42898bb403aSmacallan    }
42998bb403aSmacallan
43098bb403aSmacallan    if (pAG10E->HWCursor && xf86LoadSubModule(pScrn, "xaa") == NULL) {
43198bb403aSmacallan	AG10EFreeRec(pScrn);
43298bb403aSmacallan	return FALSE;
43398bb403aSmacallan    }
43498bb403aSmacallan    xf86LoaderReqSymLists(xaaSymbols, NULL);
43598bb403aSmacallan
43698bb403aSmacallan    /*********************
43798bb403aSmacallan    set up clock and mode stuff
43898bb403aSmacallan    *********************/
43998bb403aSmacallan
44098bb403aSmacallan    pScrn->progClock = TRUE;
44198bb403aSmacallan
44298bb403aSmacallan    if(pScrn->display->virtualX || pScrn->display->virtualY) {
44398bb403aSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
44498bb403aSmacallan		   "AG10E does not support a virtual desktop\n");
44598bb403aSmacallan	pScrn->display->virtualX = 0;
44698bb403aSmacallan	pScrn->display->virtualY = 0;
44798bb403aSmacallan    }
44898bb403aSmacallan
44998bb403aSmacallan    xf86SbusUseBuiltinMode(pScrn, pAG10E->psdp);
45098bb403aSmacallan    pScrn->currentMode = pScrn->modes;
45198bb403aSmacallan    pScrn->displayWidth = pScrn->virtualX;
45298bb403aSmacallan
45398bb403aSmacallan    /* Set display resolution */
45498bb403aSmacallan    xf86SetDpi(pScrn, 0, 0);
45598bb403aSmacallan
45698bb403aSmacallan    return TRUE;
45798bb403aSmacallan}
45898bb403aSmacallan
45998bb403aSmacallan/* Mandatory */
46098bb403aSmacallan
46198bb403aSmacallan/* This gets called at the start of each server generation */
46298bb403aSmacallan
46398bb403aSmacallanstatic Bool
46498bb403aSmacallanAG10EScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
46598bb403aSmacallan{
46698bb403aSmacallan    ScrnInfoPtr pScrn;
46798bb403aSmacallan    AG10EPtr pAG10E;
46898bb403aSmacallan    struct fbtype fb;
46998bb403aSmacallan    sbusDevicePtr psdp;
47098bb403aSmacallan    VisualPtr visual;
47198bb403aSmacallan    int ret;
47298bb403aSmacallan
47398bb403aSmacallan    pScrn = xf86Screens[pScreen->myNum];
47498bb403aSmacallan    pAG10E = GET_AG10E_FROM_SCRN(pScrn);
47598bb403aSmacallan    psdp = pAG10E->psdp;
47698bb403aSmacallan
47798bb403aSmacallan    /*
47898bb403aSmacallan     * for some idiotic reason we need to check if the file descriptor is
47998bb403aSmacallan     * really open here
48098bb403aSmacallan     */
48198bb403aSmacallan    if (psdp->fd == -1) {
48298bb403aSmacallan	psdp->fd = open(psdp->device, O_RDWR);
48398bb403aSmacallan	if (psdp->fd == -1)
48498bb403aSmacallan	    return FALSE;
48598bb403aSmacallan    }
48698bb403aSmacallan
48798bb403aSmacallan    /* figure out how much VRAM we can map */
48898bb403aSmacallan    if ((ret = ioctl(pAG10E->psdp->fd, FBIOGTYPE, &fb)) != 0) {
48998bb403aSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
49098bb403aSmacallan	    "ioctl(FBIOGTYPE) failed with %d\n", ret);
49198bb403aSmacallan	return FALSE;
49298bb403aSmacallan    }
49398bb403aSmacallan    pAG10E->vidmem = fb.fb_size;
49498bb403aSmacallan
49598bb403aSmacallan    /* Map AG10E memory areas */
49698bb403aSmacallan
49798bb403aSmacallan    pAG10E->regs = xf86MapSbusMem(psdp, pAG10E->vidmem, 0x10000);
49898bb403aSmacallan    pAG10E->fb = xf86MapSbusMem(psdp, 0, pAG10E->vidmem);
49998bb403aSmacallan
50098bb403aSmacallan    if (pAG10E->fb != NULL) {
50198bb403aSmacallan        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mapped %d KB video RAM\n",
50298bb403aSmacallan	    pAG10E->vidmem >> 10);
50398bb403aSmacallan    }
50498bb403aSmacallan
50598bb403aSmacallan    if (!pAG10E->regs || !pAG10E->fb) {
50698bb403aSmacallan    	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
50798bb403aSmacallan		   "xf86MapSbusMem failed regs:%" PRIxPTR " fb:%" PRIxPTR "\n",
50898bb403aSmacallan		   pAG10E->regs, pAG10E->fb);
50998bb403aSmacallan
51098bb403aSmacallan	if (pAG10E->fb) {
51198bb403aSmacallan	    xf86UnmapSbusMem(psdp, pAG10E->fb, sizeof(*pAG10E->fb));
51298bb403aSmacallan	    pAG10E->fb = NULL;
51398bb403aSmacallan	}
51498bb403aSmacallan
51598bb403aSmacallan	if (pAG10E->regs) {
51698bb403aSmacallan	    xf86UnmapSbusMem(psdp, pAG10E->regs, sizeof(*pAG10E->regs));
51798bb403aSmacallan	    pAG10E->regs = NULL;
51898bb403aSmacallan	}
51998bb403aSmacallan
52098bb403aSmacallan	return FALSE;
52198bb403aSmacallan    }
52298bb403aSmacallan    pAG10E->IOOffset = 0;
52398bb403aSmacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "vram: %d\n",
52498bb403aSmacallan        (1 << ((GLINT_READ_REG(FBMemoryCtl) & 0xE0000000)>>29)) * 1024);
52598bb403aSmacallan
52698bb403aSmacallan    /*
52798bb403aSmacallan     * The next step is to setup the screen's visuals, and initialise the
52898bb403aSmacallan     * framebuffer code.  In cases where the framebuffer's default
52998bb403aSmacallan     * choices for things like visual layouts and bits per RGB are OK,
53098bb403aSmacallan     * this may be as simple as calling the framebuffer's ScreenInit()
53198bb403aSmacallan     * function.  If not, the visuals will need to be setup before calling
53298bb403aSmacallan     * a fb ScreenInit() function and fixed up after.
53398bb403aSmacallan     */
53498bb403aSmacallan
53598bb403aSmacallan    /*
53698bb403aSmacallan     * Reset visual list.
53798bb403aSmacallan     */
53898bb403aSmacallan    miClearVisualTypes();
53998bb403aSmacallan
54098bb403aSmacallan    /* Setup the visuals we support. */
54198bb403aSmacallan    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
54298bb403aSmacallan			  pScrn->rgbBits, pScrn->defaultVisual))
54398bb403aSmacallan	return FALSE;
54498bb403aSmacallan
54598bb403aSmacallan    miSetPixmapDepths();
54698bb403aSmacallan
54798bb403aSmacallan    /*
54898bb403aSmacallan     * Call the framebuffer layer's ScreenInit function, and fill in other
54998bb403aSmacallan     * pScreen fields.
55098bb403aSmacallan     */
55198bb403aSmacallan
55298bb403aSmacallan    ret = fbScreenInit(pScreen, pAG10E->fb, pScrn->virtualX,
55398bb403aSmacallan		       pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
55498bb403aSmacallan		       pScrn->virtualX, pScrn->bitsPerPixel);
55598bb403aSmacallan    /*if (!ret)
55698bb403aSmacallan	return FALSE;*/
55798bb403aSmacallan
558df1b2e9dSmacallan    pAG10E->width = pScrn->virtualX;
559df1b2e9dSmacallan    pAG10E->height = pScrn->virtualY;
560df1b2e9dSmacallan    pAG10E->maxheight = (pAG10E->vidmem / (pAG10E->width << 2)) & 0xffff;
56198bb403aSmacallan
56298bb403aSmacallan    fbPictureInit(pScreen, 0, 0);
56398bb403aSmacallan
56498bb403aSmacallan    visual = pScreen->visuals + pScreen->numVisuals;
56598bb403aSmacallan    while (--visual >= pScreen->visuals) {
56698bb403aSmacallan      if ((visual->class | DynamicClass) == DirectColor) {
56798bb403aSmacallan        visual->offsetRed = pScrn->offset.red;
56898bb403aSmacallan	visual->offsetGreen = pScrn->offset.green;
56998bb403aSmacallan	visual->offsetBlue = pScrn->offset.blue;
57098bb403aSmacallan	visual->redMask = pScrn->mask.red;
57198bb403aSmacallan	visual->greenMask = pScrn->mask.green;
57298bb403aSmacallan	visual->blueMask = pScrn->mask.blue;
57398bb403aSmacallan      }
57498bb403aSmacallan    }
57598bb403aSmacallan
57698bb403aSmacallan    xf86SetBackingStore(pScreen);
57798bb403aSmacallan    xf86SetSilkenMouse(pScreen);
57898bb403aSmacallan
57998bb403aSmacallan    xf86SetBlackWhitePixels(pScreen);
58098bb403aSmacallan
58198bb403aSmacallan    if (!pAG10E->NoAccel) {
58298bb403aSmacallan	if (!AG10EAccelInit(pScreen))
58398bb403aSmacallan		return FALSE;
58498bb403aSmacallan	xf86Msg(X_INFO, "%s: Using acceleration\n", pAG10E->psdp->device);
58598bb403aSmacallan    }
58698bb403aSmacallan    /* setup DGA */
58798bb403aSmacallan    AG10EDGAInit(pScreen);
58898bb403aSmacallan
58998bb403aSmacallan    /* Initialise cursor functions */
59098bb403aSmacallan    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
59198bb403aSmacallan
59298bb403aSmacallan    /* Initialize HW cursor layer.
59398bb403aSmacallan       Must follow software cursor initialization*/
59498bb403aSmacallan    if (pAG10E->HWCursor) {
59598bb403aSmacallan	if(!AG10EHWCursorInit(pScreen)) {
59698bb403aSmacallan	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
59798bb403aSmacallan		       "Hardware cursor initialization failed\n");
59898bb403aSmacallan	    return(FALSE);
59998bb403aSmacallan	}
60098bb403aSmacallan	xf86SbusHideOsHwCursor(psdp);
60198bb403aSmacallan    }
60298bb403aSmacallan
60398bb403aSmacallan    /* Initialise default colourmap */
60498bb403aSmacallan    if (!miCreateDefColormap(pScreen))
60598bb403aSmacallan	return FALSE;
60698bb403aSmacallan
60798bb403aSmacallan    if(!xf86SbusHandleColormaps(pScreen, psdp))
60898bb403aSmacallan	return FALSE;
60998bb403aSmacallan
61098bb403aSmacallan    pAG10E->CloseScreen = pScreen->CloseScreen;
61198bb403aSmacallan    pScreen->CloseScreen = AG10ECloseScreen;
61298bb403aSmacallan    pScreen->SaveScreen = AG10ESaveScreen;
61398bb403aSmacallan
61498bb403aSmacallan    /* Report any unused options (only for the first generation) */
61598bb403aSmacallan    if (serverGeneration == 1) {
61698bb403aSmacallan	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
61798bb403aSmacallan    }
61898bb403aSmacallan
61998bb403aSmacallan    /* unblank the screen */
62098bb403aSmacallan    AG10ESaveScreen(pScreen, SCREEN_SAVER_OFF);
62198bb403aSmacallan
62298bb403aSmacallan    /* Done */
62398bb403aSmacallan    return TRUE;
62498bb403aSmacallan}
62598bb403aSmacallan
62698bb403aSmacallan
62798bb403aSmacallan/* Usually mandatory */
62898bb403aSmacallanstatic Bool
62998bb403aSmacallanAG10ESwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
63098bb403aSmacallan{
63198bb403aSmacallan    return TRUE;
63298bb403aSmacallan}
63398bb403aSmacallan
63498bb403aSmacallan
63598bb403aSmacallan/*
63698bb403aSmacallan * This function is used to initialize the Start Address - the first
63798bb403aSmacallan * displayed location in the video memory.
63898bb403aSmacallan */
63998bb403aSmacallan/* Usually mandatory */
64098bb403aSmacallanstatic void
64198bb403aSmacallanAG10EAdjustFrame(int scrnIndex, int x, int y, int flags)
64298bb403aSmacallan{
64398bb403aSmacallan    /* we don't support virtual desktops */
64498bb403aSmacallan    return;
64598bb403aSmacallan}
64698bb403aSmacallan
64798bb403aSmacallan/*
64898bb403aSmacallan * This is called when VT switching back to the X server.  Its job is
64998bb403aSmacallan * to reinitialise the video mode.
65098bb403aSmacallan */
65198bb403aSmacallan
65298bb403aSmacallan/* Mandatory */
65398bb403aSmacallanstatic Bool
65498bb403aSmacallanAG10EEnterVT(int scrnIndex, int flags)
65598bb403aSmacallan{
65698bb403aSmacallan    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
65798bb403aSmacallan    AG10EPtr pAG10E = GET_AG10E_FROM_SCRN(pScrn);
65898bb403aSmacallan
65998bb403aSmacallan    if (pAG10E->HWCursor) {
66098bb403aSmacallan	xf86SbusHideOsHwCursor(pAG10E->psdp);
66198bb403aSmacallan    }
66298bb403aSmacallan    return TRUE;
66398bb403aSmacallan}
66498bb403aSmacallan
66598bb403aSmacallan
66698bb403aSmacallan/*
66798bb403aSmacallan * This is called when VT switching away from the X server.
66898bb403aSmacallan */
66998bb403aSmacallan
67098bb403aSmacallan/* Mandatory */
67198bb403aSmacallanstatic void
67298bb403aSmacallanAG10ELeaveVT(int scrnIndex, int flags)
67398bb403aSmacallan{
67498bb403aSmacallan    return;
67598bb403aSmacallan}
67698bb403aSmacallan
67798bb403aSmacallan
67898bb403aSmacallan/*
67998bb403aSmacallan * This is called at the end of each server generation.  It restores the
68098bb403aSmacallan * original (text) mode.  It should really also unmap the video memory too.
68198bb403aSmacallan */
68298bb403aSmacallan
68398bb403aSmacallan/* Mandatory */
68498bb403aSmacallanstatic Bool
68598bb403aSmacallanAG10ECloseScreen(int scrnIndex, ScreenPtr pScreen)
68698bb403aSmacallan{
68798bb403aSmacallan    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
68898bb403aSmacallan    AG10EPtr pAG10E = GET_AG10E_FROM_SCRN(pScrn);
68998bb403aSmacallan    sbusDevicePtr psdp = pAG10E->psdp;
69098bb403aSmacallan
69198bb403aSmacallan    pScrn->vtSema = FALSE;
69298bb403aSmacallan
69398bb403aSmacallan    xf86UnmapSbusMem(psdp, pAG10E->regs, 0x10000);
69498bb403aSmacallan    xf86UnmapSbusMem(psdp, pAG10E->fb, pAG10E->vidmem);
69598bb403aSmacallan
69698bb403aSmacallan    if (pAG10E->HWCursor)
69798bb403aSmacallan	xf86SbusHideOsHwCursor(psdp);
69898bb403aSmacallan
69998bb403aSmacallan    pScreen->CloseScreen = pAG10E->CloseScreen;
70098bb403aSmacallan    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
70198bb403aSmacallan    return FALSE;
70298bb403aSmacallan}
70398bb403aSmacallan
70498bb403aSmacallan
70598bb403aSmacallan/* Free up any per-generation data structures */
70698bb403aSmacallan
70798bb403aSmacallan/* Optional */
70898bb403aSmacallanstatic void
70998bb403aSmacallanAG10EFreeScreen(int scrnIndex, int flags)
71098bb403aSmacallan{
71198bb403aSmacallan    AG10EFreeRec(xf86Screens[scrnIndex]);
71298bb403aSmacallan}
71398bb403aSmacallan
71498bb403aSmacallan
71598bb403aSmacallan/* Checks if a mode is suitable for the selected chipset. */
71698bb403aSmacallan
71798bb403aSmacallan/* Optional */
71898bb403aSmacallanstatic ModeStatus
71998bb403aSmacallanAG10EValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
72098bb403aSmacallan{
72198bb403aSmacallan    if (mode->Flags & V_INTERLACE)
72298bb403aSmacallan	return(MODE_NO_INTERLACE);
72398bb403aSmacallan
72498bb403aSmacallan    return(MODE_OK);
72598bb403aSmacallan}
72698bb403aSmacallan
72798bb403aSmacallan/* Do screen blanking */
72898bb403aSmacallan
72998bb403aSmacallan/* Mandatory */
73098bb403aSmacallanstatic Bool
73198bb403aSmacallanAG10ESaveScreen(ScreenPtr pScreen, int mode)
73298bb403aSmacallan{
73398bb403aSmacallan    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
73498bb403aSmacallan    AG10EPtr pAG10E = GET_AG10E_FROM_SCRN(pScrn);
73598bb403aSmacallan    int flag;
73698bb403aSmacallan
73798bb403aSmacallan    switch (mode)
73898bb403aSmacallan    {
73998bb403aSmacallan	case SCREEN_SAVER_ON:
74098bb403aSmacallan	case SCREEN_SAVER_CYCLE:
74198bb403aSmacallan	    flag = 0;
74298bb403aSmacallan	    ioctl(pAG10E->psdp->fd, FBIOSVIDEO, &flag);
74398bb403aSmacallan	    break;
74498bb403aSmacallan	case SCREEN_SAVER_OFF:
74598bb403aSmacallan	case SCREEN_SAVER_FORCER:
74698bb403aSmacallan	    flag = 1;
74798bb403aSmacallan	    ioctl(pAG10E->psdp->fd, FBIOSVIDEO, &flag);
74898bb403aSmacallan	    break;
74998bb403aSmacallan	default:
75098bb403aSmacallan	    return FALSE;
75198bb403aSmacallan    }
75298bb403aSmacallan
75398bb403aSmacallan    return TRUE;
75498bb403aSmacallan}
755