ngle_driver.c revision f8e8ce30
1f8e8ce30Smacallan/* $NetBSD: ngle_driver.c,v 1.6 2024/10/27 11:09:37 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" },
110a7fd8e5eSmacallan	{ -1, NULL }
111a7fd8e5eSmacallan};
112a7fd8e5eSmacallan
113a7fd8e5eSmacallan/* Supported options */
114a7fd8e5eSmacallantypedef enum {
115a7fd8e5eSmacallan	OPTION_HW_CURSOR,
116a7fd8e5eSmacallan	OPTION_SW_CURSOR
117a7fd8e5eSmacallan} NGLEOpts;
118a7fd8e5eSmacallan
119a7fd8e5eSmacallanstatic const OptionInfoRec NGLEOptions[] = {
120a7fd8e5eSmacallan	{ OPTION_SW_CURSOR, "SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
121a7fd8e5eSmacallan	{ OPTION_HW_CURSOR, "HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
122a7fd8e5eSmacallan	{ -1, NULL, OPTV_NONE, {0}, FALSE}
123a7fd8e5eSmacallan};
124a7fd8e5eSmacallan
125a7fd8e5eSmacallanstatic XF86ModuleVersionInfo NGLEVersRec = {
126a7fd8e5eSmacallan	"ngle",
127a7fd8e5eSmacallan	"The NetBSD Foundation",
128a7fd8e5eSmacallan	MODINFOSTRING1,
129a7fd8e5eSmacallan	MODINFOSTRING2,
130a7fd8e5eSmacallan	XORG_VERSION_CURRENT,
131a7fd8e5eSmacallan	NGLE_MAJOR_VERSION, NGLE_MINOR_VERSION, 0,
132a7fd8e5eSmacallan	ABI_CLASS_VIDEODRV,
133a7fd8e5eSmacallan	ABI_VIDEODRV_VERSION,
134a7fd8e5eSmacallan	NULL,
135a7fd8e5eSmacallan	{0, 0, 0, 0}
136a7fd8e5eSmacallan};
137a7fd8e5eSmacallan
138a7fd8e5eSmacallan_X_EXPORT XF86ModuleData ngleModuleData = { &NGLEVersRec, NGLESetup, NULL };
139a7fd8e5eSmacallan
140a7fd8e5eSmacallanstatic pointer
141a7fd8e5eSmacallanNGLESetup(pointer module, pointer opts, int *errmaj, int *errmin)
142a7fd8e5eSmacallan{
143a7fd8e5eSmacallan	static Bool setupDone = FALSE;
144a7fd8e5eSmacallan	const char *osname;
145a7fd8e5eSmacallan
146a7fd8e5eSmacallan	if (!setupDone) {
147a7fd8e5eSmacallan		setupDone = TRUE;
148a7fd8e5eSmacallan		xf86AddDriver(&NGLE, module, 0);
149a7fd8e5eSmacallan		return (pointer)1;
150a7fd8e5eSmacallan	} else {
151a7fd8e5eSmacallan		if (errmaj != NULL)
152a7fd8e5eSmacallan			*errmaj = LDR_ONCEONLY;
153a7fd8e5eSmacallan		return NULL;
154a7fd8e5eSmacallan	}
155a7fd8e5eSmacallan}
156a7fd8e5eSmacallan
157a7fd8e5eSmacallanstatic Bool
158a7fd8e5eSmacallanNGLEGetRec(ScrnInfoPtr pScrn)
159a7fd8e5eSmacallan{
160a7fd8e5eSmacallan
161a7fd8e5eSmacallan	if (pScrn->driverPrivate != NULL)
162a7fd8e5eSmacallan		return TRUE;
163a7fd8e5eSmacallan
164a7fd8e5eSmacallan	pScrn->driverPrivate = xnfcalloc(sizeof(NGLERec), 1);
165a7fd8e5eSmacallan	return TRUE;
166a7fd8e5eSmacallan}
167a7fd8e5eSmacallan
168a7fd8e5eSmacallanstatic void
169a7fd8e5eSmacallanNGLEFreeRec(ScrnInfoPtr pScrn)
170a7fd8e5eSmacallan{
171a7fd8e5eSmacallan
172a7fd8e5eSmacallan	if (pScrn->driverPrivate == NULL)
173a7fd8e5eSmacallan		return;
174a7fd8e5eSmacallan	free(pScrn->driverPrivate);
175a7fd8e5eSmacallan	pScrn->driverPrivate = NULL;
176a7fd8e5eSmacallan}
177a7fd8e5eSmacallan
178a7fd8e5eSmacallanstatic const OptionInfoRec *
179a7fd8e5eSmacallanNGLEAvailableOptions(int chipid, int busid)
180a7fd8e5eSmacallan{
181a7fd8e5eSmacallan	return NGLEOptions;
182a7fd8e5eSmacallan}
183a7fd8e5eSmacallan
184a7fd8e5eSmacallanstatic void
185a7fd8e5eSmacallanNGLEIdentify(int flags)
186a7fd8e5eSmacallan{
187a7fd8e5eSmacallan	xf86PrintChipsets(NGLE_NAME, "driver for NGLE framebuffers",
188a7fd8e5eSmacallan			  NGLEChipsets);
189a7fd8e5eSmacallan}
190a7fd8e5eSmacallan
191a7fd8e5eSmacallan
192a7fd8e5eSmacallan#define priv_open_device(n)	open(n,O_RDWR|O_NONBLOCK|O_EXCL)
193a7fd8e5eSmacallan
194a7fd8e5eSmacallan/* Open the framebuffer device */
195a7fd8e5eSmacallanstatic int
196a7fd8e5eSmacallanngle_open(const char *dev)
197a7fd8e5eSmacallan{
198a7fd8e5eSmacallan	int fd = -1;
199a7fd8e5eSmacallan
200a7fd8e5eSmacallan	/* try argument from XF86Config first */
201a7fd8e5eSmacallan	if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
202a7fd8e5eSmacallan		/* second: environment variable */
203a7fd8e5eSmacallan		dev = getenv("XDEVICE");
204a7fd8e5eSmacallan		if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
205a7fd8e5eSmacallan			/* last try: default device */
206a7fd8e5eSmacallan			dev = NGLE_DEFAULT_DEV;
207a7fd8e5eSmacallan			if ((fd = priv_open_device(dev)) == -1) {
208a7fd8e5eSmacallan				return -1;
209a7fd8e5eSmacallan			}
210a7fd8e5eSmacallan		}
211a7fd8e5eSmacallan	}
212a7fd8e5eSmacallan	return fd;
213a7fd8e5eSmacallan}
214a7fd8e5eSmacallan
215a7fd8e5eSmacallan/* Map the framebuffer's memory */
216a7fd8e5eSmacallanstatic pointer
217a7fd8e5eSmacallanngle_mmap(size_t len, off_t off, int fd, int ro)
218a7fd8e5eSmacallan{
219a7fd8e5eSmacallan	pointer mapaddr;
220a7fd8e5eSmacallan
221a7fd8e5eSmacallan	/*
222a7fd8e5eSmacallan	 * try and make it private first, that way once we get it, an
223a7fd8e5eSmacallan	 * interloper, e.g. another server, can't get this frame buffer,
224a7fd8e5eSmacallan	 * and if another server already has it, this one won't.
225a7fd8e5eSmacallan	 */
226a7fd8e5eSmacallan	if (ro) {
227a7fd8e5eSmacallan		mapaddr = (pointer) mmap(NULL, len,
228a7fd8e5eSmacallan					 PROT_READ, MAP_SHARED,
229a7fd8e5eSmacallan					 fd, off);
230a7fd8e5eSmacallan		xf86Msg(X_ERROR, "mapping %08x read only\n", off);
231a7fd8e5eSmacallan	} else {
232a7fd8e5eSmacallan		mapaddr = (pointer) mmap(NULL, len,
233a7fd8e5eSmacallan					 PROT_READ | PROT_WRITE, MAP_SHARED,
234a7fd8e5eSmacallan					 fd, off);
235a7fd8e5eSmacallan		xf86Msg(X_ERROR, "mapping %08x read/write\n", off);
236a7fd8e5eSmacallan	}
237a7fd8e5eSmacallan	if (mapaddr == (pointer) -1) {
238a7fd8e5eSmacallan		mapaddr = NULL;
239a7fd8e5eSmacallan	}
240a7fd8e5eSmacallan#ifdef NGLE_DEBUG
241a7fd8e5eSmacallan	ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, len);
242a7fd8e5eSmacallan#endif
243a7fd8e5eSmacallan	return mapaddr;
244a7fd8e5eSmacallan}
245a7fd8e5eSmacallan
246a7fd8e5eSmacallanstatic Bool
247a7fd8e5eSmacallanNGLEProbe(DriverPtr drv, int flags)
248a7fd8e5eSmacallan{
249a7fd8e5eSmacallan	ScrnInfoPtr pScrn = NULL;
250a7fd8e5eSmacallan	int i, fd, entity, wstype;
251a7fd8e5eSmacallan       	GDevPtr *devSections;
252a7fd8e5eSmacallan	int numDevSections;
253a7fd8e5eSmacallan	char *dev;
254a7fd8e5eSmacallan	const char *name;
255a7fd8e5eSmacallan	uint32_t gid;
256a7fd8e5eSmacallan	Bool foundScreen = FALSE;
257a7fd8e5eSmacallan
258a7fd8e5eSmacallan	if ((numDevSections = xf86MatchDevice(NGLE_DRIVER_NAME,
259a7fd8e5eSmacallan					      &devSections)) <= 0)
260a7fd8e5eSmacallan		return FALSE;
261a7fd8e5eSmacallan
262a7fd8e5eSmacallan
263a7fd8e5eSmacallan	if ((fd = ngle_open(NGLE_DEFAULT_DEV)) == 0)
264a7fd8e5eSmacallan		return FALSE;
265a7fd8e5eSmacallan
266a7fd8e5eSmacallan	if (ioctl(fd, WSDISPLAYIO_GTYPE, &wstype) == -1)
267a7fd8e5eSmacallan		return FALSE;
268a7fd8e5eSmacallan
269a7fd8e5eSmacallan	if (wstype != WSDISPLAY_TYPE_STI)
270a7fd8e5eSmacallan		return FALSE;
271a7fd8e5eSmacallan
272a7fd8e5eSmacallan	if (ioctl(fd, GCID, &gid) == -1)
273a7fd8e5eSmacallan		return FALSE;
274a7fd8e5eSmacallan
275a7fd8e5eSmacallan	/* reject GIDs not in the table */
276a7fd8e5eSmacallan	if ((name = xf86TokenToString(NGLEChipsets, gid)) == NULL)
277a7fd8e5eSmacallan		return FALSE;
278a7fd8e5eSmacallan
279a7fd8e5eSmacallan	xf86Msg(X_INFO, "%s: found %s ( GID %08x )\n", __func__, name, gid);
280a7fd8e5eSmacallan
281a7fd8e5eSmacallan	if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
282a7fd8e5eSmacallan		GDevPtr pGDev;
283a7fd8e5eSmacallan
284a7fd8e5eSmacallan		pGDev = xf86AddBusDeviceToConfigure(NGLE_DRIVER_NAME, BUS_NONE,
285a7fd8e5eSmacallan			NULL, 0);
286a7fd8e5eSmacallan		if (pGDev) {
287a7fd8e5eSmacallan			/*
288a7fd8e5eSmacallan			 * XF86Match???Instances() treat chipID and chipRev as
289a7fd8e5eSmacallan			 * overrides, so clobber them here.
290a7fd8e5eSmacallan			 */
291a7fd8e5eSmacallan			pGDev->chipID = pGDev->chipRev = -1;
292a7fd8e5eSmacallan	    	}
293a7fd8e5eSmacallan	}
294a7fd8e5eSmacallan
295a7fd8e5eSmacallan	if (flags & PROBE_DETECT) {
296a7fd8e5eSmacallan		return TRUE;
297a7fd8e5eSmacallan	}
298a7fd8e5eSmacallan
299a7fd8e5eSmacallan	if (numDevSections > 1) {
300a7fd8e5eSmacallan		xf86Msg(X_ERROR, "Ignoring additional device sections\n");
301a7fd8e5eSmacallan		numDevSections = 1;
302a7fd8e5eSmacallan	}
303a7fd8e5eSmacallan	/* ok, at this point we know we've got a NGLE */
304a7fd8e5eSmacallan	for (i = 0; i < numDevSections; i++) {
305a7fd8e5eSmacallan
306a7fd8e5eSmacallan		entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
307a7fd8e5eSmacallan		pScrn = xf86ConfigFbEntity(NULL, 0, entity,
308a7fd8e5eSmacallan		    NULL, NULL, NULL, NULL);
309a7fd8e5eSmacallan		if (pScrn != NULL) {
310a7fd8e5eSmacallan			foundScreen = TRUE;
311a7fd8e5eSmacallan			pScrn->driverVersion = VERSION;
312a7fd8e5eSmacallan			pScrn->driverName = NGLE_DRIVER_NAME;
313a7fd8e5eSmacallan			pScrn->name = NGLE_NAME;
314a7fd8e5eSmacallan			pScrn->Probe = NGLEProbe;
315a7fd8e5eSmacallan			pScrn->PreInit = NGLEPreInit;
316a7fd8e5eSmacallan			pScrn->ScreenInit = NGLEScreenInit;
317a7fd8e5eSmacallan			pScrn->SwitchMode = NGLESwitchMode;
318a7fd8e5eSmacallan			pScrn->AdjustFrame = NULL;
319a7fd8e5eSmacallan			pScrn->EnterVT = NGLEEnterVT;
320a7fd8e5eSmacallan			pScrn->LeaveVT = NGLELeaveVT;
321a7fd8e5eSmacallan			pScrn->ValidMode = NGLEValidMode;
322a7fd8e5eSmacallan
323a7fd8e5eSmacallan		}
324a7fd8e5eSmacallan	}
325a7fd8e5eSmacallan	free(devSections);
326a7fd8e5eSmacallan	return foundScreen;
327a7fd8e5eSmacallan}
328a7fd8e5eSmacallan
329a7fd8e5eSmacallanstatic Bool
330a7fd8e5eSmacallanNGLEPreInit(ScrnInfoPtr pScrn, int flags)
331a7fd8e5eSmacallan{
332a7fd8e5eSmacallan	NGLEPtr fPtr;
333727c6de2Smacallan	int default_depth, bitsperpixel, gid;
334a7fd8e5eSmacallan	const char *dev;
335a7fd8e5eSmacallan	char *mod = NULL;
336a7fd8e5eSmacallan	const char *reqSym = NULL;
337a7fd8e5eSmacallan	Gamma zeros = {0.0, 0.0, 0.0};
338a7fd8e5eSmacallan	DisplayModePtr mode;
339a7fd8e5eSmacallan	MessageType from;
340a7fd8e5eSmacallan	rgb rgbzeros = { 0, 0, 0 }, masks;
341a7fd8e5eSmacallan
342a7fd8e5eSmacallan	if (flags & PROBE_DETECT) return FALSE;
343a7fd8e5eSmacallan
344a7fd8e5eSmacallan	if (pScrn->numEntities != 1) return FALSE;
345a7fd8e5eSmacallan
346a7fd8e5eSmacallan	pScrn->monitor = pScrn->confScreen->monitor;
347a7fd8e5eSmacallan
348a7fd8e5eSmacallan	NGLEGetRec(pScrn);
349a7fd8e5eSmacallan	fPtr = NGLEPTR(pScrn);
350a7fd8e5eSmacallan
351a7fd8e5eSmacallan	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
352a7fd8e5eSmacallan
353a7fd8e5eSmacallan	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
354a7fd8e5eSmacallan	fPtr->fd = ngle_open(dev);
355a7fd8e5eSmacallan	if (fPtr->fd == -1) {
356a7fd8e5eSmacallan		return FALSE;
357a7fd8e5eSmacallan	}
358a7fd8e5eSmacallan
359a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_GET_FBINFO, &fPtr->fbi) == -1) {
360a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
361a7fd8e5eSmacallan			   "ioctl WSDISPLAY_GINFO: %s\n",
362a7fd8e5eSmacallan			   strerror(errno));
363a7fd8e5eSmacallan		return FALSE;
364a7fd8e5eSmacallan	}
365727c6de2Smacallan
366727c6de2Smacallan	if (ioctl(fPtr->fd, GCID, &gid) == -1)
367a7fd8e5eSmacallan		return FALSE;
368727c6de2Smacallan
369727c6de2Smacallan	fPtr->gid = gid;
370727c6de2Smacallan	fPtr->fbacc = 0;
371727c6de2Smacallan
372727c6de2Smacallan	switch (gid) {
373727c6de2Smacallan		case STI_DD_EG:
374bc460d0dSmacallan			fPtr->buf = BINapp0I;
375727c6de2Smacallan			fPtr->fbacc = BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, fPtr->buf, 0);
376727c6de2Smacallan			break;
377727c6de2Smacallan		case STI_DD_HCRX:
378727c6de2Smacallan			/* XXX BINovly if in 8 bit */
379727c6de2Smacallan			fPtr->buf = BINapp0F8;
380727c6de2Smacallan			fPtr->fbacc = BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, fPtr->buf, 0);
381ce159321Smacallan			/*
382ce159321Smacallan			 * XXX
383ce159321Smacallan			 * we don't know yet how much usable video memory we
384ce159321Smacallan			 * have but EXA gets cranky if there is no off screen
385ce159321Smacallan			 * memory at all, so we give it one line and cross
386ce159321Smacallan			 * fingers
387ce159321Smacallan			 */
388ce159321Smacallan			fPtr->fbi.fbi_fbsize += 8192;
389727c6de2Smacallan	break;
390a7fd8e5eSmacallan	}
391727c6de2Smacallan	xf86Msg(X_ERROR, "gid %08x fb access %08x\n", fPtr->gid, fPtr->fbacc);
392727c6de2Smacallan
393a7fd8e5eSmacallan	/* Handle depth */
394a7fd8e5eSmacallan	default_depth = fPtr->fbi.fbi_bitsperpixel <= 24 ? fPtr->fbi.fbi_bitsperpixel : 24;
395a7fd8e5eSmacallan	bitsperpixel = fPtr->fbi.fbi_bitsperpixel == 15 ? 16 : fPtr->fbi.fbi_bitsperpixel;
396a7fd8e5eSmacallan	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
397a7fd8e5eSmacallan		bitsperpixel,
398a7fd8e5eSmacallan		bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0))
399a7fd8e5eSmacallan		return FALSE;
400a7fd8e5eSmacallan
401a7fd8e5eSmacallan	xf86PrintDepthBpp(pScrn);
402a7fd8e5eSmacallan
403a7fd8e5eSmacallan	/* color weight */
404a7fd8e5eSmacallan	masks.red =   0x00ff0000;
405a7fd8e5eSmacallan	masks.green = 0x0000ff00;
406a7fd8e5eSmacallan	masks.blue =  0x000000ff;
407a7fd8e5eSmacallan	if (!xf86SetWeight(pScrn, rgbzeros, masks))
408a7fd8e5eSmacallan		return FALSE;
409a7fd8e5eSmacallan
410a7fd8e5eSmacallan	/* visual init */
411a7fd8e5eSmacallan	if (!xf86SetDefaultVisual(pScrn, -1))
412a7fd8e5eSmacallan		return FALSE;
413a7fd8e5eSmacallan
414a7fd8e5eSmacallan	/* We don't currently support DirectColor at > 8bpp */
415a7fd8e5eSmacallan	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
416a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
417a7fd8e5eSmacallan			   " (%s) is not supported at depth %d\n",
418a7fd8e5eSmacallan			   xf86GetVisualName(pScrn->defaultVisual),
419a7fd8e5eSmacallan			   pScrn->depth);
420a7fd8e5eSmacallan		return FALSE;
421a7fd8e5eSmacallan	}
422a7fd8e5eSmacallan
423a7fd8e5eSmacallan	xf86SetGamma(pScrn,zeros);
424a7fd8e5eSmacallan
425a7fd8e5eSmacallan	pScrn->progClock = TRUE;
426a7fd8e5eSmacallan	pScrn->rgbBits   = 8;
427a7fd8e5eSmacallan	pScrn->chipset   = "NGLE";
428a7fd8e5eSmacallan	fPtr->fbmem_len = pScrn->videoRam  = fPtr->fbi.fbi_fbsize;
429a7fd8e5eSmacallan
430a7fd8e5eSmacallan	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
431a7fd8e5eSmacallan		   pScrn->videoRam/1024);
432a7fd8e5eSmacallan
433a7fd8e5eSmacallan	/* handle options */
434a7fd8e5eSmacallan	xf86CollectOptions(pScrn, NULL);
435a7fd8e5eSmacallan	if (!(fPtr->Options = malloc(sizeof(NGLEOptions))))
436a7fd8e5eSmacallan		return FALSE;
437a7fd8e5eSmacallan	memcpy(fPtr->Options, NGLEOptions, sizeof(NGLEOptions));
438a7fd8e5eSmacallan	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
439a7fd8e5eSmacallan			   fPtr->Options);
440a7fd8e5eSmacallan
441a7fd8e5eSmacallan	/* fake video mode struct */
442a7fd8e5eSmacallan	mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec));
443a7fd8e5eSmacallan	mode->prev = mode;
444a7fd8e5eSmacallan	mode->next = mode;
445a7fd8e5eSmacallan	mode->name = "NGLE current mode";
446a7fd8e5eSmacallan	mode->status = MODE_OK;
447a7fd8e5eSmacallan	mode->type = M_T_BUILTIN;
448a7fd8e5eSmacallan	mode->Clock = 0;
449a7fd8e5eSmacallan	mode->HDisplay = fPtr->fbi.fbi_width;
450a7fd8e5eSmacallan	mode->HSyncStart = 0;
451a7fd8e5eSmacallan	mode->HSyncEnd = 0;
452a7fd8e5eSmacallan	mode->HTotal = 0;
453a7fd8e5eSmacallan	mode->HSkew = 0;
454a7fd8e5eSmacallan	mode->VDisplay = fPtr->fbi.fbi_height;
455a7fd8e5eSmacallan	mode->VSyncStart = 0;
456a7fd8e5eSmacallan	mode->VSyncEnd = 0;
457a7fd8e5eSmacallan	mode->VTotal = 0;
458a7fd8e5eSmacallan	mode->VScan = 0;
459a7fd8e5eSmacallan	mode->Flags = 0;
460a7fd8e5eSmacallan	if (pScrn->modes != NULL) {
461a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
462a7fd8e5eSmacallan		   "Ignoring mode specification from screen section\n");
463a7fd8e5eSmacallan	}
464a7fd8e5eSmacallan	pScrn->currentMode = pScrn->modes = mode;
465a7fd8e5eSmacallan	pScrn->virtualX = fPtr->fbi.fbi_width;
466a7fd8e5eSmacallan	pScrn->virtualY = fPtr->fbi.fbi_height;
467a7fd8e5eSmacallan	pScrn->displayWidth = 2048;
468a7fd8e5eSmacallan
469a7fd8e5eSmacallan	/* Set the display resolution */
470a7fd8e5eSmacallan	xf86SetDpi(pScrn, 0, 0);
471a7fd8e5eSmacallan
472a7fd8e5eSmacallan	from = X_DEFAULT;
473a7fd8e5eSmacallan	fPtr->HWCursor = TRUE;
474a7fd8e5eSmacallan	if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor))
475a7fd8e5eSmacallan		from = X_CONFIG;
476a7fd8e5eSmacallan	if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) {
477a7fd8e5eSmacallan		from = X_CONFIG;
478a7fd8e5eSmacallan		fPtr->HWCursor = FALSE;
479a7fd8e5eSmacallan	}
480a7fd8e5eSmacallan	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
481a7fd8e5eSmacallan		fPtr->HWCursor ? "HW" : "SW");
482a7fd8e5eSmacallan
483a7fd8e5eSmacallan	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
484a7fd8e5eSmacallan		NGLEFreeRec(pScrn);
485a7fd8e5eSmacallan		return FALSE;
486a7fd8e5eSmacallan	}
487a7fd8e5eSmacallan
488a7fd8e5eSmacallan	if (xf86LoadSubModule(pScrn, "exa") == NULL) {
489a7fd8e5eSmacallan		NGLEFreeRec(pScrn);
490a7fd8e5eSmacallan		return FALSE;
491a7fd8e5eSmacallan	}
492a7fd8e5eSmacallan
493a7fd8e5eSmacallan	if (xf86LoadSubModule(pScrn, "ramdac") == NULL) {
494a7fd8e5eSmacallan		NGLEFreeRec(pScrn);
495a7fd8e5eSmacallan		return FALSE;
496a7fd8e5eSmacallan	}
497a7fd8e5eSmacallan
498a7fd8e5eSmacallan	return TRUE;
499a7fd8e5eSmacallan}
500a7fd8e5eSmacallan
501a7fd8e5eSmacallanstatic Bool
502a7fd8e5eSmacallanNGLEScreenInit(SCREEN_INIT_ARGS_DECL)
503a7fd8e5eSmacallan{
504a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
505a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
506a7fd8e5eSmacallan	VisualPtr visual;
507a7fd8e5eSmacallan	int ret, flags, width, height, i, j;
508a7fd8e5eSmacallan	int wsmode = WSDISPLAYIO_MODE_MAPPED;
509a7fd8e5eSmacallan	size_t len;
510a7fd8e5eSmacallan
511a7fd8e5eSmacallan#ifdef NGLE_DEBUG
512a7fd8e5eSmacallan	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
513a7fd8e5eSmacallan	       "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
514a7fd8e5eSmacallan	       pScrn->bitsPerPixel,
515a7fd8e5eSmacallan	       pScrn->depth,
516a7fd8e5eSmacallan	       xf86GetVisualName(pScrn->defaultVisual),
517a7fd8e5eSmacallan	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
518a7fd8e5eSmacallan	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
519a7fd8e5eSmacallan#endif
520a7fd8e5eSmacallan
521a7fd8e5eSmacallan	/* Switch to graphics mode - required before mmap */
522a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
523a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
524a7fd8e5eSmacallan			   "ioctl WSDISPLAYIO_SMODE: %s\n",
525a7fd8e5eSmacallan			   strerror(errno));
526a7fd8e5eSmacallan		return FALSE;
527a7fd8e5eSmacallan	}
528727c6de2Smacallan	fPtr->regs = ngle_mmap(0x400000, 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) {
598727c6de2Smacallan		NGLEInitAccel(pScreen);
599727c6de2Smacallan		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using acceleration\n");
600a7fd8e5eSmacallan	}
601a7fd8e5eSmacallan
602a7fd8e5eSmacallan	/* software cursor */
603a7fd8e5eSmacallan	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
604a7fd8e5eSmacallan
605a7fd8e5eSmacallan	/* check for hardware cursor support */
606a7fd8e5eSmacallan	NGLESetupCursor(pScreen);
607a7fd8e5eSmacallan
608a7fd8e5eSmacallan	/* colormap */
609a7fd8e5eSmacallan	if (!miCreateDefColormap(pScreen))
610a7fd8e5eSmacallan		return FALSE;
611a7fd8e5eSmacallan
612a7fd8e5eSmacallan	flags = CMAP_RELOAD_ON_MODE_SWITCH;
613a7fd8e5eSmacallan	if(!xf86HandleColormaps(pScreen, 256, 8, NGLELoadPalette,
614a7fd8e5eSmacallan				NULL, flags))
615a7fd8e5eSmacallan		return FALSE;
616a7fd8e5eSmacallan
617a7fd8e5eSmacallan	pScreen->SaveScreen = NGLESaveScreen;
618a7fd8e5eSmacallan
619a7fd8e5eSmacallan#ifdef XvExtension
620a7fd8e5eSmacallan	{
621a7fd8e5eSmacallan		XF86VideoAdaptorPtr *ptr;
622a7fd8e5eSmacallan
623a7fd8e5eSmacallan		int n = xf86XVListGenericAdaptors(pScrn,&ptr);
624a7fd8e5eSmacallan		if (n) {
625a7fd8e5eSmacallan			xf86XVScreenInit(pScreen,ptr,n);
626a7fd8e5eSmacallan		}
627a7fd8e5eSmacallan	}
628a7fd8e5eSmacallan#endif
629a7fd8e5eSmacallan
630a7fd8e5eSmacallan	/* Wrap the current CloseScreen function */
631a7fd8e5eSmacallan	fPtr->CloseScreen = pScreen->CloseScreen;
632a7fd8e5eSmacallan	pScreen->CloseScreen = NGLECloseScreen;
633a7fd8e5eSmacallan
634a7fd8e5eSmacallan	return TRUE;
635a7fd8e5eSmacallan}
636a7fd8e5eSmacallan
637a7fd8e5eSmacallanstatic Bool
638a7fd8e5eSmacallanNGLECloseScreen(CLOSE_SCREEN_ARGS_DECL)
639a7fd8e5eSmacallan{
640a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
641a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
642a7fd8e5eSmacallan
643a7fd8e5eSmacallan	if (pScrn->vtSema) {
644a7fd8e5eSmacallan		NGLERestore(pScrn);
645a7fd8e5eSmacallan		if (munmap(fPtr->regs, 0x40000) == -1) {
646a7fd8e5eSmacallan			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
647a7fd8e5eSmacallan				   "munmap engine: %s\n", strerror(errno));
648a7fd8e5eSmacallan		}
649a7fd8e5eSmacallan
650a7fd8e5eSmacallan		if (munmap(fPtr->fbmem, fPtr->fbmem_len) == -1) {
651a7fd8e5eSmacallan			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
652a7fd8e5eSmacallan				   "munmap fb: %s\n", strerror(errno));
653a7fd8e5eSmacallan		}
654a7fd8e5eSmacallan
655a7fd8e5eSmacallan		fPtr->regs = NULL;
656a7fd8e5eSmacallan		fPtr->fbmem = NULL;
657a7fd8e5eSmacallan	}
658a7fd8e5eSmacallan	pScrn->vtSema = FALSE;
659a7fd8e5eSmacallan
660a7fd8e5eSmacallan	/* unwrap CloseScreen */
661a7fd8e5eSmacallan	pScreen->CloseScreen = fPtr->CloseScreen;
662a7fd8e5eSmacallan	return (*pScreen->CloseScreen)(pScreen);
663a7fd8e5eSmacallan}
664a7fd8e5eSmacallan
665a7fd8e5eSmacallanstatic Bool
666a7fd8e5eSmacallanNGLEEnterVT(VT_FUNC_ARGS_DECL)
667a7fd8e5eSmacallan{
668a7fd8e5eSmacallan	SCRN_INFO_PTR(arg);
669a7fd8e5eSmacallan
670a7fd8e5eSmacallan	pScrn->vtSema = TRUE;
671a7fd8e5eSmacallan	return TRUE;
672a7fd8e5eSmacallan}
673a7fd8e5eSmacallan
674a7fd8e5eSmacallanstatic void
675a7fd8e5eSmacallanNGLELeaveVT(VT_FUNC_ARGS_DECL)
676a7fd8e5eSmacallan{
677a7fd8e5eSmacallan}
678a7fd8e5eSmacallan
679a7fd8e5eSmacallanstatic Bool
680a7fd8e5eSmacallanNGLESwitchMode(SWITCH_MODE_ARGS_DECL)
681a7fd8e5eSmacallan{
682a7fd8e5eSmacallan
683a7fd8e5eSmacallan	/* Nothing else to do */
684a7fd8e5eSmacallan	return TRUE;
685a7fd8e5eSmacallan}
686a7fd8e5eSmacallan
687a7fd8e5eSmacallanstatic int
688a7fd8e5eSmacallanNGLEValidMode(SCRN_ARG_TYPE, DisplayModePtr mode, Bool verbose, int flags)
689a7fd8e5eSmacallan{
690a7fd8e5eSmacallan
691a7fd8e5eSmacallan	return MODE_OK;
692a7fd8e5eSmacallan}
693a7fd8e5eSmacallan
694a7fd8e5eSmacallanstatic void
695a7fd8e5eSmacallanNGLELoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
696a7fd8e5eSmacallan	       LOCO *colors, VisualPtr pVisual)
697a7fd8e5eSmacallan{
698a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
699a7fd8e5eSmacallan	struct wsdisplay_cmap cmap;
700a7fd8e5eSmacallan	unsigned char red[256],green[256],blue[256];
701a7fd8e5eSmacallan	int i, indexMin=256, indexMax=0;
702a7fd8e5eSmacallan
703a7fd8e5eSmacallan	/* nothing to do if there is no color palette support */
704a7fd8e5eSmacallan	if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0)
705a7fd8e5eSmacallan		return;
706a7fd8e5eSmacallan
707a7fd8e5eSmacallan	cmap.count   = 1;
708a7fd8e5eSmacallan	cmap.red   = red;
709a7fd8e5eSmacallan	cmap.green = green;
710a7fd8e5eSmacallan	cmap.blue  = blue;
711a7fd8e5eSmacallan
712a7fd8e5eSmacallan	if (numColors == 1) {
713a7fd8e5eSmacallan		/* Optimisation */
714a7fd8e5eSmacallan		cmap.index = indices[0];
715a7fd8e5eSmacallan		red[0]   = colors[indices[0]].red;
716a7fd8e5eSmacallan		green[0] = colors[indices[0]].green;
717a7fd8e5eSmacallan		blue[0]  = colors[indices[0]].blue;
718a7fd8e5eSmacallan		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
719a7fd8e5eSmacallan			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
720a7fd8e5eSmacallan	} else {
721a7fd8e5eSmacallan		/*
722a7fd8e5eSmacallan		 * Change all colors in 2 ioctls
723a7fd8e5eSmacallan		 * and limit the data to be transferred.
724a7fd8e5eSmacallan		 */
725a7fd8e5eSmacallan		for (i = 0; i < numColors; i++) {
726a7fd8e5eSmacallan			if (indices[i] < indexMin)
727a7fd8e5eSmacallan				indexMin = indices[i];
728a7fd8e5eSmacallan			if (indices[i] > indexMax)
729a7fd8e5eSmacallan				indexMax = indices[i];
730a7fd8e5eSmacallan		}
731a7fd8e5eSmacallan		cmap.index = indexMin;
732a7fd8e5eSmacallan		cmap.count = indexMax - indexMin + 1;
733a7fd8e5eSmacallan		cmap.red = &red[indexMin];
734a7fd8e5eSmacallan		cmap.green = &green[indexMin];
735a7fd8e5eSmacallan		cmap.blue = &blue[indexMin];
736a7fd8e5eSmacallan		/* Get current map. */
737a7fd8e5eSmacallan		if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1)
738a7fd8e5eSmacallan			ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno));
739a7fd8e5eSmacallan		/* Change the colors that require updating. */
740a7fd8e5eSmacallan		for (i = 0; i < numColors; i++) {
741a7fd8e5eSmacallan			red[indices[i]]   = colors[indices[i]].red;
742a7fd8e5eSmacallan			green[indices[i]] = colors[indices[i]].green;
743a7fd8e5eSmacallan			blue[indices[i]]  = colors[indices[i]].blue;
744a7fd8e5eSmacallan		}
745a7fd8e5eSmacallan		/* Write the colormap back. */
746a7fd8e5eSmacallan		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
747a7fd8e5eSmacallan			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
748a7fd8e5eSmacallan	}
749f8e8ce30Smacallan	fPtr->hwmode = -1;
750a7fd8e5eSmacallan}
751a7fd8e5eSmacallan
752a7fd8e5eSmacallanstatic Bool
753a7fd8e5eSmacallanNGLESaveScreen(ScreenPtr pScreen, int mode)
754a7fd8e5eSmacallan{
755a7fd8e5eSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
756a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
757a7fd8e5eSmacallan	int state;
758a7fd8e5eSmacallan
759a7fd8e5eSmacallan	if (!pScrn->vtSema)
760a7fd8e5eSmacallan		return TRUE;
761a7fd8e5eSmacallan
762a7fd8e5eSmacallan	if (mode != SCREEN_SAVER_FORCER) {
763a7fd8e5eSmacallan		state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON:
764a7fd8e5eSmacallan		                            WSDISPLAYIO_VIDEO_OFF;
765a7fd8e5eSmacallan		ioctl(fPtr->fd,
766a7fd8e5eSmacallan		      WSDISPLAYIO_SVIDEO, &state);
767a7fd8e5eSmacallan	}
768a7fd8e5eSmacallan	return TRUE;
769a7fd8e5eSmacallan}
770a7fd8e5eSmacallan
771a7fd8e5eSmacallan
772a7fd8e5eSmacallanstatic void
773a7fd8e5eSmacallanNGLESave(ScrnInfoPtr pScrn)
774a7fd8e5eSmacallan{
775a7fd8e5eSmacallan}
776a7fd8e5eSmacallan
777a7fd8e5eSmacallanstatic void
778a7fd8e5eSmacallanNGLERestore(ScrnInfoPtr pScrn)
779a7fd8e5eSmacallan{
780a7fd8e5eSmacallan	NGLEPtr fPtr = NGLEPTR(pScrn);
781a7fd8e5eSmacallan	int mode;
782a7fd8e5eSmacallan
783a7fd8e5eSmacallan	/* Restore the text mode */
784a7fd8e5eSmacallan	mode = WSDISPLAYIO_MODE_EMUL;
785a7fd8e5eSmacallan	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
786a7fd8e5eSmacallan		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
787a7fd8e5eSmacallan			   "error setting text mode %s\n", strerror(errno));
788a7fd8e5eSmacallan	}
789a7fd8e5eSmacallan}
790