igs_driver.c revision 5683c28b
1/* $OpenBSD: wsfb_driver.c,v 1.19 2003/04/27 16:42:32 matthieu Exp $ */
2/* $NetBSD: igs_driver.c,v 1.6 2011/02/01 22:53:03 macallan Exp $ */
3/*
4 * Copyright (c) 2001 Matthieu Herrb
5 *		 2009 Michael Lorenz
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 *    - Redistributions of source code must retain the above copyright
13 *      notice, this list of conditions and the following disclaimer.
14 *    - Redistributions in binary form must reproduce the above
15 *      copyright notice, this list of conditions and the following
16 *      disclaimer in the documentation and/or other materials provided
17 *      with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34/*
35 * Based on fbdev.c written by:
36 *
37 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
38 *	     Michel Dänzer, <michdaen@iiic.ethz.ch>
39 */
40
41 /*
42  * a driver for IGS CyberPro 2010 graphics controllers
43  * adapted from wsfb
44  */
45
46#ifdef HAVE_CONFIG_H
47#include "config.h"
48#endif
49
50#include <fcntl.h>
51#include <sys/types.h>
52#include <sys/time.h>
53#include <errno.h>
54#include <dev/wscons/wsconsio.h>
55
56/* all driver need this */
57#include "xf86.h"
58#include "xf86_OSproc.h"
59
60#include "mipointer.h"
61#include "mibstore.h"
62#include "micmap.h"
63#include "colormapst.h"
64#include "xf86cmap.h"
65#include "shadow.h"
66#include "dgaproc.h"
67
68/* Everything using inb/outb, etc needs "compiler.h" */
69#include "compiler.h"
70
71/* for visuals */
72#include "fb.h"
73
74#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 7
75#include "xf86Resources.h"
76#include "xf86RAC.h"
77#endif
78
79#ifdef XvExtension
80#include "xf86xv.h"
81#endif
82
83#include "igs.h"
84
85#include <sys/mman.h>
86
87#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 6
88#define xf86LoaderReqSymLists(...) do {} while (0)
89#define LoaderRefSymLists(...) do {} while (0)
90#endif
91
92#define DEBUG 0
93
94#if DEBUG
95# define TRACE_ENTER(str)       ErrorF("igs: " str " %d\n",pScrn->scrnIndex)
96# define TRACE_EXIT(str)        ErrorF("igs: " str " done\n")
97# define TRACE(str)             ErrorF("igs trace: " str "\n")
98#else
99# define TRACE_ENTER(str)
100# define TRACE_EXIT(str)
101# define TRACE(str)
102#endif
103
104#define IGS_DEFAULT_DEV "/dev/ttyE0"
105
106/* Prototypes */
107#ifdef XFree86LOADER
108static pointer IgsSetup(pointer, pointer, int *, int *);
109#endif
110static Bool IgsGetRec(ScrnInfoPtr);
111static void IgsFreeRec(ScrnInfoPtr);
112static const OptionInfoRec * IgsAvailableOptions(int, int);
113static void IgsIdentify(int);
114static Bool IgsProbe(DriverPtr, int);
115static Bool IgsPreInit(ScrnInfoPtr, int);
116static Bool IgsScreenInit(int, ScreenPtr, int, char **);
117static Bool IgsCloseScreen(int, ScreenPtr);
118static void *IgsWindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *,
119			      void *);
120static Bool IgsEnterVT(int, int);
121static void IgsLeaveVT(int, int);
122static Bool IgsSwitchMode(int, DisplayModePtr, int);
123static int IgsValidMode(int, DisplayModePtr, Bool, int);
124static void IgsLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
125static Bool IgsSaveScreen(ScreenPtr, int);
126static void IgsSave(ScrnInfoPtr);
127static void IgsRestore(ScrnInfoPtr);
128
129/* dga stuff */
130#ifdef XFreeXDGA
131static Bool IgsDGAOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
132				   int *, int *, int *);
133static Bool IgsDGASetMode(ScrnInfoPtr, DGAModePtr);
134static void IgsDGASetViewport(ScrnInfoPtr, int, int, int);
135static Bool IgsDGAInit(ScrnInfoPtr, ScreenPtr);
136#endif
137static Bool IgsDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
138				pointer ptr);
139
140/* helper functions */
141static pointer igs_mmap(size_t, off_t, int);
142
143/*
144 * This is intentionally screen-independent.  It indicates the binding
145 * choice made in the first PreInit.
146 */
147static int pix24bpp = 0;
148
149#define IGS_VERSION 		4000
150#define IGS_NAME		"igs"
151#define IGS_DRIVER_NAME	"igs"
152
153_X_EXPORT DriverRec IGS = {
154	IGS_VERSION,
155	IGS_DRIVER_NAME,
156	IgsIdentify,
157	IgsProbe,
158	IgsAvailableOptions,
159	NULL,
160	0,
161	IgsDriverFunc
162};
163
164/* Supported "chipsets" */
165static SymTabRec IgsChipsets[] = {
166	{ 0, "CyberPro 2010" },
167	{ -1, NULL }
168};
169
170/* Supported options */
171typedef enum {
172	OPTION_NOACCEL,
173	OPTION_HW_CURSOR,
174	OPTION_SW_CURSOR
175} IgsOpts;
176
177static const OptionInfoRec IgsOptions[] = {
178	{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
179	{ -1, NULL, OPTV_NONE, {0}, FALSE}
180};
181
182/* Symbols needed from other modules */
183static const char *fbSymbols[] = {
184	"fbPictureInit",
185	"fbScreenInit",
186	NULL
187};
188static const char *shadowSymbols[] = {
189	"shadowAdd",
190	"shadowSetup",
191	"shadowUpdatePacked",
192	"shadowUpdatePackedWeak",
193	"shadowUpdateRotatePacked",
194	"shadowUpdateRotatePackedWeak",
195	NULL
196};
197
198static const char *ramdacSymbols[] = {
199	"xf86CreateCursorInfoRec",
200	"xf86DestroyCursorInfoRec",
201	"xf86InitCursor",
202	NULL
203};
204
205#ifdef XFree86LOADER
206static XF86ModuleVersionInfo IgsVersRec = {
207	"igs",
208	MODULEVENDORSTRING,
209	MODINFOSTRING1,
210	MODINFOSTRING2,
211	XORG_VERSION_CURRENT,
212	PACKAGE_VERSION_MAJOR,
213	PACKAGE_VERSION_MINOR,
214	PACKAGE_VERSION_PATCHLEVEL,
215	ABI_CLASS_VIDEODRV,
216	ABI_VIDEODRV_VERSION,
217	NULL,
218	{0, 0, 0, 0}
219};
220
221_X_EXPORT XF86ModuleData igsModuleData = { &IgsVersRec, IgsSetup, NULL };
222
223static pointer
224IgsSetup(pointer module, pointer opts, int *errmaj, int *errmin)
225{
226	static Bool setupDone = FALSE;
227	const char *osname;
228
229	/* Check that we're being loaded on a OpenBSD or NetBSD system */
230	LoaderGetOS(&osname, NULL, NULL, NULL);
231	if (!osname || (strcmp(osname, "openbsd") != 0 &&
232	                strcmp(osname, "netbsd") != 0)) {
233		if (errmaj)
234			*errmaj = LDR_BADOS;
235		if (errmin)
236			*errmin = 0;
237		return NULL;
238	}
239	if (!setupDone) {
240		setupDone = TRUE;
241		xf86AddDriver(&IGS, module, HaveDriverFuncs);
242		LoaderRefSymLists(fbSymbols, shadowSymbols, ramdacSymbols,
243		    NULL);
244		return (pointer)1;
245	} else {
246		if (errmaj != NULL)
247			*errmaj = LDR_ONCEONLY;
248		return NULL;
249	}
250}
251#endif /* XFree86LOADER */
252
253static Bool
254IgsGetRec(ScrnInfoPtr pScrn)
255{
256
257	if (pScrn->driverPrivate != NULL)
258		return TRUE;
259
260	pScrn->driverPrivate = xnfcalloc(sizeof(IgsRec), 1);
261	return TRUE;
262}
263
264static void
265IgsFreeRec(ScrnInfoPtr pScrn)
266{
267
268	if (pScrn->driverPrivate == NULL)
269		return;
270	xfree(pScrn->driverPrivate);
271	pScrn->driverPrivate = NULL;
272}
273
274static const OptionInfoRec *
275IgsAvailableOptions(int chipid, int busid)
276{
277	return IgsOptions;
278}
279
280static void
281IgsIdentify(int flags)
282{
283	xf86PrintChipsets(IGS_NAME, "driver for IGS CyberPro 2010",
284			  IgsChipsets);
285}
286
287#define priv_open_device(n)	open(n,O_RDWR|O_NONBLOCK|O_EXCL)
288
289/* Open the framebuffer device */
290static int
291igs_open(char *dev)
292{
293	int fd = -1;
294
295	/* try argument from XF86Config first */
296	if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
297		/* second: environment variable */
298		dev = getenv("XDEVICE");
299		if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) {
300			/* last try: default device */
301			dev = IGS_DEFAULT_DEV;
302			if ((fd = priv_open_device(dev)) == -1) {
303				return -1;
304			}
305		}
306	}
307	return fd;
308}
309/* Map the framebuffer's memory */
310static pointer
311igs_mmap(size_t len, off_t off, int fd)
312{
313	int pagemask, mapsize;
314	caddr_t addr;
315	pointer mapaddr;
316
317	pagemask = getpagesize() - 1;
318	mapsize = ((int) len + pagemask) & ~pagemask;
319	addr = 0;
320
321	/*
322	 * try and make it private first, that way once we get it, an
323	 * interloper, e.g. another server, can't get this frame buffer,
324	 * and if another server already has it, this one won't.
325	 */
326	mapaddr = (pointer) mmap(addr, mapsize,
327				 PROT_READ | PROT_WRITE, MAP_SHARED,
328				 fd, off);
329	if (mapaddr == MAP_FAILED) {
330		mapaddr = NULL;
331	}
332#if DEBUG
333	ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, mapsize);
334#endif
335	return mapaddr;
336}
337
338static int
339igsFindIsaDevice(GDevPtr dev)
340{
341	int found = -1;
342	uint8_t id0, id1, rev;
343
344	/* read chip ID from extended VGA registers */
345	id0 = igs_ext_read(IGS_EXT_CHIP_ID0);
346	id1 = igs_ext_read(IGS_EXT_CHIP_ID1);
347	rev = igs_ext_read(IGS_EXT_CHIP_REV);
348	xf86Msg(X_ERROR, "%s: %x %x %x\n", __func__, id0, id1, rev);
349	if ((id0 == 0xa4) && (id1 == 8))
350		found = 0;
351	return found;
352}
353
354static Bool
355IgsProbe(DriverPtr drv, int flags)
356{
357    ScrnInfoPtr pScrn = NULL;
358    IgsPtr cPtr;
359    Bool foundScreen = FALSE;
360    int numDevSections, numUsed;
361    GDevPtr *devSections;
362    int *usedChips;
363    int i, chipset, entity;
364
365    /*
366     * Find the config file Device sections that match this
367     * driver, and return if there are none.
368     */
369    if ((numDevSections = xf86MatchDevice(IGS_DRIVER_NAME,
370					  &devSections)) <= 0) {
371	return FALSE;
372    }
373
374    /* Isa Bus */
375    if ((numDevSections =
376      xf86MatchDevice(IGS_DRIVER_NAME, &devSections)) > 0) {
377	for (i = 0; i < numDevSections; i++) {
378	    if ((chipset = igsFindIsaDevice(devSections[i])) > -1) {
379		if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
380		    xf86AddBusDeviceToConfigure(IGS_DRIVER_NAME, BUS_ISA,
381			  NULL, chipset);
382		}
383		if (flags & PROBE_DETECT) {
384		    return TRUE;
385		}
386		if (!xf86CheckStrOption(devSections[i]->options, "BusID",
387		  "ISA")) {
388		    continue;
389		}
390
391		pScrn = NULL;
392		entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
393	    	pScrn = xf86ConfigFbEntity(NULL, 0, entity, NULL, NULL,
394		  NULL, NULL);
395		pScrn->driverVersion = IGS_VERSION;
396		pScrn->driverName    = IGS_DRIVER_NAME;
397		pScrn->name          = IGS_NAME;
398		pScrn->Probe         = IgsProbe;
399		pScrn->PreInit       = IgsPreInit;
400		pScrn->ScreenInit    = IgsScreenInit;
401		pScrn->SwitchMode    = IgsSwitchMode;
402		pScrn->AdjustFrame   = NULL;
403		pScrn->EnterVT       = IgsEnterVT;
404		pScrn->LeaveVT       = IgsLeaveVT;
405		pScrn->ValidMode     = IgsValidMode;
406		if (!IgsGetRec(pScrn)) {
407		    return;
408		}
409		cPtr = IGSPTR(pScrn);
410		cPtr->Chipset = chipset;
411		cPtr->fb_paddr =
412		    ((uint32_t)igs_ext_read(IGS_EXT_LINA_HI)) << 24;
413		xf86Msg(X_ERROR, "Aperture at %08x\n", cPtr->fb_paddr);
414	    }
415	}
416    }
417
418    xfree(devSections);
419    return foundScreen;
420}
421
422static Bool
423IgsPreInit(ScrnInfoPtr pScrn, int flags)
424{
425	IgsPtr fPtr;
426	int default_depth, vram_size = 2 * 1024 * 1024;
427	char *dev, *s;
428	char *mod = NULL;
429	const char *reqSym = NULL;
430	Gamma zeros = {0.0, 0.0, 0.0};
431	DisplayModePtr mode;
432	MessageType from;
433
434	if (flags & PROBE_DETECT) return FALSE;
435
436	TRACE_ENTER("PreInit");
437
438	if (pScrn->numEntities != 1) return FALSE;
439
440	pScrn->monitor = pScrn->confScreen->monitor;
441
442	IgsGetRec(pScrn);
443	fPtr = IGSPTR(pScrn);
444
445	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
446
447#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
448	pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
449	pScrn->racIoFlags = pScrn->racMemFlags;
450#endif
451
452	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
453	fPtr->fd = igs_open(dev);
454	if (fPtr->fd == -1) {
455		return FALSE;
456	}
457
458	if (ioctl(fPtr->fd, WSDISPLAYIO_GINFO, &fPtr->info) == -1) {
459		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
460			   "ioctl WSDISPLAY_GINFO: %s\n",
461			   strerror(errno));
462		return FALSE;
463	}
464
465	/* Handle depth */
466	default_depth = fPtr->info.depth <= 24 ? fPtr->info.depth : 24;
467	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
468		fPtr->info.depth,
469		fPtr->info.depth >= 24 ? Support24bppFb|Support32bppFb : 0))
470		return FALSE;
471
472	/* Check consistency */
473	if (pScrn->bitsPerPixel != fPtr->info.depth) {
474		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
475		    "specified depth (%d) or bpp (%d) doesn't match "
476		    "framebuffer depth (%d)\n", pScrn->depth,
477		    pScrn->bitsPerPixel, fPtr->info.depth);
478		return FALSE;
479	}
480	xf86PrintDepthBpp(pScrn);
481
482	/* Get the depth24 pixmap format */
483	if (pScrn->depth == 24 && pix24bpp == 0)
484		pix24bpp = xf86GetBppFromDepth(pScrn, 24);
485
486	/* color weight */
487	if (pScrn->depth > 8) {
488		rgb zeros = { 0, 0, 0 }, masks;
489
490		masks.red = 0;
491		masks.green = 0;
492		masks.blue = 0;
493
494		if (!xf86SetWeight(pScrn, zeros, masks))
495			return FALSE;
496	}
497
498	/* visual init */
499	if (!xf86SetDefaultVisual(pScrn, -1))
500		return FALSE;
501
502	/* We don't currently support DirectColor at > 8bpp */
503	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
504		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
505			   " (%s) is not supported at depth %d\n",
506			   xf86GetVisualName(pScrn->defaultVisual),
507			   pScrn->depth);
508		return FALSE;
509	}
510
511	xf86SetGamma(pScrn,zeros);
512
513	pScrn->progClock = TRUE;
514	pScrn->rgbBits   = 8;
515	pScrn->chipset   = "igs";
516	pScrn->videoRam  = vram_size;
517
518	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
519		   pScrn->videoRam/1024);
520
521	/* handle options */
522	xf86CollectOptions(pScrn, NULL);
523	if (!(fPtr->Options = xalloc(sizeof(IgsOptions))))
524		return FALSE;
525	memcpy(fPtr->Options, IgsOptions, sizeof(IgsOptions));
526	xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
527			   fPtr->Options);
528
529	/* fake video mode struct */
530	mode = (DisplayModePtr)xalloc(sizeof(DisplayModeRec));
531	mode->prev = mode;
532	mode->next = mode;
533	mode->name = "igs current mode";
534	mode->status = MODE_OK;
535	mode->type = M_T_BUILTIN;
536	mode->Clock = 0;
537	mode->HDisplay = fPtr->info.width;
538	mode->HSyncStart = 0;
539	mode->HSyncEnd = 0;
540	mode->HTotal = 0;
541	mode->HSkew = 0;
542	mode->VDisplay = fPtr->info.height;
543	mode->VSyncStart = 0;
544	mode->VSyncEnd = 0;
545	mode->VTotal = 0;
546	mode->VScan = 0;
547	mode->Flags = 0;
548	if (pScrn->modes != NULL) {
549		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
550		   "Ignoring mode specification from screen section\n");
551	}
552	pScrn->currentMode = pScrn->modes = mode;
553	pScrn->virtualX = fPtr->info.width;
554	pScrn->virtualY = fPtr->info.height;
555	pScrn->displayWidth = pScrn->virtualX;
556
557	/* Set the display resolution */
558	xf86SetDpi(pScrn, 0, 0);
559
560	from = X_DEFAULT;
561	fPtr->HWCursor = TRUE;
562	if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor))
563		from = X_CONFIG;
564	if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) {
565		from = X_CONFIG;
566		fPtr->HWCursor = FALSE;
567	}
568	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
569		fPtr->HWCursor ? "HW" : "SW");
570
571	/* Load bpp-specific modules */
572	switch(pScrn->bitsPerPixel) {
573	default:
574		mod = "fb";
575		break;
576	}
577
578	if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
579		IgsFreeRec(pScrn);
580		return FALSE;
581	}
582
583	if (xf86LoadSubModule(pScrn, "ramdac") == NULL) {
584		IgsFreeRec(pScrn);
585		return FALSE;
586        }
587
588	if (mod) {
589		if (reqSym) {
590			xf86LoaderReqSymbols(reqSym, NULL);
591		} else {
592			xf86LoaderReqSymLists(fbSymbols, NULL);
593		}
594	}
595	TRACE_EXIT("PreInit");
596	return TRUE;
597}
598
599static Bool
600IgsCreateScreenResources(ScreenPtr pScreen)
601{
602	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
603	IgsPtr fPtr = IGSPTR(pScrn);
604	PixmapPtr pPixmap;
605	Bool ret;
606
607	pScreen->CreateScreenResources = fPtr->CreateScreenResources;
608	ret = pScreen->CreateScreenResources(pScreen);
609	pScreen->CreateScreenResources = IgsCreateScreenResources;
610
611	if (!ret)
612		return FALSE;
613
614	pPixmap = pScreen->GetScreenPixmap(pScreen);
615
616	if (!shadowAdd(pScreen, pPixmap, shadowUpdatePackedWeak(),
617		IgsWindowLinear, FALSE, NULL)) {
618		return FALSE;
619	}
620	return TRUE;
621}
622
623
624static Bool
625IgsShadowInit(ScreenPtr pScreen)
626{
627	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
628	IgsPtr fPtr = IGSPTR(pScrn);
629
630	if (!shadowSetup(pScreen))
631		return FALSE;
632	fPtr->CreateScreenResources = pScreen->CreateScreenResources;
633	pScreen->CreateScreenResources = IgsCreateScreenResources;
634
635	return TRUE;
636}
637
638static Bool
639IgsScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
640{
641	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
642	IgsPtr fPtr = IGSPTR(pScrn);
643	VisualPtr visual;
644	int ret, flags, ncolors;
645	int wsmode = WSDISPLAYIO_MODE_DUMBFB;
646	size_t len;
647
648	TRACE_ENTER("IgsScreenInit");
649#if DEBUG
650	ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
651	       "\tmask: %x,%x,%x, offset: %u,%u,%u\n",
652	       pScrn->bitsPerPixel,
653	       pScrn->depth,
654	       xf86GetVisualName(pScrn->defaultVisual),
655	       pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
656	       pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
657#endif
658	fPtr->linebytes = fPtr->info.width * (fPtr->info.depth >> 3);
659
660	/* Switch to graphics mode - required before mmap */
661	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) {
662		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
663			   "ioctl WSDISPLAYIO_SMODE: %s\n",
664			   strerror(errno));
665		return FALSE;
666	}
667
668	/* find our aperturwe */
669
670	/* assume 2MB for now, until I add actual RAM size probing */
671	len = 2 * 1024 * 1024;
672	fPtr->fbmem = igs_mmap(len, fPtr->fb_paddr, fPtr->fd);
673
674	if (fPtr->fbmem == NULL) {
675		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
676			   "igs_mmap(fb): %s\n", strerror(errno));
677		return FALSE;
678	}
679	fPtr->fbmem_len = len - 1024; /* leave room for the hw cursor */
680
681	fPtr->reg = igs_mmap(4096,
682	    fPtr->fb_paddr + IGS_MEM_MMIO_SELECT + IGS_COP_BASE_B, fPtr->fd);
683	if (fPtr->reg == NULL) {
684		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
685			   "igs_mmap(registers): %s\n", strerror(errno));
686		return FALSE;
687	}
688	xf86Msg(X_ERROR, "0x10: %08x\n", *(uint32_t *)(fPtr->reg + 0x10));
689
690	IgsSave(pScrn);
691	pScrn->vtSema = TRUE;
692
693	/* mi layer */
694	miClearVisualTypes();
695	if (pScrn->bitsPerPixel > 8) {
696		if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
697				      pScrn->rgbBits, TrueColor))
698			return FALSE;
699	} else {
700		if (!miSetVisualTypes(pScrn->depth,
701				      miGetDefaultVisualMask(pScrn->depth),
702				      pScrn->rgbBits, pScrn->defaultVisual))
703			return FALSE;
704	}
705	if (!miSetPixmapDepths())
706		return FALSE;
707
708	fPtr->fbstart = fPtr->fbmem;
709
710	switch (pScrn->bitsPerPixel) {
711	case 8:
712	case 16:
713	case 24:
714	case 32:
715		ret = fbScreenInit(pScreen,
716		    fPtr->fbstart,
717		    pScrn->virtualX, pScrn->virtualY,
718		    pScrn->xDpi, pScrn->yDpi,
719		    pScrn->displayWidth, pScrn->bitsPerPixel);
720		break;
721	default:
722		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
723			   "Unsupported bpp: %d", pScrn->bitsPerPixel);
724		return FALSE;
725	} /* case */
726
727	if (!ret)
728		return FALSE;
729
730	if (pScrn->bitsPerPixel > 8) {
731		/* Fixup RGB ordering */
732		visual = pScreen->visuals + pScreen->numVisuals;
733		while (--visual >= pScreen->visuals) {
734			if ((visual->class | DynamicClass) == DirectColor) {
735				visual->offsetRed   = pScrn->offset.red;
736				visual->offsetGreen = pScrn->offset.green;
737				visual->offsetBlue  = pScrn->offset.blue;
738				visual->redMask     = pScrn->mask.red;
739				visual->greenMask   = pScrn->mask.green;
740				visual->blueMask    = pScrn->mask.blue;
741			}
742		}
743	}
744
745	if (pScrn->bitsPerPixel >= 8) {
746		if (!fbPictureInit(pScreen, NULL, 0))
747			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
748				   "RENDER extension initialisation failed.");
749	}
750
751#ifdef XFreeXDGA
752	IgsDGAInit(pScrn, pScreen);
753#endif
754
755	xf86SetBlackWhitePixels(pScreen);
756	miInitializeBackingStore(pScreen);
757	xf86SetBackingStore(pScreen);
758
759	/* setup acceleration */
760	if (1) {
761		XF86ModReqInfo req;
762		int errmaj, errmin;
763
764		memset(&req, 0, sizeof(XF86ModReqInfo));
765		req.majorversion = 2;
766		req.minorversion = 0;
767		if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
768		    &errmaj, &errmin)) {
769			LoaderErrorMsg(NULL, "exa", errmaj, errmin);
770			return FALSE;
771		}
772		if (!IgsInitAccel(pScreen))
773			return FALSE;
774	}
775
776	/* software cursor */
777	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
778
779	/* check for hardware cursor support */
780	if (fPtr->HWCursor)
781		IgsSetupCursor(pScreen);
782
783	/* colormap */
784	if (!miCreateDefColormap(pScreen))
785		return FALSE;
786	flags = CMAP_RELOAD_ON_MODE_SWITCH;
787	ncolors = fPtr->info.cmsize;
788	/* on StaticGray visuals, fake a 256 entries colormap */
789	if (ncolors == 0)
790		ncolors = 256;
791	if(!xf86HandleColormaps(pScreen, ncolors, 8, IgsLoadPalette,
792				NULL, flags))
793		return FALSE;
794
795	pScreen->SaveScreen = IgsSaveScreen;
796
797#ifdef XvExtension
798	{
799		XF86VideoAdaptorPtr *ptr;
800
801		int n = xf86XVListGenericAdaptors(pScrn,&ptr);
802		if (n) {
803			xf86XVScreenInit(pScreen,ptr,n);
804		}
805	}
806#endif
807
808	/* Wrap the current CloseScreen function */
809	fPtr->CloseScreen = pScreen->CloseScreen;
810	pScreen->CloseScreen = IgsCloseScreen;
811
812	TRACE_EXIT("IgsScreenInit");
813	return TRUE;
814}
815
816static Bool
817IgsCloseScreen(int scrnIndex, ScreenPtr pScreen)
818{
819	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
820	IgsPtr fPtr = IGSPTR(pScrn);
821
822	TRACE_ENTER("IgsCloseScreen");
823
824	if (pScrn->vtSema) {
825		IgsRestore(pScrn);
826		if (munmap(fPtr->fbmem, fPtr->fbmem_len) == -1) {
827			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
828				   "munmap: %s\n", strerror(errno));
829		}
830
831		fPtr->fbmem = NULL;
832	}
833#ifdef XFreeXDGA
834	if (fPtr->pDGAMode) {
835		xfree(fPtr->pDGAMode);
836		fPtr->pDGAMode = NULL;
837		fPtr->nDGAMode = 0;
838	}
839#endif
840	pScrn->vtSema = FALSE;
841
842	/* unwrap CloseScreen */
843	pScreen->CloseScreen = fPtr->CloseScreen;
844	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
845}
846
847static void *
848IgsWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
849		CARD32 *size, void *closure)
850{
851	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
852	IgsPtr fPtr = IGSPTR(pScrn);
853
854	if (fPtr->linebytes)
855		*size = fPtr->linebytes;
856	else {
857		if (ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, size) == -1)
858			return NULL;
859		fPtr->linebytes = *size;
860	}
861	return ((CARD8 *)fPtr->fbmem + row *fPtr->linebytes + offset);
862}
863
864static Bool
865IgsEnterVT(int scrnIndex, int flags)
866{
867	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
868
869	TRACE_ENTER("EnterVT");
870	pScrn->vtSema = TRUE;
871	return TRUE;
872}
873
874static void
875IgsLeaveVT(int scrnIndex, int flags)
876{
877#if DEBUG
878	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
879#endif
880
881	TRACE_ENTER("LeaveVT");
882}
883
884static Bool
885IgsSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
886{
887#if DEBUG
888	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
889#endif
890
891	TRACE_ENTER("SwitchMode");
892	/* Nothing else to do */
893	return TRUE;
894}
895
896static int
897IgsValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
898{
899#if DEBUG
900	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
901#endif
902
903	TRACE_ENTER("ValidMode");
904	return MODE_OK;
905}
906
907static void
908IgsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
909	       LOCO *colors, VisualPtr pVisual)
910{
911	IgsPtr fPtr = IGSPTR(pScrn);
912	struct wsdisplay_cmap cmap;
913	unsigned char red[256],green[256],blue[256];
914	int i, indexMin=256, indexMax=0;
915
916	TRACE_ENTER("LoadPalette");
917
918	cmap.count   = 1;
919	cmap.red   = red;
920	cmap.green = green;
921	cmap.blue  = blue;
922
923	if (numColors == 1) {
924		/* Optimisation */
925		cmap.index = indices[0];
926		red[0]   = colors[indices[0]].red;
927		green[0] = colors[indices[0]].green;
928		blue[0]  = colors[indices[0]].blue;
929		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
930			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
931	} else {
932		/* Change all colors in 2 syscalls */
933		/* and limit the data to be transfered */
934		for (i = 0; i < numColors; i++) {
935			if (indices[i] < indexMin)
936				indexMin = indices[i];
937			if (indices[i] > indexMax)
938				indexMax = indices[i];
939		}
940		cmap.index = indexMin;
941		cmap.count = indexMax - indexMin + 1;
942		cmap.red = &red[indexMin];
943		cmap.green = &green[indexMin];
944		cmap.blue = &blue[indexMin];
945		/* Get current map */
946		if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1)
947			ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno));
948		/* Change the colors that require updating */
949		for (i = 0; i < numColors; i++) {
950			red[indices[i]]   = colors[indices[i]].red;
951			green[indices[i]] = colors[indices[i]].green;
952			blue[indices[i]]  = colors[indices[i]].blue;
953		}
954		/* Write the colormap back */
955		if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1)
956			ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno));
957	}
958	TRACE_EXIT("LoadPalette");
959}
960
961static Bool
962IgsSaveScreen(ScreenPtr pScreen, int mode)
963{
964	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
965	IgsPtr fPtr = IGSPTR(pScrn);
966	int state;
967
968	TRACE_ENTER("SaveScreen");
969
970	if (!pScrn->vtSema)
971		return TRUE;
972
973	if (mode != SCREEN_SAVER_FORCER) {
974		state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON:
975		                            WSDISPLAYIO_VIDEO_OFF;
976		ioctl(fPtr->fd,
977		      WSDISPLAYIO_SVIDEO, &state);
978	}
979	return TRUE;
980}
981
982
983static void
984IgsSave(ScrnInfoPtr pScrn)
985{
986	IgsPtr fPtr = IGSPTR(pScrn);
987
988	TRACE_ENTER("IgsSave");
989
990	if (fPtr->info.cmsize == 0)
991		return;
992
993}
994
995static void
996IgsRestore(ScrnInfoPtr pScrn)
997{
998	IgsPtr fPtr = IGSPTR(pScrn);
999	int mode;
1000
1001	TRACE_ENTER("IgsRestore");
1002
1003	/* Clear the screen */
1004	memset(fPtr->fbmem, 0, fPtr->fbmem_len);
1005
1006	/* Restore the text mode */
1007	mode = WSDISPLAYIO_MODE_EMUL;
1008	if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) {
1009		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1010			   "error setting text mode %s\n", strerror(errno));
1011	}
1012	TRACE_EXIT("IgsRestore");
1013}
1014
1015#ifdef XFreeXDGA
1016/***********************************************************************
1017 * DGA stuff
1018 ***********************************************************************/
1019
1020static Bool
1021IgsDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1022		       unsigned char **ApertureBase, int *ApertureSize,
1023		       int *ApertureOffset, int *flags)
1024{
1025	*DeviceName = NULL;		/* No special device */
1026	*ApertureBase = (unsigned char *)(pScrn->memPhysBase);
1027	*ApertureSize = pScrn->videoRam;
1028	*ApertureOffset = pScrn->fbOffset;
1029	*flags = 0;
1030
1031	return TRUE;
1032}
1033
1034static Bool
1035IgsDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1036{
1037	DisplayModePtr pMode;
1038	int scrnIdx = pScrn->pScreen->myNum;
1039	int frameX0, frameY0;
1040
1041	if (pDGAMode) {
1042		pMode = pDGAMode->mode;
1043		frameX0 = frameY0 = 0;
1044	} else {
1045		if (!(pMode = pScrn->currentMode))
1046			return TRUE;
1047
1048		frameX0 = pScrn->frameX0;
1049		frameY0 = pScrn->frameY0;
1050	}
1051
1052	if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1053		return FALSE;
1054	(*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1055
1056	return TRUE;
1057}
1058
1059static void
1060IgsDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1061{
1062	(*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1063}
1064
1065static int
1066IgsDGAGetViewport(ScrnInfoPtr pScrn)
1067{
1068	return (0);
1069}
1070
1071static DGAFunctionRec IgsDGAFunctions =
1072{
1073	IgsDGAOpenFramebuffer,
1074	NULL,       /* CloseFramebuffer */
1075	IgsDGASetMode,
1076	IgsDGASetViewport,
1077	IgsDGAGetViewport,
1078	NULL,       /* Sync */
1079	NULL,       /* FillRect */
1080	NULL,       /* BlitRect */
1081	NULL,       /* BlitTransRect */
1082};
1083
1084static void
1085IgsDGAAddModes(ScrnInfoPtr pScrn)
1086{
1087	IgsPtr fPtr = IGSPTR(pScrn);
1088	DisplayModePtr pMode = pScrn->modes;
1089	DGAModePtr pDGAMode;
1090
1091	do {
1092		pDGAMode = xrealloc(fPtr->pDGAMode,
1093				    (fPtr->nDGAMode + 1) * sizeof(DGAModeRec));
1094		if (!pDGAMode)
1095			break;
1096
1097		fPtr->pDGAMode = pDGAMode;
1098		pDGAMode += fPtr->nDGAMode;
1099		(void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1100
1101		++fPtr->nDGAMode;
1102		pDGAMode->mode = pMode;
1103		pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1104		pDGAMode->byteOrder = pScrn->imageByteOrder;
1105		pDGAMode->depth = pScrn->depth;
1106		pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1107		pDGAMode->red_mask = pScrn->mask.red;
1108		pDGAMode->green_mask = pScrn->mask.green;
1109		pDGAMode->blue_mask = pScrn->mask.blue;
1110		pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
1111			TrueColor : PseudoColor;
1112		pDGAMode->xViewportStep = 1;
1113		pDGAMode->yViewportStep = 1;
1114		pDGAMode->viewportWidth = pMode->HDisplay;
1115		pDGAMode->viewportHeight = pMode->VDisplay;
1116
1117		if (fPtr->linebytes)
1118			pDGAMode->bytesPerScanline = fPtr->linebytes;
1119		else {
1120			ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES,
1121			      &fPtr->linebytes);
1122			pDGAMode->bytesPerScanline = fPtr->linebytes;
1123		}
1124
1125		pDGAMode->imageWidth = pMode->HDisplay;
1126		pDGAMode->imageHeight =  pMode->VDisplay;
1127		pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1128		pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1129		pDGAMode->maxViewportX = pScrn->virtualX -
1130			pDGAMode->viewportWidth;
1131		pDGAMode->maxViewportY = pScrn->virtualY -
1132			pDGAMode->viewportHeight;
1133
1134		pDGAMode->address = fPtr->fbstart;
1135
1136		pMode = pMode->next;
1137	} while (pMode != pScrn->modes);
1138}
1139
1140static Bool
1141IgsDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1142{
1143	IgsPtr fPtr = IGSPTR(pScrn);
1144
1145	if (pScrn->depth < 8)
1146		return FALSE;
1147
1148	if (!fPtr->nDGAMode)
1149		IgsDGAAddModes(pScrn);
1150
1151	return (DGAInit(pScreen, &IgsDGAFunctions,
1152			fPtr->pDGAMode, fPtr->nDGAMode));
1153}
1154#endif
1155
1156static Bool
1157IgsDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
1158    pointer ptr)
1159{
1160	xorgHWFlags *flag;
1161
1162	switch (op) {
1163	case GET_REQUIRED_HW_INTERFACES:
1164		flag = (CARD32*)ptr;
1165		(*flag) = HW_IO | HW_MMIO;
1166		return TRUE;
1167	default:
1168		return FALSE;
1169	}
1170}
1171
1172