ngle_driver.c revision 7517da51
17517da51Smacallan/* $NetBSD: ngle_driver.c,v 1.7 2024/12/07 10:48:38 macallan Exp $ */
2a7fd8e5eSmacallan/*
3a7fd8e5eSmacallan * Copyright (c) 2024 Michael Lorenz
4a7fd8e5eSmacallan * All rights reserved.
5a7fd8e5eSmacallan *
6a7fd8e5eSmacallan * Redistribution and use in source and binary forms, with or without
7a7fd8e5eSmacallan * modification, are permitted provided that the following conditions
8a7fd8e5eSmacallan * are met:
9a7fd8e5eSmacallan *
10a7fd8e5eSmacallan *    - Redistributions of source code must retain the above copyright
11a7fd8e5eSmacallan *      notice, this list of conditions and the following disclaimer.
12a7fd8e5eSmacallan *    - Redistributions in binary form must reproduce the above
13a7fd8e5eSmacallan *      copyright notice, this list of conditions and the following
14a7fd8e5eSmacallan *      disclaimer in the documentation and/or other materials provided
15a7fd8e5eSmacallan *      with the distribution.
16a7fd8e5eSmacallan *
17a7fd8e5eSmacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18a7fd8e5eSmacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19a7fd8e5eSmacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20a7fd8e5eSmacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21a7fd8e5eSmacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22a7fd8e5eSmacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23a7fd8e5eSmacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24a7fd8e5eSmacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25a7fd8e5eSmacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26a7fd8e5eSmacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27a7fd8e5eSmacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28a7fd8e5eSmacallan * POSSIBILITY OF SUCH DAMAGE.
29a7fd8e5eSmacallan *
30a7fd8e5eSmacallan */
31a7fd8e5eSmacallan
32a7fd8e5eSmacallan/* a driver for HP's NGLE family of graphics chips */
33a7fd8e5eSmacallan
34a7fd8e5eSmacallan#ifdef HAVE_CONFIG_H
35a7fd8e5eSmacallan#include "config.h"
36a7fd8e5eSmacallan#endif
37a7fd8e5eSmacallan#include <sys/types.h>
38a7fd8e5eSmacallan#include <dev/ic/stireg.h>
39a7fd8e5eSmacallan
40a7fd8e5eSmacallan#include <fcntl.h>
41a7fd8e5eSmacallan#include <errno.h>
42a7fd8e5eSmacallan#include <sys/time.h>
43a7fd8e5eSmacallan#include <sys/mman.h>
44a7fd8e5eSmacallan#include <sys/ioctl.h>
45a7fd8e5eSmacallan#include <dev/wscons/wsconsio.h>
46a7fd8e5eSmacallan
47a7fd8e5eSmacallan/* all driver need this */
48a7fd8e5eSmacallan#include "xf86.h"
49a7fd8e5eSmacallan#include "xf86_OSproc.h"
50a7fd8e5eSmacallan
51a7fd8e5eSmacallan#include "mipointer.h"
52a7fd8e5eSmacallan#include "micmap.h"
53a7fd8e5eSmacallan#include "colormapst.h"
54a7fd8e5eSmacallan#include "xf86cmap.h"
55a7fd8e5eSmacallan#ifdef XvExtension
56a7fd8e5eSmacallan#include "xf86xv.h"
57a7fd8e5eSmacallan#endif
58a7fd8e5eSmacallan
59a7fd8e5eSmacallan/* for visuals */
60a7fd8e5eSmacallan#include "fb.h"
61a7fd8e5eSmacallan
62a7fd8e5eSmacallan#include "ngle.h"
63a7fd8e5eSmacallan
64a7fd8e5eSmacallan/* #include "wsconsio.h" */
65a7fd8e5eSmacallan
66a7fd8e5eSmacallan#define NGLE_DEFAULT_DEV "/dev/ttyE0"
67a7fd8e5eSmacallan
68a7fd8e5eSmacallanstatic pointer NGLESetup(pointer, pointer, int *, int *);
69a7fd8e5eSmacallanstatic Bool NGLEGetRec(ScrnInfoPtr);
70a7fd8e5eSmacallanstatic void NGLEFreeRec(ScrnInfoPtr);
71a7fd8e5eSmacallanstatic const OptionInfoRec * NGLEAvailableOptions(int, int);
72a7fd8e5eSmacallanstatic void NGLEIdentify(int);
73a7fd8e5eSmacallanstatic Bool NGLEProbe(DriverPtr, int);
74a7fd8e5eSmacallanstatic Bool NGLEPreInit(ScrnInfoPtr, int);
75a7fd8e5eSmacallanstatic Bool NGLEScreenInit(SCREEN_INIT_ARGS_DECL);
76a7fd8e5eSmacallanstatic Bool NGLECloseScreen(CLOSE_SCREEN_ARGS_DECL);
77a7fd8e5eSmacallanstatic Bool NGLEEnterVT(VT_FUNC_ARGS_DECL);
78a7fd8e5eSmacallanstatic void NGLELeaveVT(VT_FUNC_ARGS_DECL);
79a7fd8e5eSmacallanstatic Bool NGLESwitchMode(SWITCH_MODE_ARGS_DECL);
80a7fd8e5eSmacallanstatic int NGLEValidMode(SCRN_ARG_TYPE, DisplayModePtr, Bool, int);
81a7fd8e5eSmacallanstatic void NGLELoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
82a7fd8e5eSmacallanstatic Bool NGLESaveScreen(ScreenPtr, int);
83a7fd8e5eSmacallanstatic void NGLESave(ScrnInfoPtr);
84a7fd8e5eSmacallanstatic void NGLERestore(ScrnInfoPtr);
85a7fd8e5eSmacallan
86a7fd8e5eSmacallan/* helper functions */
87a7fd8e5eSmacallanstatic int ngle_open(const char *);
88a7fd8e5eSmacallanstatic pointer ngle_mmap(size_t, off_t, int, int);
89a7fd8e5eSmacallan
90a7fd8e5eSmacallan#define VERSION			4000
91a7fd8e5eSmacallan#define NGLE_NAME		"ngle"
92a7fd8e5eSmacallan#define NGLE_DRIVER_NAME	"ngle"
93a7fd8e5eSmacallan#define NGLE_MAJOR_VERSION	0
94a7fd8e5eSmacallan#define NGLE_MINOR_VERSION	1
95a7fd8e5eSmacallan
96a7fd8e5eSmacallanDriverRec NGLE = {
97a7fd8e5eSmacallan	VERSION,
98a7fd8e5eSmacallan	NGLE_DRIVER_NAME,
99a7fd8e5eSmacallan	NGLEIdentify,
100a7fd8e5eSmacallan	NGLEProbe,
101a7fd8e5eSmacallan	NGLEAvailableOptions,
102a7fd8e5eSmacallan	NULL,
103a7fd8e5eSmacallan	0
104a7fd8e5eSmacallan};
105a7fd8e5eSmacallan
106a7fd8e5eSmacallan/* Supported "chipsets" */
107a7fd8e5eSmacallanstatic SymTabRec NGLEChipsets[] = {
108a7fd8e5eSmacallan	{ STI_DD_EG, "Visualize EG" },
109a7fd8e5eSmacallan	{ STI_DD_HCRX, "HCRX" },
1107517da51Smacallan	{ STI_DD_SUMMIT, "Visualize FX 2/4/6"},
111a7fd8e5eSmacallan	{ -1, NULL }
112a7fd8e5eSmacallan};
113a7fd8e5eSmacallan
114a7fd8e5eSmacallan/* Supported options */
115a7fd8e5eSmacallantypedef enum {
116a7fd8e5eSmacallan	OPTION_HW_CURSOR,
1177517da51Smacallan	OPTION_DEVICE
118a7fd8e5eSmacallan} NGLEOpts;
119a7fd8e5eSmacallan
120a7fd8e5eSmacallanstatic const OptionInfoRec NGLEOptions[] = {
121a7fd8e5eSmacallan	{ OPTION_HW_CURSOR, "HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
1227517da51Smacallan	{ OPTION_DEVICE,    "Device",   OPTV_ANYSTR,    {0}, FALSE },
123a7fd8e5eSmacallan	{ -1, NULL, OPTV_NONE, {0}, FALSE}
124a7fd8e5eSmacallan};
125a7fd8e5eSmacallan
126a7fd8e5eSmacallanstatic XF86ModuleVersionInfo NGLEVersRec = {
127a7fd8e5eSmacallan	"ngle",
128a7fd8e5eSmacallan	"The NetBSD Foundation",
129a7fd8e5eSmacallan	MODINFOSTRING1,
130a7fd8e5eSmacallan	MODINFOSTRING2,
131a7fd8e5eSmacallan	XORG_VERSION_CURRENT,
132a7fd8e5eSmacallan	NGLE_MAJOR_VERSION, NGLE_MINOR_VERSION, 0,
133a7fd8e5eSmacallan	ABI_CLASS_VIDEODRV,
134a7fd8e5eSmacallan	ABI_VIDEODRV_VERSION,
135a7fd8e5eSmacallan	NULL,
136a7fd8e5eSmacallan	{0, 0, 0, 0}
137a7fd8e5eSmacallan};
138a7fd8e5eSmacallan
139a7fd8e5eSmacallan_X_EXPORT XF86ModuleData ngleModuleData = { &NGLEVersRec, NGLESetup, NULL };
140a7fd8e5eSmacallan
141a7fd8e5eSmacallanstatic pointer
142a7fd8e5eSmacallanNGLESetup(pointer module, pointer opts, int *errmaj, int *errmin)
143a7fd8e5eSmacallan{
144a7fd8e5eSmacallan	static Bool setupDone = FALSE;
145a7fd8e5eSmacallan	const char *osname;
146a7fd8e5eSmacallan
147a7fd8e5eSmacallan	if (!setupDone) {
148a7fd8e5eSmacallan		setupDone = TRUE;
149a7fd8e5eSmacallan		xf86AddDriver(&NGLE, module, 0);
150a7fd8e5eSmacallan		return (pointer)1;
151a7fd8e5eSmacallan	} else {
152a7fd8e5eSmacallan		if (errmaj != NULL)
153a7fd8e5eSmacallan			*errmaj = LDR_ONCEONLY;
154a7fd8e5eSmacallan		return NULL;
155a7fd8e5eSmacallan	}
156a7fd8e5eSmacallan}
157a7fd8e5eSmacallan
158a7fd8e5eSmacallanstatic Bool
159a7fd8e5eSmacallanNGLEGetRec(ScrnInfoPtr pScrn)
160a7fd8e5eSmacallan{
161a7fd8e5eSmacallan
162a7fd8e5eSmacallan	if (pScrn->driverPrivate != NULL)
163a7fd8e5eSmacallan		return TRUE;
164a7fd8e5eSmacallan
165a7fd8e5eSmacallan	pScrn->driverPrivate = xnfcalloc(sizeof(NGLERec), 1);
166a7fd8e5eSmacallan	return TRUE;
167a7fd8e5eSmacallan}
168a7fd8e5eSmacallan
169a7fd8e5eSmacallanstatic void
170a7fd8e5eSmacallanNGLEFreeRec(ScrnInfoPtr pScrn)
171a7fd8e5eSmacallan{
172a7fd8e5eSmacallan
173a7fd8e5eSmacallan	if (pScrn->driverPrivate == NULL)
174a7fd8e5eSmacallan		return;
175a7fd8e5eSmacallan	free(pScrn->driverPrivate);
176a7fd8e5eSmacallan	pScrn->driverPrivate = NULL;
177a7fd8e5eSmacallan}
178a7fd8e5eSmacallan
179a7fd8e5eSmacallanstatic const OptionInfoRec *
180a7fd8e5eSmacallanNGLEAvailableOptions(int chipid, int busid)
181a7fd8e5eSmacallan{
182a7fd8e5eSmacallan	return NGLEOptions;
183a7fd8e5eSmacallan}
184a7fd8e5eSmacallan
185a7fd8e5eSmacallanstatic void
186a7fd8e5eSmacallanNGLEIdentify(int flags)
187a7fd8e5eSmacallan{
188a7fd8e5eSmacallan	xf86PrintChipsets(NGLE_NAME, "driver for NGLE framebuffers",
189a7fd8e5eSmacallan			  NGLEChipsets);
190a7fd8e5eSmacallan}
191a7fd8e5eSmacallan
192a7fd8e5eSmacallan
193a7fd8e5eSmacallan#define priv_open_device(n)	open(n,O_RDWR|O_NONBLOCK|O_EXCL)
194a7fd8e5eSmacallan
195a7fd8e5eSmacallan/* Open the framebuffer device */
196a7fd8e5eSmacallanstatic int
197a7fd8e5eSmacallanngle_open(const char *dev)
198a7fd8e5eSmacallan{
199a7fd8e5eSmacallan	int fd = -1;
200a7fd8e5eSmacallan
201a7fd8e5eSmacallan	/* try argument from XF86Config first */
202a7fd8e5eSmacallan	if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
203a7fd8e5eSmacallan		/* second: environment variable */
204a7fd8e5eSmacallan		dev = getenv("XDEVICE");
205a7fd8e5eSmacallan		if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
206a7fd8e5eSmacallan			/* last try: default device */
207a7fd8e5eSmacallan			dev = NGLE_DEFAULT_DEV;
208a7fd8e5eSmacallan			if ((fd = priv_open_device(dev)) == -1) {
209a7fd8e5eSmacallan				return -1;
210a7fd8e5eSmacallan			}
211a7fd8e5eSmacallan		}
212a7fd8e5eSmacallan	}
213a7fd8e5eSmacallan	return fd;
214a7fd8e5eSmacallan}
215a7fd8e5eSmacallan
216a7fd8e5eSmacallan/* Map the framebuffer's memory */
217a7fd8e5eSmacallanstatic pointer
218a7fd8e5eSmacallanngle_mmap(size_t len, off_t off, int fd, int ro)
219a7fd8e5eSmacallan{
220a7fd8e5eSmacallan	pointer mapaddr;
221a7fd8e5eSmacallan
222a7fd8e5eSmacallan	/*
223a7fd8e5eSmacallan	 * try and make it private first, that way once we get it, an
224a7fd8e5eSmacallan	 * interloper, e.g. another server, can't get this frame buffer,
225a7fd8e5eSmacallan	 * and if another server already has it, this one won't.
226a7fd8e5eSmacallan	 */
227a7fd8e5eSmacallan	if (ro) {
228a7fd8e5eSmacallan		mapaddr = (pointer) mmap(NULL, len,
229a7fd8e5eSmacallan					 PROT_READ, MAP_SHARED,
230a7fd8e5eSmacallan					 fd, off);
231a7fd8e5eSmacallan		xf86Msg(X_ERROR, "mapping %08x read only\n", off);
232a7fd8e5eSmacallan	} else {
233a7fd8e5eSmacallan		mapaddr = (pointer) mmap(NULL, len,
234a7fd8e5eSmacallan					 PROT_READ | PROT_WRITE, MAP_SHARED,
235a7fd8e5eSmacallan					 fd, off);
236a7fd8e5eSmacallan		xf86Msg(X_ERROR, "mapping %08x read/write\n", off);
237a7fd8e5eSmacallan	}
238a7fd8e5eSmacallan	if (mapaddr == (pointer) -1) {
239a7fd8e5eSmacallan		mapaddr = NULL;
240a7fd8e5eSmacallan	}
241a7fd8e5eSmacallan#ifdef NGLE_DEBUG
242a7fd8e5eSmacallan	ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, len);
243a7fd8e5eSmacallan#endif
244a7fd8e5eSmacallan	return mapaddr;
245a7fd8e5eSmacallan}
246a7fd8e5eSmacallan
247a7fd8e5eSmacallanstatic Bool
248a7fd8e5eSmacallanNGLEProbe(DriverPtr drv, int flags)
249a7fd8e5eSmacallan{
250a7fd8e5eSmacallan	ScrnInfoPtr pScrn = NULL;
251a7fd8e5eSmacallan	int i, fd, entity, wstype;
252a7fd8e5eSmacallan       	GDevPtr *devSections;
253a7fd8e5eSmacallan	int numDevSections;
254a7fd8e5eSmacallan	char *dev;
255a7fd8e5eSmacallan	const char *name;
256a7fd8e5eSmacallan	uint32_t gid;
257a7fd8e5eSmacallan	Bool foundScreen = FALSE;
258a7fd8e5eSmacallan
259a7fd8e5eSmacallan	if ((numDevSections = xf86MatchDevice(NGLE_DRIVER_NAME,
260a7fd8e5eSmacallan					      &devSections)) <= 0)
261a7fd8e5eSmacallan		return FALSE;
262a7fd8e5eSmacallan
263a7fd8e5eSmacallan
264a7fd8e5eSmacallan	if ((fd = ngle_open(NGLE_DEFAULT_DEV)) == 0)
265a7fd8e5eSmacallan		return FALSE;
266a7fd8e5eSmacallan
267a7fd8e5eSmacallan	if (ioctl(fd, WSDISPLAYIO_GTYPE, &wstype) == -1)
268a7fd8e5eSmacallan		return FALSE;
269a7fd8e5eSmacallan
270a7fd8e5eSmacallan	if (wstype != WSDISPLAY_TYPE_STI)
271a7fd8e5eSmacallan		return FALSE;
272a7fd8e5eSmacallan
273a7fd8e5eSmacallan	if (ioctl(fd, GCID, &gid) == -1)
274a7fd8e5eSmacallan		return FALSE;
275a7fd8e5eSmacallan
276a7fd8e5eSmacallan	/* reject GIDs not in the table */
277a7fd8e5eSmacallan	if ((name = xf86TokenToString(NGLEChipsets, gid)) == NULL)
278a7fd8e5eSmacallan		return FALSE;
279a7fd8e5eSmacallan
280a7fd8e5eSmacallan	xf86Msg(X_INFO, "%s: found %s ( GID %08x )\n", __func__, name, gid);
281a7fd8e5eSmacallan
282a7fd8e5eSmacallan	if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
283a7fd8e5eSmacallan		GDevPtr pGDev;
284a7fd8e5eSmacallan
285a7fd8e5eSmacallan		pGDev = xf86AddBusDeviceToConfigure(NGLE_DRIVER_NAME, BUS_NONE,
286a7fd8e5eSmacallan			NULL, 0);
287a7fd8e5eSmacallan		if (pGDev) {
288a7fd8e5eSmacallan			/*
289a7fd8e5eSmacallan			 * XF86Match???Instances() treat chipID and chipRev as
290a7fd8e5eSmacallan			 * overrides, so clobber them here.
291a7fd8e5eSmacallan			 */
292a7fd8e5eSmacallan			pGDev->chipID = pGDev->chipRev = -1;
293a7fd8e5eSmacallan	    	}
294a7fd8e5eSmacallan	}
295a7fd8e5eSmacallan
296a7fd8e5eSmacallan	if (flags & PROBE_DETECT) {
297a7fd8e5eSmacallan		return TRUE;
298a7fd8e5eSmacallan	}
299a7fd8e5eSmacallan
300a7fd8e5eSmacallan	if (numDevSections > 1) {
301a7fd8e5eSmacallan		xf86Msg(X_ERROR, "Ignoring additional device sections\n");
302a7fd8e5eSmacallan		numDevSections = 1;
303a7fd8e5eSmacallan	}
304a7fd8e5eSmacallan	/* ok, at this point we know we've got a NGLE */
305a7fd8e5eSmacallan	for (i = 0; i < numDevSections; i++) {
306a7fd8e5eSmacallan
307a7fd8e5eSmacallan		entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
308a7fd8e5eSmacallan		pScrn = xf86ConfigFbEntity(NULL, 0, entity,
309a7fd8e5eSmacallan		    NULL, NULL, NULL, NULL);
310a7fd8e5eSmacallan		if (pScrn != NULL) {
311a7fd8e5eSmacallan			foundScreen = TRUE;
312a7fd8e5eSmacallan			pScrn->driverVersion = VERSION;
313a7fd8e5eSmacallan			pScrn->driverName = NGLE_DRIVER_NAME;
314a7fd8e5eSmacallan			pScrn->name = NGLE_NAME;
315a7fd8e5eSmacallan			pScrn->Probe = NGLEProbe;
316a7fd8e5eSmacallan			pScrn->PreInit = NGLEPreInit;
317a7fd8e5eSmacallan			pScrn->ScreenInit = NGLEScreenInit;
318a7fd8e5eSmacallan			pScrn->SwitchMode = NGLESwitchMode;
319a7fd8e5eSmacallan			pScrn->AdjustFrame = NULL;
320a7fd8e5eSmacallan			pScrn->EnterVT = NGLEEnterVT;
321a7fd8e5eSmacallan			pScrn->LeaveVT = NGLELeaveVT;
322a7fd8e5eSmacallan			pScrn->ValidMode = NGLEValidMode;
323a7fd8e5eSmacallan
324a7fd8e5eSmacallan		}
325a7fd8e5eSmacallan	}
326a7fd8e5eSmacallan	free(devSections);
327a7fd8e5eSmacallan	return foundScreen;
328a7fd8e5eSmacallan}
329a7fd8e5eSmacallan
330a7fd8e5eSmacallanstatic Bool
331a7fd8e5eSmacallanNGLEPreInit(ScrnInfoPtr pScrn, int flags)
332a7fd8e5eSmacallan{
333a7fd8e5eSmacallan	NGLEPtr fPtr;
334727c6de2Smacallan	int default_depth, bitsperpixel, gid;
335a7fd8e5eSmacallan	const char *dev;
336a7fd8e5eSmacallan	char *mod = NULL;
337a7fd8e5eSmacallan	const char *reqSym = NULL;
338a7fd8e5eSmacallan	Gamma zeros = {0.0, 0.0, 0.0};
339a7fd8e5eSmacallan	DisplayModePtr mode;
340a7fd8e5eSmacallan	MessageType from;
341a7fd8e5eSmacallan	rgb rgbzeros = { 0, 0, 0 }, masks;
342a7fd8e5eSmacallan
343a7fd8e5eSmacallan	if (flags & PROBE_DETECT) return FALSE;
344a7fd8e5eSmacallan
345a7fd8e5eSmacallan	if (pScrn->numEntities != 1) return FALSE;
346a7fd8e5eSmacallan
347a7fd8e5eSmacallan	pScrn->monitor = pScrn->confScreen->monitor;
348a7fd8e5eSmacallan
349a7fd8e5eSmacallan	NGLEGetRec(pScrn);
350a7fd8e5eSmacallan	fPtr = NGLEPTR(pScrn);
351a7fd8e5eSmacallan
352a7fd8e5eSmacallan	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
353a7fd8e5eSmacallan
354a7fd8e5eSmacallan	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
355a7fd8e5eSmacallan	fPtr->fd = ngle_open(dev);
356a7fd8e5eSmacallan	if (fPtr->fd == -1) {
357a7fd8e5eSmacallan		return FALSE;
358a7fd8e5eSmacallan	}
359a7fd8e5eSmacallan
360a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_GET_FBINFO, &fPtr->fbi) == -1) {
361a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
362a7fd8e5eSmacallan			   "ioctl WSDISPLAY_GINFO: %s\n",
363a7fd8e5eSmacallan			   strerror(errno));
364a7fd8e5eSmacallan		return FALSE;
365a7fd8e5eSmacallan	}
366727c6de2Smacallan
367727c6de2Smacallan	if (ioctl(fPtr->fd, GCID, &gid) == -1)
368a7fd8e5eSmacallan		return FALSE;
369727c6de2Smacallan
370727c6de2Smacallan	fPtr->gid = gid;
371727c6de2Smacallan	fPtr->fbacc = 0;
372727c6de2Smacallan
373727c6de2Smacallan	switch (gid) {
374727c6de2Smacallan		case STI_DD_EG:
375bc460d0dSmacallan			fPtr->buf = BINapp0I;
376727c6de2Smacallan			fPtr->fbacc = BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, fPtr->buf, 0);
3777517da51Smacallan			fPtr->reglen = 0x400000;
378727c6de2Smacallan			break;
379727c6de2Smacallan		case STI_DD_HCRX:
380727c6de2Smacallan			/* XXX BINovly if in 8 bit */
381727c6de2Smacallan			fPtr->buf = BINapp0F8;
382727c6de2Smacallan			fPtr->fbacc = BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, fPtr->buf, 0);
383ce159321Smacallan			/*
384ce159321Smacallan			 * XXX
385ce159321Smacallan			 * we don't know yet how much usable video memory we
386ce159321Smacallan			 * have but EXA gets cranky if there is no off screen
387ce159321Smacallan			 * memory at all, so we give it one line and cross
388ce159321Smacallan			 * fingers
389ce159321Smacallan			 */
390ce159321Smacallan			fPtr->fbi.fbi_fbsize += 8192;
3917517da51Smacallan			fPtr->reglen = 0x400000;
3927517da51Smacallan			break;
3937517da51Smacallan		case STI_DD_SUMMIT:
3947517da51Smacallan			fPtr->reglen = 0x1000000;
3957517da51Smacallan			break;
396a7fd8e5eSmacallan	}
397727c6de2Smacallan	xf86Msg(X_ERROR, "gid %08x fb access %08x\n", fPtr->gid, fPtr->fbacc);
398727c6de2Smacallan
399a7fd8e5eSmacallan	/* Handle depth */
400a7fd8e5eSmacallan	default_depth = fPtr->fbi.fbi_bitsperpixel <= 24 ? fPtr->fbi.fbi_bitsperpixel : 24;
401a7fd8e5eSmacallan	bitsperpixel = fPtr->fbi.fbi_bitsperpixel == 15 ? 16 : fPtr->fbi.fbi_bitsperpixel;
402a7fd8e5eSmacallan	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
403a7fd8e5eSmacallan		bitsperpixel,
404a7fd8e5eSmacallan		bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0))
405a7fd8e5eSmacallan		return FALSE;
406a7fd8e5eSmacallan
407a7fd8e5eSmacallan	xf86PrintDepthBpp(pScrn);
408a7fd8e5eSmacallan
409a7fd8e5eSmacallan	/* color weight */
410a7fd8e5eSmacallan	masks.red =   0x00ff0000;
411a7fd8e5eSmacallan	masks.green = 0x0000ff00;
412a7fd8e5eSmacallan	masks.blue =  0x000000ff;
413a7fd8e5eSmacallan	if (!xf86SetWeight(pScrn, rgbzeros, masks))
414a7fd8e5eSmacallan		return FALSE;
415a7fd8e5eSmacallan
416a7fd8e5eSmacallan	/* visual init */
417a7fd8e5eSmacallan	if (!xf86SetDefaultVisual(pScrn, -1))
418a7fd8e5eSmacallan		return FALSE;
419a7fd8e5eSmacallan
420a7fd8e5eSmacallan	/* We don't currently support DirectColor at > 8bpp */
421a7fd8e5eSmacallan	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
422a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
423a7fd8e5eSmacallan			   " (%s) is not supported at depth %d\n",
424a7fd8e5eSmacallan			   xf86GetVisualName(pScrn->defaultVisual),
425a7fd8e5eSmacallan			   pScrn->depth);
426a7fd8e5eSmacallan		return FALSE;
427a7fd8e5eSmacallan	}
428a7fd8e5eSmacallan
429a7fd8e5eSmacallan	xf86SetGamma(pScrn,zeros);
430a7fd8e5eSmacallan
431a7fd8e5eSmacallan	pScrn->progClock = TRUE;
432a7fd8e5eSmacallan	pScrn->rgbBits   = 8;
433a7fd8e5eSmacallan	pScrn->chipset   = "NGLE";
434a7fd8e5eSmacallan	fPtr->fbmem_len = pScrn->videoRam  = fPtr->fbi.fbi_fbsize;
435a7fd8e5eSmacallan
436a7fd8e5eSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
437a7fd8e5eSmacallan		   pScrn->videoRam/1024);
438a7fd8e5eSmacallan
439a7fd8e5eSmacallan	/* handle options */
440a7fd8e5eSmacallan	xf86CollectOptions(pScrn, NULL);
441a7fd8e5eSmacallan	if (!(fPtr->Options = malloc(sizeof(NGLEOptions))))
442a7fd8e5eSmacallan		return FALSE;
443a7fd8e5eSmacallan	memcpy(fPtr->Options, NGLEOptions, sizeof(NGLEOptions));
444a7fd8e5eSmacallan	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
445a7fd8e5eSmacallan			   fPtr->Options);
446a7fd8e5eSmacallan
447a7fd8e5eSmacallan	/* fake video mode struct */
448a7fd8e5eSmacallan	mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec));
449a7fd8e5eSmacallan	mode->prev = mode;
450a7fd8e5eSmacallan	mode->next = mode;
451a7fd8e5eSmacallan	mode->name = "NGLE current mode";
452a7fd8e5eSmacallan	mode->status = MODE_OK;
453a7fd8e5eSmacallan	mode->type = M_T_BUILTIN;
454a7fd8e5eSmacallan	mode->Clock = 0;
455a7fd8e5eSmacallan	mode->HDisplay = fPtr->fbi.fbi_width;
456a7fd8e5eSmacallan	mode->HSyncStart = 0;
457a7fd8e5eSmacallan	mode->HSyncEnd = 0;
458a7fd8e5eSmacallan	mode->HTotal = 0;
459a7fd8e5eSmacallan	mode->HSkew = 0;
460a7fd8e5eSmacallan	mode->VDisplay = fPtr->fbi.fbi_height;
461a7fd8e5eSmacallan	mode->VSyncStart = 0;
462a7fd8e5eSmacallan	mode->VSyncEnd = 0;
463a7fd8e5eSmacallan	mode->VTotal = 0;
464a7fd8e5eSmacallan	mode->VScan = 0;
465a7fd8e5eSmacallan	mode->Flags = 0;
466a7fd8e5eSmacallan	if (pScrn->modes != NULL) {
467a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
468a7fd8e5eSmacallan		   "Ignoring mode specification from screen section\n");
469a7fd8e5eSmacallan	}
470a7fd8e5eSmacallan	pScrn->currentMode = pScrn->modes = mode;
471a7fd8e5eSmacallan	pScrn->virtualX = fPtr->fbi.fbi_width;
472a7fd8e5eSmacallan	pScrn->virtualY = fPtr->fbi.fbi_height;
473a7fd8e5eSmacallan	pScrn->displayWidth = 2048;
474a7fd8e5eSmacallan
475a7fd8e5eSmacallan	/* Set the display resolution */
476a7fd8e5eSmacallan	xf86SetDpi(pScrn, 0, 0);
477a7fd8e5eSmacallan
478a7fd8e5eSmacallan	from = X_DEFAULT;
4797517da51Smacallan	fPtr->HWCursor = FALSE;
4807517da51Smacallan	if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor)) {
481a7fd8e5eSmacallan		from = X_CONFIG;
4827517da51Smacallan		fPtr->HWCursor = TRUE;
483a7fd8e5eSmacallan	}
484a7fd8e5eSmacallan	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
485a7fd8e5eSmacallan		fPtr->HWCursor ? "HW" : "SW");
486a7fd8e5eSmacallan
487a7fd8e5eSmacallan	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
488a7fd8e5eSmacallan		NGLEFreeRec(pScrn);
489a7fd8e5eSmacallan		return FALSE;
490a7fd8e5eSmacallan	}
491a7fd8e5eSmacallan
492a7fd8e5eSmacallan	if (xf86LoadSubModule(pScrn, "exa") == NULL) {
493a7fd8e5eSmacallan		NGLEFreeRec(pScrn);
494a7fd8e5eSmacallan		return FALSE;
495a7fd8e5eSmacallan	}
496a7fd8e5eSmacallan
497a7fd8e5eSmacallan	return TRUE;
498a7fd8e5eSmacallan}
499a7fd8e5eSmacallan
500a7fd8e5eSmacallanstatic Bool
501a7fd8e5eSmacallanNGLEScreenInit(SCREEN_INIT_ARGS_DECL)
502a7fd8e5eSmacallan{
503a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
504a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
505a7fd8e5eSmacallan	VisualPtr visual;
506a7fd8e5eSmacallan	int ret, flags, width, height, i, j;
507a7fd8e5eSmacallan	int wsmode = WSDISPLAYIO_MODE_MAPPED;
508a7fd8e5eSmacallan	size_t len;
509a7fd8e5eSmacallan
510a7fd8e5eSmacallan#ifdef NGLE_DEBUG
511a7fd8e5eSmacallan	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
512a7fd8e5eSmacallan	       "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
513a7fd8e5eSmacallan	       pScrn->bitsPerPixel,
514a7fd8e5eSmacallan	       pScrn->depth,
515a7fd8e5eSmacallan	       xf86GetVisualName(pScrn->defaultVisual),
516a7fd8e5eSmacallan	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
517a7fd8e5eSmacallan	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
518a7fd8e5eSmacallan#endif
519a7fd8e5eSmacallan
520a7fd8e5eSmacallan	/* Switch to graphics mode - required before mmap */
521a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
522a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
523a7fd8e5eSmacallan			   "ioctl WSDISPLAYIO_SMODE: %s\n",
524a7fd8e5eSmacallan			   strerror(errno));
525a7fd8e5eSmacallan		return FALSE;
526a7fd8e5eSmacallan	}
5277517da51Smacallan
5287517da51Smacallan	fPtr->regs = ngle_mmap(fPtr->reglen, 0x80000000, fPtr->fd, 0);
529a7fd8e5eSmacallan
530a7fd8e5eSmacallan	if (fPtr->regs == NULL) {
531a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
532a7fd8e5eSmacallan			   "ngle_mmap registers: %s\n", strerror(errno));
533a7fd8e5eSmacallan		return FALSE;
534a7fd8e5eSmacallan	}
535a7fd8e5eSmacallan
536a7fd8e5eSmacallan	fPtr->fbmem = ngle_mmap(fPtr->fbmem_len, 0, fPtr->fd, 0);
537a7fd8e5eSmacallan	if (fPtr->fbmem == NULL) {
538a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
539a7fd8e5eSmacallan			   "ngle_mmap fb: %s\n", strerror(errno));
540a7fd8e5eSmacallan		return FALSE;
541a7fd8e5eSmacallan	}
542a7fd8e5eSmacallan
543a7fd8e5eSmacallan	NGLESave(pScrn);
544a7fd8e5eSmacallan	pScrn->vtSema = TRUE;
545a7fd8e5eSmacallan
546a7fd8e5eSmacallan	/* mi layer */
547a7fd8e5eSmacallan	miClearVisualTypes();
54888c8ff34Smacallan	if (pScrn->bitsPerPixel > 8) {
54988c8ff34Smacallan		if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
55088c8ff34Smacallan				      pScrn->rgbBits, TrueColor))
55188c8ff34Smacallan			return FALSE;
55288c8ff34Smacallan	} else {
55388c8ff34Smacallan		if (!miSetVisualTypes(pScrn->depth,
55488c8ff34Smacallan				      miGetDefaultVisualMask(pScrn->depth),
55588c8ff34Smacallan				      pScrn->rgbBits, pScrn->defaultVisual))
55688c8ff34Smacallan			return FALSE;
55788c8ff34Smacallan	}
558a7fd8e5eSmacallan
559a7fd8e5eSmacallan	if (!miSetPixmapDepths())
560a7fd8e5eSmacallan		return FALSE;
561a7fd8e5eSmacallan
562a7fd8e5eSmacallan	height = pScrn->virtualY;
563a7fd8e5eSmacallan	width = pScrn->virtualX;
564a7fd8e5eSmacallan
565a7fd8e5eSmacallan	ret = fbScreenInit(pScreen,
566a7fd8e5eSmacallan			   fPtr->fbmem,
567a7fd8e5eSmacallan			   width, height,
568a7fd8e5eSmacallan			   pScrn->xDpi, pScrn->yDpi,
569a7fd8e5eSmacallan			   pScrn->displayWidth,
570a7fd8e5eSmacallan			   pScrn->bitsPerPixel);
571a7fd8e5eSmacallan
572a7fd8e5eSmacallan	if (!ret)
573a7fd8e5eSmacallan		return FALSE;
574a7fd8e5eSmacallan
575a7fd8e5eSmacallan	if (pScrn->bitsPerPixel > 8) {
576a7fd8e5eSmacallan		/* Fixup RGB ordering. */
577a7fd8e5eSmacallan		visual = pScreen->visuals + pScreen->numVisuals;
578a7fd8e5eSmacallan		while (--visual >= pScreen->visuals) {
579a7fd8e5eSmacallan			if ((visual->class | DynamicClass) == DirectColor) {
580a7fd8e5eSmacallan				visual->offsetRed   = pScrn->offset.red;
581a7fd8e5eSmacallan				visual->offsetGreen = pScrn->offset.green;
582a7fd8e5eSmacallan				visual->offsetBlue  = pScrn->offset.blue;
583a7fd8e5eSmacallan				visual->redMask     = pScrn->mask.red;
584a7fd8e5eSmacallan				visual->greenMask   = pScrn->mask.green;
585a7fd8e5eSmacallan				visual->blueMask    = pScrn->mask.blue;
586a7fd8e5eSmacallan			}
587a7fd8e5eSmacallan		}
588a7fd8e5eSmacallan	}
589a7fd8e5eSmacallan
590a7fd8e5eSmacallan	if (!fbPictureInit(pScreen, NULL, 0))
591a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
592a7fd8e5eSmacallan			   "RENDER extension initialisation failed.");
593a7fd8e5eSmacallan
594a7fd8e5eSmacallan	xf86SetBlackWhitePixels(pScreen);
595a7fd8e5eSmacallan	xf86SetBackingStore(pScreen);
596a7fd8e5eSmacallan
597a7fd8e5eSmacallan	if (fPtr) {
5987517da51Smacallan		if (fPtr->gid == STI_DD_SUMMIT) {
5997517da51Smacallan			SummitInitAccel(pScreen);
6007517da51Smacallan		} else
6017517da51Smacallan			NGLEInitAccel(pScreen);
602727c6de2Smacallan		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using acceleration\n");
603a7fd8e5eSmacallan	}
604a7fd8e5eSmacallan
605a7fd8e5eSmacallan	/* software cursor */
606a7fd8e5eSmacallan	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
607a7fd8e5eSmacallan
608a7fd8e5eSmacallan	/* check for hardware cursor support */
609a7fd8e5eSmacallan	NGLESetupCursor(pScreen);
610a7fd8e5eSmacallan
611a7fd8e5eSmacallan	/* colormap */
612a7fd8e5eSmacallan	if (!miCreateDefColormap(pScreen))
613a7fd8e5eSmacallan		return FALSE;
614a7fd8e5eSmacallan
615a7fd8e5eSmacallan	flags = CMAP_RELOAD_ON_MODE_SWITCH;
616a7fd8e5eSmacallan	if(!xf86HandleColormaps(pScreen, 256, 8, NGLELoadPalette,
617a7fd8e5eSmacallan				NULL, flags))
618a7fd8e5eSmacallan		return FALSE;
619a7fd8e5eSmacallan
620a7fd8e5eSmacallan	pScreen->SaveScreen = NGLESaveScreen;
621a7fd8e5eSmacallan
622a7fd8e5eSmacallan#ifdef XvExtension
623a7fd8e5eSmacallan	{
624a7fd8e5eSmacallan		XF86VideoAdaptorPtr *ptr;
625a7fd8e5eSmacallan
626a7fd8e5eSmacallan		int n = xf86XVListGenericAdaptors(pScrn,&ptr);
627a7fd8e5eSmacallan		if (n) {
628a7fd8e5eSmacallan			xf86XVScreenInit(pScreen,ptr,n);
629a7fd8e5eSmacallan		}
630a7fd8e5eSmacallan	}
631a7fd8e5eSmacallan#endif
632a7fd8e5eSmacallan
633a7fd8e5eSmacallan	/* Wrap the current CloseScreen function */
634a7fd8e5eSmacallan	fPtr->CloseScreen = pScreen->CloseScreen;
635a7fd8e5eSmacallan	pScreen->CloseScreen = NGLECloseScreen;
636a7fd8e5eSmacallan
637a7fd8e5eSmacallan	return TRUE;
638a7fd8e5eSmacallan}
639a7fd8e5eSmacallan
640a7fd8e5eSmacallanstatic Bool
641a7fd8e5eSmacallanNGLECloseScreen(CLOSE_SCREEN_ARGS_DECL)
642a7fd8e5eSmacallan{
643a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
644a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
645a7fd8e5eSmacallan
646a7fd8e5eSmacallan	if (pScrn->vtSema) {
647a7fd8e5eSmacallan		NGLERestore(pScrn);
6487517da51Smacallan		if (munmap(fPtr->regs, fPtr->reglen) == -1) {
649a7fd8e5eSmacallan			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
650a7fd8e5eSmacallan				   "munmap engine: %s\n", strerror(errno));
651a7fd8e5eSmacallan		}
652a7fd8e5eSmacallan
653a7fd8e5eSmacallan		if (munmap(fPtr->fbmem, fPtr->fbmem_len) == -1) {
654a7fd8e5eSmacallan			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
655a7fd8e5eSmacallan				   "munmap fb: %s\n", strerror(errno));
656a7fd8e5eSmacallan		}
657a7fd8e5eSmacallan
658a7fd8e5eSmacallan		fPtr->regs = NULL;
659a7fd8e5eSmacallan		fPtr->fbmem = NULL;
660a7fd8e5eSmacallan	}
661a7fd8e5eSmacallan	pScrn->vtSema = FALSE;
662a7fd8e5eSmacallan
663a7fd8e5eSmacallan	/* unwrap CloseScreen */
664a7fd8e5eSmacallan	pScreen->CloseScreen = fPtr->CloseScreen;
665a7fd8e5eSmacallan	return (*pScreen->CloseScreen)(pScreen);
666a7fd8e5eSmacallan}
667a7fd8e5eSmacallan
668a7fd8e5eSmacallanstatic Bool
669a7fd8e5eSmacallanNGLEEnterVT(VT_FUNC_ARGS_DECL)
670a7fd8e5eSmacallan{
671a7fd8e5eSmacallan	SCRN_INFO_PTR(arg);
672a7fd8e5eSmacallan
673a7fd8e5eSmacallan	pScrn->vtSema = TRUE;
674a7fd8e5eSmacallan	return TRUE;
675a7fd8e5eSmacallan}
676a7fd8e5eSmacallan
677a7fd8e5eSmacallanstatic void
678a7fd8e5eSmacallanNGLELeaveVT(VT_FUNC_ARGS_DECL)
679a7fd8e5eSmacallan{
680a7fd8e5eSmacallan}
681a7fd8e5eSmacallan
682a7fd8e5eSmacallanstatic Bool
683a7fd8e5eSmacallanNGLESwitchMode(SWITCH_MODE_ARGS_DECL)
684a7fd8e5eSmacallan{
685a7fd8e5eSmacallan
686a7fd8e5eSmacallan	/* Nothing else to do */
687a7fd8e5eSmacallan	return TRUE;
688a7fd8e5eSmacallan}
689a7fd8e5eSmacallan
690a7fd8e5eSmacallanstatic int
691a7fd8e5eSmacallanNGLEValidMode(SCRN_ARG_TYPE, DisplayModePtr mode, Bool verbose, int flags)
692a7fd8e5eSmacallan{
693a7fd8e5eSmacallan
694a7fd8e5eSmacallan	return MODE_OK;
695a7fd8e5eSmacallan}
696a7fd8e5eSmacallan
697a7fd8e5eSmacallanstatic void
698a7fd8e5eSmacallanNGLELoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
699a7fd8e5eSmacallan	       LOCO *colors, VisualPtr pVisual)
700a7fd8e5eSmacallan{
701a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
702a7fd8e5eSmacallan	struct wsdisplay_cmap cmap;
703a7fd8e5eSmacallan	unsigned char red[256],green[256],blue[256];
704a7fd8e5eSmacallan	int i, indexMin=256, indexMax=0;
705a7fd8e5eSmacallan
706a7fd8e5eSmacallan	/* nothing to do if there is no color palette support */
707a7fd8e5eSmacallan	if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0)
708a7fd8e5eSmacallan		return;
709a7fd8e5eSmacallan
710a7fd8e5eSmacallan	cmap.count   = 1;
711a7fd8e5eSmacallan	cmap.red   = red;
712a7fd8e5eSmacallan	cmap.green = green;
713a7fd8e5eSmacallan	cmap.blue  = blue;
714a7fd8e5eSmacallan
715a7fd8e5eSmacallan	if (numColors == 1) {
716a7fd8e5eSmacallan		/* Optimisation */
717a7fd8e5eSmacallan		cmap.index = indices[0];
718a7fd8e5eSmacallan		red[0]   = colors[indices[0]].red;
719a7fd8e5eSmacallan		green[0] = colors[indices[0]].green;
720a7fd8e5eSmacallan		blue[0]  = colors[indices[0]].blue;
721a7fd8e5eSmacallan		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
722a7fd8e5eSmacallan			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
723a7fd8e5eSmacallan	} else {
724a7fd8e5eSmacallan		/*
725a7fd8e5eSmacallan		 * Change all colors in 2 ioctls
726a7fd8e5eSmacallan		 * and limit the data to be transferred.
727a7fd8e5eSmacallan		 */
728a7fd8e5eSmacallan		for (i = 0; i < numColors; i++) {
729a7fd8e5eSmacallan			if (indices[i] < indexMin)
730a7fd8e5eSmacallan				indexMin = indices[i];
731a7fd8e5eSmacallan			if (indices[i] > indexMax)
732a7fd8e5eSmacallan				indexMax = indices[i];
733a7fd8e5eSmacallan		}
734a7fd8e5eSmacallan		cmap.index = indexMin;
735a7fd8e5eSmacallan		cmap.count = indexMax - indexMin + 1;
736a7fd8e5eSmacallan		cmap.red = &red[indexMin];
737a7fd8e5eSmacallan		cmap.green = &green[indexMin];
738a7fd8e5eSmacallan		cmap.blue = &blue[indexMin];
739a7fd8e5eSmacallan		/* Get current map. */
740a7fd8e5eSmacallan		if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1)
741a7fd8e5eSmacallan			ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno));
742a7fd8e5eSmacallan		/* Change the colors that require updating. */
743a7fd8e5eSmacallan		for (i = 0; i < numColors; i++) {
744a7fd8e5eSmacallan			red[indices[i]]   = colors[indices[i]].red;
745a7fd8e5eSmacallan			green[indices[i]] = colors[indices[i]].green;
746a7fd8e5eSmacallan			blue[indices[i]]  = colors[indices[i]].blue;
747a7fd8e5eSmacallan		}
748a7fd8e5eSmacallan		/* Write the colormap back. */
749a7fd8e5eSmacallan		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
750a7fd8e5eSmacallan			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
751a7fd8e5eSmacallan	}
752f8e8ce30Smacallan	fPtr->hwmode = -1;
753a7fd8e5eSmacallan}
754a7fd8e5eSmacallan
755a7fd8e5eSmacallanstatic Bool
756a7fd8e5eSmacallanNGLESaveScreen(ScreenPtr pScreen, int mode)
757a7fd8e5eSmacallan{
758a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
759a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
760a7fd8e5eSmacallan	int state;
761a7fd8e5eSmacallan
762a7fd8e5eSmacallan	if (!pScrn->vtSema)
763a7fd8e5eSmacallan		return TRUE;
764a7fd8e5eSmacallan
765a7fd8e5eSmacallan	if (mode != SCREEN_SAVER_FORCER) {
766a7fd8e5eSmacallan		state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON:
767a7fd8e5eSmacallan		                            WSDISPLAYIO_VIDEO_OFF;
768a7fd8e5eSmacallan		ioctl(fPtr->fd,
769a7fd8e5eSmacallan		      WSDISPLAYIO_SVIDEO, &state);
770a7fd8e5eSmacallan	}
771a7fd8e5eSmacallan	return TRUE;
772a7fd8e5eSmacallan}
773a7fd8e5eSmacallan
774a7fd8e5eSmacallan
775a7fd8e5eSmacallanstatic void
776a7fd8e5eSmacallanNGLESave(ScrnInfoPtr pScrn)
777a7fd8e5eSmacallan{
778a7fd8e5eSmacallan}
779a7fd8e5eSmacallan
780a7fd8e5eSmacallanstatic void
781a7fd8e5eSmacallanNGLERestore(ScrnInfoPtr pScrn)
782a7fd8e5eSmacallan{
783a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
784a7fd8e5eSmacallan	int mode;
785a7fd8e5eSmacallan
786a7fd8e5eSmacallan	/* Restore the text mode */
787a7fd8e5eSmacallan	mode = WSDISPLAYIO_MODE_EMUL;
788a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
789a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
790a7fd8e5eSmacallan			   "error setting text mode %s\n", strerror(errno));
791a7fd8e5eSmacallan	}
792a7fd8e5eSmacallan}
793