crime_driver.c revision e1ea03a3
1/* $NetBSD: crime_driver.c,v 1.1 2008/11/06 22:06:47 macallan Exp $ */
2/*
3 * Copyright (c) 2008 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 the CRIME rendering engine foundin SGI O2 workstations */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include <fcntl.h>
39#include <sys/types.h>
40#include <sys/time.h>
41#include <dev/wscons/wsconsio.h>
42
43/* all driver need this */
44#include "xf86.h"
45#include "xf86_OSproc.h"
46#include "xf86_ansic.h"
47
48#include "mipointer.h"
49#include "mibstore.h"
50#include "micmap.h"
51#include "colormapst.h"
52#include "xf86cmap.h"
53
54/* for visuals */
55#include "xf1bpp.h"
56#include "xf4bpp.h"
57#include "fb.h"
58
59#include "xf86Resources.h"
60#include "xf86RAC.h"
61
62#ifdef XvExtension
63#include "xf86xv.h"
64#endif
65
66#include "crime.h"
67
68/* #include "wsconsio.h" */
69
70#ifndef XFree86LOADER
71#include <sys/mman.h>
72#endif
73
74#define CRIME_DEFAULT_DEV "/dev/ttyE0"
75
76#define DEBUG 1
77#ifndef DEBUG
78#define DEBUG 0
79#endif
80
81/* Prototypes */
82#ifdef XFree86LOADER
83static pointer CrimeSetup(pointer, pointer, int *, int *);
84#endif
85static Bool CrimeGetRec(ScrnInfoPtr);
86static void CrimeFreeRec(ScrnInfoPtr);
87static const OptionInfoRec * CrimeAvailableOptions(int, int);
88static void CrimeIdentify(int);
89static Bool CrimeProbe(DriverPtr, int);
90static Bool CrimePreInit(ScrnInfoPtr, int);
91static Bool CrimeScreenInit(int, ScreenPtr, int, char **);
92static Bool CrimeCloseScreen(int, ScreenPtr);
93static Bool CrimeEnterVT(int, int);
94static void CrimeLeaveVT(int, int);
95static Bool CrimeSwitchMode(int, DisplayModePtr, int);
96static int CrimeValidMode(int, DisplayModePtr, Bool, int);
97static void CrimeLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
98static Bool CrimeSaveScreen(ScreenPtr, int);
99static void CrimeSave(ScrnInfoPtr);
100static void CrimeRestore(ScrnInfoPtr);
101
102/* helper functions */
103static int crime_open(char *);
104static pointer crime_mmap(size_t, off_t, int, int);
105
106/*
107 * This is intentionally screen-independent.  It indicates the binding
108 * choice made in the first PreInit.
109 */
110static int pix24bpp = 0;
111
112#define VERSION			4000
113#define CRIME_NAME		"crime"
114#define CRIME_DRIVER_NAME	"crime"
115#define CRIME_MAJOR_VERSION	0
116#define CRIME_MINOR_VERSION	1
117
118DriverRec CRIME = {
119	VERSION,
120	CRIME_DRIVER_NAME,
121	CrimeIdentify,
122	CrimeProbe,
123	CrimeAvailableOptions,
124	NULL,
125	0
126};
127
128/* Supported "chipsets" */
129static SymTabRec CrimeChipsets[] = {
130	{ 0, "crime" },
131	{ -1, NULL }
132};
133
134/* Supported options */
135typedef enum {
136	OPTION_HW_CURSOR,
137	OPTION_SW_CURSOR
138} CrimeOpts;
139
140static const OptionInfoRec CrimeOptions[] = {
141	{ OPTION_SW_CURSOR, "SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
142	{ OPTION_HW_CURSOR, "HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
143	{ -1, NULL, OPTV_NONE, {0}, FALSE}
144};
145
146/* Symbols needed from other modules */
147static const char *fbSymbols[] = {
148	"fbPictureInit",
149	"fbScreenInit",
150	NULL
151};
152
153static const char *xaaSymbols[] =
154{
155    "XAACreateInfoRec",
156    "XAADestroyInfoRec",
157    "XAAInit",
158    "XAAScreenIndex",
159    NULL
160};
161
162static const char *ramdacSymbols[] = {
163	"xf86CreateCursorInfoRec",
164	"xf86DestroyCursorInfoRec",
165	"xf86InitCursor",
166	NULL
167};
168
169#ifdef XFree86LOADER
170static XF86ModuleVersionInfo CrimeVersRec = {
171	"crime",
172	MODULEVENDORSTRING,
173	MODINFOSTRING1,
174	MODINFOSTRING2,
175	XORG_VERSION_CURRENT,
176	CRIME_MAJOR_VERSION, CRIME_MINOR_VERSION, 0,
177	ABI_CLASS_VIDEODRV,
178	ABI_VIDEODRV_VERSION,
179	NULL,
180	{0, 0, 0, 0}
181};
182
183_X_EXPORT XF86ModuleData crimeModuleData = { &CrimeVersRec, CrimeSetup, NULL };
184
185static pointer
186CrimeSetup(pointer module, pointer opts, int *errmaj, int *errmin)
187{
188	static Bool setupDone = FALSE;
189	const char *osname;
190
191	/* Check that we're being loaded on a OpenBSD or NetBSD system */
192	LoaderGetOS(&osname, NULL, NULL, NULL);
193	if (!osname
194	    && (strcmp(osname, "netbsd") != 0)) {
195		if (errmaj)
196			*errmaj = LDR_BADOS;
197		if (errmin)
198			*errmin = 0;
199		return NULL;
200	}
201	if (!setupDone) {
202		setupDone = TRUE;
203		xf86AddDriver(&CRIME, module, 0);
204		LoaderRefSymLists(xaaSymbols, fbSymbols, NULL);
205		return (pointer)1;
206	} else {
207		if (errmaj != NULL)
208			*errmaj = LDR_ONCEONLY;
209		return NULL;
210	}
211}
212#endif /* XFree86LOADER */
213
214static Bool
215CrimeGetRec(ScrnInfoPtr pScrn)
216{
217
218	if (pScrn->driverPrivate != NULL)
219		return TRUE;
220
221	pScrn->driverPrivate = xnfcalloc(sizeof(CrimeRec), 1);
222	return TRUE;
223}
224
225static void
226CrimeFreeRec(ScrnInfoPtr pScrn)
227{
228
229	if (pScrn->driverPrivate == NULL)
230		return;
231	xfree(pScrn->driverPrivate);
232	pScrn->driverPrivate = NULL;
233}
234
235static const OptionInfoRec *
236CrimeAvailableOptions(int chipid, int busid)
237{
238	return CrimeOptions;
239}
240
241static void
242CrimeIdentify(int flags)
243{
244	xf86PrintChipsets(CRIME_NAME, "driver for CRIME framebuffer",
245			  CrimeChipsets);
246}
247
248
249#define priv_open_device(n)	open(n,O_RDWR|O_NONBLOCK|O_EXCL)
250
251/* Open the framebuffer device */
252static int
253crime_open(char *dev)
254{
255	int fd = -1;
256
257	/* try argument from XF86Config first */
258	if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
259		/* second: environment variable */
260		dev = getenv("XDEVICE");
261		if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
262			/* last try: default device */
263			dev = CRIME_DEFAULT_DEV;
264			if ((fd = priv_open_device(dev)) == -1) {
265				return -1;
266			}
267		}
268	}
269	return fd;
270}
271
272/* Map the framebuffer's memory */
273static pointer
274crime_mmap(size_t len, off_t off, int fd, int ro)
275{
276	pointer mapaddr;
277
278	/*
279	 * try and make it private first, that way once we get it, an
280	 * interloper, e.g. another server, can't get this frame buffer,
281	 * and if another server already has it, this one won't.
282	 */
283	if (ro) {
284		mapaddr = (pointer) mmap(NULL, len,
285					 PROT_READ, MAP_SHARED,
286					 fd, off);
287	} else {
288		mapaddr = (pointer) mmap(NULL, len,
289					 PROT_READ | PROT_WRITE, MAP_SHARED,
290					 fd, off);
291	}
292	if (mapaddr == (pointer) -1) {
293		mapaddr = NULL;
294	}
295#if DEBUG
296	ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, len);
297#endif
298	return mapaddr;
299}
300
301static Bool
302CrimeProbe(DriverPtr drv, int flags)
303{
304	ScrnInfoPtr pScrn = NULL;
305	int i, fd, entity, wstype;
306       	GDevPtr *devSections;
307	int numDevSections;
308	char *dev;
309	Bool foundScreen = FALSE;
310
311	xf86Msg(X_ERROR, "%s\n", __func__);
312
313	if ((numDevSections = xf86MatchDevice(CRIME_DRIVER_NAME,
314					      &devSections)) <= 0)
315		return FALSE;
316
317
318	if ((fd = crime_open(CRIME_DEFAULT_DEV)) == 0)
319		return FALSE;
320	xf86Msg(X_ERROR, "%s: fd found\n", __func__);
321
322	if (ioctl(fd, WSDISPLAYIO_GTYPE, &wstype) == -1)
323		return FALSE;
324	xf86Msg(X_ERROR, "%s: type: %d\n", __func__, wstype);
325	if (wstype != WSDISPLAY_TYPE_CRIME)
326		return FALSE;
327
328	xf86Msg(X_ERROR, "%s: CRIME found\n", __func__);
329
330	if (flags & PROBE_DETECT)
331		return TRUE;
332
333	/* ok, at this point we know we've got a CRIME */
334	for (i = 0; i < numDevSections; i++) {
335
336		dev = xf86FindOptionValue(devSections[i]->options, "device");
337		if ((fd = crime_open(dev)) >= 0) {
338			entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
339			pScrn = xf86ConfigFbEntity(NULL,0,entity,
340						   NULL,NULL,NULL,NULL);
341			if (pScrn != NULL) {
342				foundScreen = TRUE;
343				pScrn->driverVersion = VERSION;
344				pScrn->driverName = CRIME_DRIVER_NAME;
345				pScrn->name = CRIME_NAME;
346				pScrn->Probe = CrimeProbe;
347				pScrn->PreInit = CrimePreInit;
348				pScrn->ScreenInit = CrimeScreenInit;
349				pScrn->SwitchMode = CrimeSwitchMode;
350				pScrn->AdjustFrame = NULL;
351				pScrn->EnterVT = CrimeEnterVT;
352				pScrn->LeaveVT = CrimeLeaveVT;
353				pScrn->ValidMode = CrimeValidMode;
354
355				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
356				    "using %s\n", dev != NULL ? dev :
357				    "default device");
358			}
359		}
360	}
361	xfree(devSections);
362	return foundScreen;
363}
364
365static Bool
366CrimePreInit(ScrnInfoPtr pScrn, int flags)
367{
368	CrimePtr fPtr;
369	int default_depth, wstype;
370	char *dev;
371	char *mod = NULL;
372	const char *reqSym = NULL;
373	Gamma zeros = {0.0, 0.0, 0.0};
374	DisplayModePtr mode;
375	MessageType from;
376	rgb rgbzeros = { 0, 0, 0 }, masks;
377
378	if (flags & PROBE_DETECT) return FALSE;
379
380	if (pScrn->numEntities != 1) return FALSE;
381
382	pScrn->monitor = pScrn->confScreen->monitor;
383
384	CrimeGetRec(pScrn);
385	fPtr = CRIMEPTR(pScrn);
386
387	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
388
389	pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
390	pScrn->racIoFlags = pScrn->racMemFlags;
391
392	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
393	fPtr->fd = crime_open(dev);
394	if (fPtr->fd == -1) {
395		return FALSE;
396	}
397
398	if (ioctl(fPtr->fd, WSDISPLAYIO_GINFO, &fPtr->info) == -1) {
399		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
400			   "ioctl WSDISPLAY_GINFO: %s\n",
401			   strerror(errno));
402		return FALSE;
403	}
404	if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) {
405		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
406			   "ioctl WSDISPLAY_GTYPE: %s\n",
407			   strerror(errno));
408		return FALSE;
409	}
410
411	/* Handle depth */
412	default_depth = fPtr->info.depth <= 24 ? fPtr->info.depth : 24;
413	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
414			     fPtr->info.depth, Support24bppFb|Support32bppFb))
415		return FALSE;
416	xf86PrintDepthBpp(pScrn);
417
418	/* Get the depth24 pixmap format */
419	if (pScrn->depth == 24 && pix24bpp == 0)
420		pix24bpp = xf86GetBppFromDepth(pScrn, 24);
421
422	/* color weight */
423	masks.red =   0x00ff0000;
424	masks.green = 0x0000ff00;
425	masks.blue =  0x000000ff;
426	if (!xf86SetWeight(pScrn, rgbzeros, masks))
427		return FALSE;
428
429	/* visual init */
430	if (!xf86SetDefaultVisual(pScrn, -1))
431		return FALSE;
432
433	/* We don't currently support DirectColor at > 8bpp */
434	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
435		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
436			   " (%s) is not supported at depth %d\n",
437			   xf86GetVisualName(pScrn->defaultVisual),
438			   pScrn->depth);
439		return FALSE;
440	}
441
442	xf86SetGamma(pScrn,zeros);
443
444	pScrn->progClock = TRUE;
445	pScrn->rgbBits   = 8;
446	pScrn->chipset   = "crime";
447	pScrn->videoRam  = fPtr->info.width * 4 * 2048;
448
449	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
450		   pScrn->videoRam/1024);
451
452	/* handle options */
453	xf86CollectOptions(pScrn, NULL);
454	if (!(fPtr->Options = xalloc(sizeof(CrimeOptions))))
455		return FALSE;
456	memcpy(fPtr->Options, CrimeOptions, sizeof(CrimeOptions));
457	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
458			   fPtr->Options);
459
460	/* fake video mode struct */
461	mode = (DisplayModePtr)xalloc(sizeof(DisplayModeRec));
462	mode->prev = mode;
463	mode->next = mode;
464	mode->name = "crime current mode";
465	mode->status = MODE_OK;
466	mode->type = M_T_BUILTIN;
467	mode->Clock = 0;
468	mode->HDisplay = fPtr->info.width;
469	mode->HSyncStart = 0;
470	mode->HSyncEnd = 0;
471	mode->HTotal = 0;
472	mode->HSkew = 0;
473	mode->VDisplay = fPtr->info.height;
474	mode->VSyncStart = 0;
475	mode->VSyncEnd = 0;
476	mode->VTotal = 0;
477	mode->VScan = 0;
478	mode->Flags = 0;
479	if (pScrn->modes != NULL) {
480		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
481		   "Ignoring mode specification from screen section\n");
482	}
483	pScrn->currentMode = pScrn->modes = mode;
484	pScrn->virtualX = fPtr->info.width;
485	pScrn->virtualY = fPtr->info.height;
486	pScrn->displayWidth = pScrn->virtualX;
487
488	/* Set the display resolution */
489	xf86SetDpi(pScrn, 0, 0);
490
491	from = X_DEFAULT;
492	fPtr->HWCursor = TRUE;
493	if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor))
494		from = X_CONFIG;
495	if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) {
496		from = X_CONFIG;
497		fPtr->HWCursor = FALSE;
498	}
499	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
500		fPtr->HWCursor ? "HW" : "SW");
501
502	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
503		CrimeFreeRec(pScrn);
504		return FALSE;
505	}
506	xf86LoaderReqSymLists(fbSymbols, NULL);
507
508	if (xf86LoadSubModule(pScrn, "xaa") == NULL) {
509		PnozzFreeRec(pScrn);
510		return FALSE;
511	}
512	xf86LoaderReqSymLists(xaaSymbols, NULL);
513
514	if (xf86LoadSubModule(pScrn, "ramdac") == NULL) {
515		CrimeFreeRec(pScrn);
516		return FALSE;
517	}
518	xf86LoaderReqSymLists(ramdacSymbols, NULL);
519
520	return TRUE;
521}
522
523static Bool
524CrimeScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
525{
526	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
527	CrimePtr fPtr = CRIMEPTR(pScrn);
528	VisualPtr visual;
529	int ret, flags, width, height, i, j;
530	int wsmode = WSDISPLAYIO_MODE_DUMBFB;
531	size_t len;
532
533#if DEBUG
534	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
535	       "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
536	       pScrn->bitsPerPixel,
537	       pScrn->depth,
538	       xf86GetVisualName(pScrn->defaultVisual),
539	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
540	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
541#endif
542
543	/* Switch to graphics mode - required before mmap */
544	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
545		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
546			   "ioctl WSDISPLAYIO_SMODE: %s\n",
547			   strerror(errno));
548		return FALSE;
549	}
550	fPtr->engine = crime_mmap(0x5000, 0x15000000, fPtr->fd, 0);
551
552	if (fPtr->engine == NULL) {
553		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
554			   "crime_mmap engine: %s\n", strerror(errno));
555		return FALSE;
556	}
557
558	fPtr->linear = crime_mmap(0x10000, 0x15010000, fPtr->fd, 0);
559	if (fPtr->linear == NULL) {
560		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
561			   "crime_mmap linear: %s\n", strerror(errno));
562		return FALSE;
563	}
564
565	memset(fPtr->linear, 0, 0x10000);
566	fPtr->fb = crime_mmap(8192 * fPtr->info.width, 0, fPtr->fd, 1);
567	if (fPtr->fb == NULL) {
568		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
569			   "crime_mmap fb: %s\n", strerror(errno));
570		return FALSE;
571	}
572
573if (0) {
574	for (i = 0x2000; i < 0x4000; i+= 16) {
575		for (j = 0; j < 16; j += 4) {
576			xf86Msg(X_ERROR, "%08x ",
577			    *(CARD32 *)(fPtr->engine + i + j));
578		}
579		xf86Msg(X_ERROR, "\n");
580	}
581}
582	CrimeSave(pScrn);
583	pScrn->vtSema = TRUE;
584
585	/* mi layer */
586	miClearVisualTypes();
587	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
588			      pScrn->rgbBits, TrueColor))
589		return FALSE;
590
591	if (!miSetPixmapDepths())
592		return FALSE;
593
594	height = pScrn->virtualY;
595	width = pScrn->virtualX;
596
597#if 1
598	ret = fbScreenInit(pScreen,
599			   fPtr->fb,
600			   width, height,
601			   pScrn->xDpi, pScrn->yDpi,
602			   pScrn->displayWidth,
603			   pScrn->bitsPerPixel);
604
605	if (!ret)
606		return FALSE;
607#endif
608#if 1
609	/* Fixup RGB ordering */
610	visual = pScreen->visuals + pScreen->numVisuals;
611	while (--visual >= pScreen->visuals) {
612		if ((visual->class | DynamicClass) == DirectColor) {
613			visual->offsetRed   = pScrn->offset.red;
614			visual->offsetGreen = pScrn->offset.green;
615			visual->offsetBlue  = pScrn->offset.blue;
616			visual->redMask     = pScrn->mask.red;
617			visual->greenMask   = pScrn->mask.green;
618			visual->blueMask    = pScrn->mask.blue;
619			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
620			    "%d %d %d %08x %08x %08x\n",
621			    visual->offsetRed, visual->offsetGreen,
622			    visual->offsetBlue, visual->redMask,
623			    visual->greenMask, visual->blueMask);
624		}
625	}
626#endif
627#if 1
628	if (!fbPictureInit(pScreen, NULL, 0))
629		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
630			   "RENDER extension initialisation failed.");
631#endif
632	xf86SetBlackWhitePixels(pScreen);
633	miInitializeBackingStore(pScreen);
634	xf86SetBackingStore(pScreen);
635
636	if (fPtr) {
637		BoxRec bx;
638		fPtr->pXAA = XAACreateInfoRec();
639		CrimeAccelInit(pScrn);
640		bx.x1 = bx.y1 = 0;
641		bx.x2 = fPtr->info.width;
642		bx.y2 = 2048;
643		xf86InitFBManager(pScreen, &bx);
644		if(!XAAInit(pScreen, fPtr->pXAA))
645			return FALSE;
646		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using acceleration\n");
647	}
648
649	/* software cursor */
650	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
651
652	/* check for hardware cursor support */
653	CrimeSetupCursor(pScreen);
654
655	/* colormap */
656	if (!miCreateDefColormap(pScreen))
657		return FALSE;
658		flags = CMAP_RELOAD_ON_MODE_SWITCH;
659	if(!xf86HandleColormaps(pScreen, 256, 8, CrimeLoadPalette,
660				NULL, flags))
661		return FALSE;
662
663	pScreen->SaveScreen = CrimeSaveScreen;
664
665#ifdef XvExtension
666	{
667		XF86VideoAdaptorPtr *ptr;
668
669		int n = xf86XVListGenericAdaptors(pScrn,&ptr);
670		if (n) {
671			xf86XVScreenInit(pScreen,ptr,n);
672		}
673	}
674#endif
675
676	/* Wrap the current CloseScreen function */
677	fPtr->CloseScreen = pScreen->CloseScreen;
678	pScreen->CloseScreen = CrimeCloseScreen;
679
680	return TRUE;
681}
682
683static Bool
684CrimeCloseScreen(int scrnIndex, ScreenPtr pScreen)
685{
686	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
687	CrimePtr fPtr = CRIMEPTR(pScrn);
688
689	if (pScrn->vtSema) {
690		CrimeRestore(pScrn);
691		if (munmap(fPtr->engine, 0x5000) == -1) {
692			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
693				   "munmap engine: %s\n", strerror(errno));
694		}
695
696		if (munmap(fPtr->linear, 0x10000) == -1) {
697			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
698				   "munmap linear: %s\n", strerror(errno));
699		}
700
701		fPtr->engine = NULL;
702		fPtr->linear = NULL;
703	}
704	pScrn->vtSema = FALSE;
705
706	/* unwrap CloseScreen */
707	pScreen->CloseScreen = fPtr->CloseScreen;
708	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
709}
710
711static Bool
712CrimeEnterVT(int scrnIndex, int flags)
713{
714	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
715
716	pScrn->vtSema = TRUE;
717	return TRUE;
718}
719
720static void
721CrimeLeaveVT(int scrnIndex, int flags)
722{
723}
724
725static Bool
726CrimeSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
727{
728#if DEBUG
729	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
730#endif
731
732	/* Nothing else to do */
733	return TRUE;
734}
735
736static int
737CrimeValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
738{
739#if DEBUG
740	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
741#endif
742
743	return MODE_OK;
744}
745
746static void
747CrimeLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
748	       LOCO *colors, VisualPtr pVisual)
749{
750	CrimePtr fPtr = CRIMEPTR(pScrn);
751	struct wsdisplay_cmap cmap;
752	unsigned char red[256],green[256],blue[256];
753	int i, indexMin=256, indexMax=0;
754
755	cmap.count   = 1;
756	cmap.red   = red;
757	cmap.green = green;
758	cmap.blue  = blue;
759
760	if (numColors == 1) {
761		/* Optimisation */
762		cmap.index = indices[0];
763		red[0]   = colors[indices[0]].red;
764		green[0] = colors[indices[0]].green;
765		blue[0]  = colors[indices[0]].blue;
766		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
767			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
768	} else {
769		/* Change all colors in 2 syscalls */
770		/* and limit the data to be transfered */
771		for (i = 0; i < numColors; i++) {
772			if (indices[i] < indexMin)
773				indexMin = indices[i];
774			if (indices[i] > indexMax)
775				indexMax = indices[i];
776		}
777		cmap.index = indexMin;
778		cmap.count = indexMax - indexMin + 1;
779		cmap.red = &red[indexMin];
780		cmap.green = &green[indexMin];
781		cmap.blue = &blue[indexMin];
782		/* Get current map */
783		if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1)
784			ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno));
785		/* Change the colors that require updating */
786		for (i = 0; i < numColors; i++) {
787			red[indices[i]]   = colors[indices[i]].red;
788			green[indices[i]] = colors[indices[i]].green;
789			blue[indices[i]]  = colors[indices[i]].blue;
790		}
791		/* Write the colormap back */
792		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
793			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
794	}
795}
796
797static Bool
798CrimeSaveScreen(ScreenPtr pScreen, int mode)
799{
800	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
801	CrimePtr fPtr = CRIMEPTR(pScrn);
802	int state;
803
804	if (!pScrn->vtSema)
805		return TRUE;
806
807	if (mode != SCREEN_SAVER_FORCER) {
808		state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON:
809		                            WSDISPLAYIO_VIDEO_OFF;
810		ioctl(fPtr->fd,
811		      WSDISPLAYIO_SVIDEO, &state);
812	}
813	return TRUE;
814}
815
816
817static void
818CrimeSave(ScrnInfoPtr pScrn)
819{
820}
821
822static void
823CrimeRestore(ScrnInfoPtr pScrn)
824{
825	CrimePtr fPtr = CRIMEPTR(pScrn);
826	int mode;
827
828	/* Restore the text mode */
829	mode = WSDISPLAYIO_MODE_EMUL;
830	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
831		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
832			   "error setting text mode %s\n", strerror(errno));
833	}
834}
835