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