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