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