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