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