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