mga_driver.c revision fe5e51b7
1/* $XConsortium: mga_driver.c /main/12 1996/10/28 05:13:26 kaleb $ */
2/*
3 * MGA Millennium (MGA2064W) with Ti3026 RAMDAC driver v.1.1
4 *
5 * The driver is written without any chip documentation. All extended ports
6 * and registers come from tracing the VESA-ROM functions.
7 * The BitBlt Engine comes from tracing the windows BitBlt function.
8 *
9 * Author:	Radoslaw Kapitan, Tarnow, Poland
10 *			kapitan@student.uci.agh.edu.pl
11 *		original source
12 *
13 * Now that MATROX has released documentation to the public, enhancing
14 * this driver has become much easier. Nevertheless, this work continues
15 * to be based on Radoslaw's original source
16 *
17 * Contributors:
18 *		Andrew van der Stock
19 *			ajv@greebo.net
20 *		additions, corrections, cleanups
21 *
22 *		Dirk Hohndel
23 *			hohndel@XFree86.Org
24 *		integrated into XFree86-3.1.2Gg
25 *		fixed some problems with PCI probing and mapping
26 *
27 *		David Dawes
28 *			dawes@XFree86.Org
29 *		some cleanups, and fixed some problems
30 *
31 *		Andrew E. Mileski
32 *			aem@ott.hookup.net
33 *		RAMDAC timing, and BIOS stuff
34 *
35 *		Leonard N. Zubkoff
36 *			lnz@dandelion.com
37 *		Support for 8MB boards, RGB Sync-on-Green, and DPMS.
38 *		Guy DESBIEF
39 *			g.desbief@aix.pacwan.net
40 *		RAMDAC MGA1064 timing,
41 *		Doug Merritt
42 *			doug@netcom.com
43 *		Fixed 32bpp hires 8MB horizontal line glitch at middle right
44 *		Niels Gram Jeppesen
45 *		Added digital screen option for first head
46 */
47
48/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_driver.c,v 1.244tsi Exp $ */
49
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53
54/* All drivers should typically include these */
55#include "xf86.h"
56#include "xf86_OSproc.h"
57#include "xf86Resources.h"
58
59/* All drivers need this */
60
61#include "compiler.h"
62
63/* Drivers for PCI hardware need this */
64#include "xf86PciInfo.h"
65
66/* Drivers that need to access the PCI config space directly need this */
67#ifndef XSERVER_LIBPCIACCESS
68#include "xf86Pci.h"
69#endif
70
71/* All drivers initialising the SW cursor need this */
72#include "mipointer.h"
73
74/* All drivers implementing backing store need this */
75#include "mibstore.h"
76
77#include "micmap.h"
78
79#include "xf86DDC.h"
80#include "xf86RAC.h"
81#include "vbe.h"
82
83#include "fb.h"
84#include "dixstruct.h"
85
86#include "mga_reg.h"
87#include "mga.h"
88#include "mga_macros.h"
89#include "mga_maven.h"
90
91#ifdef USE_XAA
92#include "xaa.h"
93#endif
94
95#include "xf86cmap.h"
96#include "shadowfb.h"
97#include "fbdevhw.h"
98
99#include "cfb8_32.h"
100
101#ifdef XF86DRI
102#include "dri.h"
103#endif
104
105#include <unistd.h>
106
107/*
108 * Forward definitions for the functions that make up the driver.
109 */
110
111/* Mandatory functions */
112static const OptionInfoRec *	MGAAvailableOptions(int chipid, int busid);
113static void	MGAIdentify(int flags);
114#ifdef XSERVER_LIBPCIACCESS
115static Bool MGAPciProbe(DriverPtr drv, int entity_num,
116    struct pci_device * dev, intptr_t match_data);
117#else
118static Bool	MGAProbe(DriverPtr drv, int flags);
119#endif
120static Bool	MGAPreInit(ScrnInfoPtr pScrn, int flags);
121static Bool	MGAScreenInit(int Index, ScreenPtr pScreen, int argc,
122			      char **argv);
123static Bool	MGAEnterVT(int scrnIndex, int flags);
124static Bool	MGAEnterVTFBDev(int scrnIndex, int flags);
125static void	MGALeaveVT(int scrnIndex, int flags);
126static Bool	MGACloseScreen(int scrnIndex, ScreenPtr pScreen);
127static Bool	MGASaveScreen(ScreenPtr pScreen, int mode);
128static Bool	MGASaveScreenCrtc2(ScreenPtr pScreen, int mode);
129
130/* This shouldn't be needed since RAC will disable all I/O for MGA cards. */
131#ifdef DISABLE_VGA_IO
132static void     VgaIOSave(int i, void *arg);
133static void     VgaIORestore(int i, void *arg);
134#endif
135
136/* Optional functions */
137static void	MGAFreeScreen(int scrnIndex, int flags);
138static ModeStatus MGAValidMode(int scrnIndex, DisplayModePtr mode,
139			       Bool verbose, int flags);
140
141#if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ >= 4)
142#define __must_check  __attribute__((warn_unused_result))
143#else
144#define __must_check  /* */
145#endif
146
147/* Internally used functions */
148static Bool __must_check MGAMapMem(ScrnInfoPtr pScrn);
149static Bool	MGAUnmapMem(ScrnInfoPtr pScrn);
150static void	MGASave(ScrnInfoPtr pScrn);
151static void	MGARestore(ScrnInfoPtr pScrn);
152static Bool	MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
153static void 	MGABlockHandler(int, pointer, pointer, pointer);
154static void	MGAG100BlackMagic(ScrnInfoPtr pScrn);
155
156static int MGAEntityIndex = -1;
157
158#include "mga_merge.h"
159
160static const struct mga_device_attributes attribs[8] = {
161    /* 2064 */
162    [0] = { 1, 0, 0, 1, 0, 0, 0, 0, old_BARs,
163	    (BLK_OPAQUE_EXPANSION | FASTBLT_BUG | USE_LINEAR_EXPANSION) },
164
165    /* 1064 */
166    [1] = { 0, 1, 0, 0, 1, 0, 0, 0, probe_BARs,
167            (USE_LINEAR_EXPANSION) },
168
169    /* 2164, 2164 AGP */
170    [2] = { 1, 0, 0, 1, 0, 0, 0, 0, new_BARs,
171            (BLK_OPAQUE_EXPANSION | TRANSC_SOLID_FILL | USE_RECTS_FOR_LINES
172	     | USE_LINEAR_EXPANSION) },
173
174    /* G100 */
175    [3] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
176            (MGA_NO_PLANEMASK | USE_LINEAR_EXPANSION) },
177
178    /* G200 */
179    [4] = { 0, 1, 0, 0, 1, 1, 1, 1, new_BARs,
180            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION) },
181
182    /* G400 / G450 */
183    [5] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
184            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION) },
185
186    /* G550 */
187    [6] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
188            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION) },
189
190    /* G200SE */
191    [7] = { 0, 1, 0, 0, 1, 0, 0, 1, new_BARs,
192            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION) },
193};
194
195#ifdef XSERVER_LIBPCIACCESS
196#define MGA_DEVICE_MATCH(d, i) \
197    { 0x102B, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
198#define MGA_SUBDEVICE_MATCH(d, s, i) \
199    { 0x102B, (d), 0x102B, (s), 0, 0, (i) }
200
201static const struct pci_id_match mga_device_match[] = {
202    MGA_DEVICE_MATCH( PCI_CHIP_MGA2064,     0 ),
203    MGA_DEVICE_MATCH( PCI_CHIP_MGA1064,     1 ),
204    MGA_DEVICE_MATCH( PCI_CHIP_MGA2164,     2 ),
205    MGA_DEVICE_MATCH( PCI_CHIP_MGA2164_AGP, 2 ),
206    MGA_DEVICE_MATCH( PCI_CHIP_MGAG100,     3 ),
207    MGA_DEVICE_MATCH( PCI_CHIP_MGAG100_PCI, 3 ),
208    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200,     4 ),
209    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_PCI, 4 ),
210    MGA_DEVICE_MATCH( PCI_CHIP_MGAG400,     5 ),
211    MGA_DEVICE_MATCH( PCI_CHIP_MGAG550,     6 ),
212
213    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_SE_A_PCI, 7 ),
214    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_SE_B_PCI, 7 ),
215
216    { 0, 0, 0 },
217};
218#endif
219
220/* Supported chipsets */
221static SymTabRec MGAChipsets[] = {
222    { PCI_CHIP_MGA2064,		"mga2064w" },
223    { PCI_CHIP_MGA1064,		"mga1064sg" },
224    { PCI_CHIP_MGA2164,		"mga2164w" },
225    { PCI_CHIP_MGA2164_AGP,	"mga2164w AGP" },
226    { PCI_CHIP_MGAG100,		"mgag100" },
227    { PCI_CHIP_MGAG100_PCI,	"mgag100 PCI" },
228    { PCI_CHIP_MGAG200,		"mgag200" },
229    { PCI_CHIP_MGAG200_PCI,	"mgag200 PCI" },
230    { PCI_CHIP_MGAG200_SE_A_PCI,	"mgag200 SE A PCI" },
231    { PCI_CHIP_MGAG200_SE_B_PCI,	"mgag200 SE B PCI" },
232    { PCI_CHIP_MGAG400,		"mgag400" },
233    { PCI_CHIP_MGAG550,		"mgag550" },
234    {-1,			NULL }
235};
236
237static PciChipsets MGAPciChipsets[] = {
238    { PCI_CHIP_MGA2064,	    PCI_CHIP_MGA2064,	(resRange*)RES_SHARED_VGA },
239    { PCI_CHIP_MGA1064,	    PCI_CHIP_MGA1064,	(resRange*)RES_SHARED_VGA },
240    { PCI_CHIP_MGA2164,	    PCI_CHIP_MGA2164,	(resRange*)RES_SHARED_VGA },
241    { PCI_CHIP_MGA2164_AGP, PCI_CHIP_MGA2164_AGP,(resRange*)RES_SHARED_VGA },
242    { PCI_CHIP_MGAG100,	    PCI_CHIP_MGAG100,	(resRange*)RES_SHARED_VGA },
243    { PCI_CHIP_MGAG100_PCI, PCI_CHIP_MGAG100_PCI,(resRange*)RES_SHARED_VGA },
244    { PCI_CHIP_MGAG200,	    PCI_CHIP_MGAG200,	(resRange*)RES_SHARED_VGA },
245    { PCI_CHIP_MGAG200_PCI, PCI_CHIP_MGAG200_PCI,(resRange*)RES_SHARED_VGA },
246    { PCI_CHIP_MGAG200_SE_B_PCI, PCI_CHIP_MGAG200_SE_B_PCI,
247	(resRange*)RES_SHARED_VGA },
248    { PCI_CHIP_MGAG200_SE_A_PCI, PCI_CHIP_MGAG200_SE_A_PCI,
249	(resRange*)RES_SHARED_VGA },
250    { PCI_CHIP_MGAG400,	    PCI_CHIP_MGAG400,	(resRange*)RES_SHARED_VGA },
251    { PCI_CHIP_MGAG550,	    PCI_CHIP_MGAG550,	(resRange*)RES_SHARED_VGA },
252    { -1,			-1,		(resRange*)RES_UNDEFINED }
253};
254
255/*
256 * This contains the functions needed by the server after loading the
257 * driver module.  It must be supplied, and gets added the driver list by
258 * the Module Setup funtion in the dynamic case.  In the static case a
259 * reference to this is compiled in, and this requires that the name of
260 * this DriverRec be an upper-case version of the driver name.
261 */
262
263_X_EXPORT DriverRec MGA_C_NAME = {
264    MGA_VERSION,
265    MGA_DRIVER_NAME,
266    MGAIdentify,
267#ifdef XSERVER_LIBPCIACCESS
268    NULL,
269#else
270    MGAProbe,
271#endif
272    MGAAvailableOptions,
273    NULL,
274    0,
275    NULL,
276
277#ifdef XSERVER_LIBPCIACCESS
278    mga_device_match,
279    MGAPciProbe
280#endif
281};
282
283
284static const OptionInfoRec MGAOptions[] = {
285    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
286    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
287    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
288    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
289    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
290    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
291    { OPTION_OVERLAY,		"Overlay",	OPTV_ANYSTR,	{0}, FALSE },
292    { OPTION_MGA_SDRAM,		"MGASDRAM",	OPTV_BOOLEAN,	{0}, FALSE },
293    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
294    { OPTION_FBDEV,		"UseFBDev",	OPTV_BOOLEAN,	{0}, FALSE },
295    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
296    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,	{0}, FALSE },
297    { OPTION_OVERCLOCK_MEM,	"OverclockMem",	OPTV_BOOLEAN,	{0}, FALSE },
298    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
299    { OPTION_ROTATE,		"Rotate",	OPTV_ANYSTR,	{0}, FALSE },
300    { OPTION_TEXTURED_VIDEO,	"TexturedVideo",OPTV_BOOLEAN,	{0}, FALSE },
301    { OPTION_CRTC2HALF,		"Crtc2Half",	OPTV_BOOLEAN,	{0}, FALSE },
302    { OPTION_CRTC2RAM,		"Crtc2Ram",	OPTV_INTEGER,	{0}, FALSE },
303    { OPTION_INT10,		"Int10",	OPTV_BOOLEAN,	{0}, FALSE },
304    { OPTION_AGP_MODE,		"AGPMode",	OPTV_INTEGER,	{0}, FALSE },
305    { OPTION_AGP_SIZE,		"AGPSize",      OPTV_INTEGER,   {0}, FALSE },
306    { OPTION_DIGITAL1,		"DigitalScreen1",OPTV_BOOLEAN,	{0}, FALSE },
307    { OPTION_DIGITAL2,		"DigitalScreen2",OPTV_BOOLEAN,	{0}, FALSE },
308    { OPTION_TV,		"TV",		OPTV_BOOLEAN,	{0}, FALSE },
309    { OPTION_TVSTANDARD,	"TVStandard",	OPTV_ANYSTR,	{0}, FALSE },
310    { OPTION_CABLETYPE,		"CableType",	OPTV_ANYSTR,	{0}, FALSE },
311    { OPTION_NOHAL,		"NoHal",	OPTV_BOOLEAN,	{0}, FALSE },
312    { OPTION_SWAPPED_HEAD,	"SwappedHead",	OPTV_BOOLEAN,	{0}, FALSE },
313    { OPTION_DRI,		"DRI",		OPTV_BOOLEAN,	{0}, FALSE },
314    { OPTION_MERGEDFB,		"MergedFB",	OPTV_BOOLEAN,	{0}, FALSE },
315    { OPTION_HSYNC2,	"Monitor2HSync",	OPTV_ANYSTR,	{0}, FALSE },
316    { OPTION_VREFRESH2,	"Monitor2VRefresh",	OPTV_ANYSTR,	{0}, FALSE },
317    { OPTION_MONITOR2POS,   "Monitor2Position",	OPTV_ANYSTR,	{0}, FALSE },
318    { OPTION_METAMODES,   "MetaModes",  	OPTV_ANYSTR,	{0}, FALSE },
319    { OPTION_OLDDMA,		"OldDmaInit",	OPTV_BOOLEAN,	{0}, FALSE },
320    { OPTION_PCIDMA,		"ForcePciDma",	OPTV_BOOLEAN,	{0}, FALSE },
321    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
322    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
323};
324
325
326/*
327 * List of symbols from other modules that this module references.  This
328 * list is used to tell the loader that it is OK for symbols here to be
329 * unresolved providing that it hasn't been told that they haven't been
330 * told that they are essential via a call to xf86LoaderReqSymbols() or
331 * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
332 * unresolved symbols that are not required.
333 */
334
335static const char *vgahwSymbols[] = {
336    "vgaHWFreeHWRec",
337    "vgaHWGetHWRec",
338    "vgaHWGetIOBase",
339    "vgaHWGetIndex",
340    "vgaHWInit",
341    "vgaHWLock",
342    "vgaHWMapMem",
343    "vgaHWProtect",
344    "vgaHWRestore",
345    "vgaHWSave",
346    "vgaHWSaveScreen",
347    "vgaHWSetMmioFuncs",
348    "vgaHWUnlock",
349    "vgaHWUnmapMem",
350    "vgaHWddc1SetSpeedWeak",
351    NULL
352};
353
354static const char *fbSymbols[] = {
355    "fbPictureInit",
356    "fbScreenInit",
357    NULL
358};
359
360static const char *xf8_32bppSymbols[] = {
361    "cfb8_32ScreenInit",
362    "xf86Overlay8Plus32Init",
363    NULL
364};
365
366#ifdef USE_EXA
367static const char *exaSymbols[] = {
368    "exaDriverInit",
369    "exaDriverFini",
370    "exaGetPixmapOffset",
371    "exaGetVersion",
372    NULL
373};
374#endif
375
376#ifdef USE_XAA
377static const char *xaaSymbols[] = {
378    "XAACachePlanarMonoStipple",
379    "XAACreateInfoRec",
380    "XAADestroyInfoRec",
381    "XAAGetFallbackOps",
382    "XAAInit",
383    "XAAMoveDWORDS",
384    "XAA_888_plus_PICT_a8_to_8888",
385    NULL
386};
387#endif
388
389static const char *ramdacSymbols[] = {
390    "xf86CreateCursorInfoRec",
391    "xf86DestroyCursorInfoRec",
392    "xf86InitCursor",
393    NULL
394};
395
396#ifdef XF86DRI
397static const char *drmSymbols[] = {
398    "drmAddBufs",
399    "drmAddMap",
400    "drmAgpAcquire",
401    "drmAgpAlloc",
402    "drmAgpBind",
403    "drmAgpDeviceId",
404    "drmAgpEnable",
405    "drmAgpFree",
406    "drmAgpGetMode",
407    "drmAgpRelease",
408    "drmAgpUnbind",
409    "drmAgpVendorId",
410    "drmCommandNone",
411    "drmCommandWrite",
412    "drmCtlInstHandler",
413    "drmCtlUninstHandler",
414    "drmFreeVersion",
415    "drmGetInterruptFromBusID",
416    "drmGetLibVersion",
417    "drmGetVersion",
418    "drmMap",
419    "drmMapBufs",
420    "drmUnmap",
421    "drmUnmapBufs",
422    NULL
423};
424
425static const char *driSymbols[] = {
426    "DRICloseScreen",
427    "DRICreateInfoRec",
428    "DRIDestroyInfoRec",
429    "DRIFinishScreenInit",
430    "DRIGetDeviceInfo",
431    "DRILock",
432    "DRIQueryVersion",
433    "DRIScreenInit",
434    "DRIUnlock",
435    "GlxSetVisualConfigs",
436    "DRICreatePCIBusID",
437    NULL
438};
439#endif
440
441#define MGAuseI2C 1
442
443static const char *ddcSymbols[] = {
444    "xf86DoEDID_DDC1",
445#if MGAuseI2C
446    "xf86DoEDID_DDC2",
447#endif
448    "xf86PrintEDID",
449    "xf86SetDDCproperties",
450    NULL
451};
452
453static const char *i2cSymbols[] = {
454    "xf86CreateI2CBusRec",
455    "xf86I2CBusInit",
456    NULL
457};
458
459static const char *shadowSymbols[] = {
460    "ShadowFBInit",
461    NULL
462};
463
464#ifdef XFree86LOADER
465static const char *vbeSymbols[] = {
466    "VBEInit",
467    "vbeDoEDID",
468    "vbeFree",
469    NULL
470};
471#endif
472
473static const char *int10Symbols[] = {
474    "xf86FreeInt10",
475    "xf86InitInt10",
476    NULL
477};
478
479static const char *fbdevHWSymbols[] = {
480    "fbdevHWAdjustFrameWeak",
481    "fbdevHWEnterVT",
482    "fbdevHWGetVidmem",
483    "fbdevHWInit",
484    "fbdevHWLeaveVTWeak",
485    "fbdevHWLoadPaletteWeak",
486    "fbdevHWMapMMIO",
487    "fbdevHWMapVidmem",
488    "fbdevHWModeInit",
489    "fbdevHWRestore",
490    "fbdevHWSave",
491    "fbdevHWSwitchModeWeak",
492    "fbdevHWUnmapMMIO",
493    "fbdevHWUnmapVidmem",
494    "fbdevHWUseBuildinMode",
495    "fbdevHWValidModeWeak",
496    NULL
497};
498
499#ifdef USEMGAHAL
500static const char *halSymbols[] = {
501  "MGACloseLibrary",
502  "MGAGetBOARDHANDLESize",
503  "MGAGetHardwareInfo",
504  "MGAOpenLibrary",
505  "MGARestoreVgaState",
506  "MGASaveVgaState",
507  "MGASetMode",
508  "MGASetVgaMode",
509  "MGAValidateMode",
510  "MGAValidateVideoParameters",
511  "HALSetDisplayStart",
512  NULL
513};
514#endif
515#ifdef XFree86LOADER
516
517static MODULESETUPPROTO(mgaSetup);
518
519static XF86ModuleVersionInfo mgaVersRec =
520{
521	MGA_DRIVER_NAME,
522	MODULEVENDORSTRING,
523	MODINFOSTRING1,
524	MODINFOSTRING2,
525	XORG_VERSION_CURRENT,
526    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
527	ABI_CLASS_VIDEODRV,			/* This is a video driver */
528	ABI_VIDEODRV_VERSION,
529	MOD_CLASS_VIDEODRV,
530	{0,0,0,0}
531};
532
533_X_EXPORT XF86ModuleData MGA_MODULE_DATA = { &mgaVersRec, mgaSetup, NULL };
534
535static pointer
536mgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
537{
538    static Bool setupDone = FALSE;
539
540    /* This module should be loaded only once, but check to be sure. */
541
542    if (!setupDone) {
543	setupDone = TRUE;
544	xf86AddDriver(&MGA_C_NAME, module, 1);
545
546	/*
547	 * Modules that this driver always requires may be loaded here
548	 * by calling LoadSubModule().
549	 */
550
551	/*
552	 * Tell the loader about symbols from other modules that this module
553	 * might refer to.
554	 */
555	LoaderRefSymLists(vgahwSymbols,
556#ifdef USE_XAA
557                          xaaSymbols,
558#endif
559#ifdef USE_EXA
560                          exaSymbols,
561#endif
562			  xf8_32bppSymbols, ramdacSymbols,
563			  ddcSymbols, i2cSymbols, shadowSymbols,
564			  fbdevHWSymbols, vbeSymbols,
565			  fbSymbols, int10Symbols,
566#ifdef XF86DRI
567			  drmSymbols, driSymbols,
568#endif
569#ifdef USEMGAHAL
570			  halSymbols,
571#endif
572			  NULL);
573
574	/*
575	 * The return value must be non-NULL on success even though there
576	 * is no TearDownProc.
577	 */
578	return (pointer)1;
579    } else {
580	if (errmaj) *errmaj = LDR_ONCEONLY;
581	return NULL;
582    }
583}
584
585
586#endif /* XFree86LOADER */
587
588/*
589 * ramdac info structure initialization
590 */
591static MGARamdacRec DacInit = {
592	FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
593	90000, /* maxPixelClock */
594	0, X_DEFAULT, X_DEFAULT, FALSE
595};
596
597Bool
598MGAGetRec(ScrnInfoPtr pScrn)
599{
600    /*
601     * Allocate an MGARec, and hook it into pScrn->driverPrivate.
602     * pScrn->driverPrivate is initialised to NULL, so we can check if
603     * the allocation has already been done.
604     */
605    if (pScrn->driverPrivate != NULL)
606	return TRUE;
607
608    pScrn->driverPrivate = xnfcalloc(sizeof(MGARec), 1);
609    /* Initialise it */
610
611    MGAPTR(pScrn)->Dac = DacInit;
612    return TRUE;
613}
614
615void
616MGAFreeRec(ScrnInfoPtr pScrn)
617{
618    if (pScrn->driverPrivate == NULL)
619	return;
620    xfree(pScrn->driverPrivate);
621    pScrn->driverPrivate = NULL;
622}
623
624static const OptionInfoRec *
625MGAAvailableOptions(int chipid, int busid)
626{
627    return MGAOptions;
628}
629
630/* Mandatory */
631static void
632MGAIdentify(int flags)
633{
634    xf86PrintChipsets(MGA_NAME, "driver for Matrox chipsets", MGAChipsets);
635}
636
637
638#ifdef XSERVER_LIBPCIACCESS
639Bool
640MGAPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev,
641	    intptr_t match_data)
642{
643    ScrnInfoPtr pScrn = NULL;
644    EntityInfoPtr pEnt;
645    MGAPtr pMga;
646#ifdef DISABLE_VGA_IO
647    MgaSavePtr smga;
648
649
650    smga = xnfalloc(sizeof(MgaSave));
651    smga->pvp = dev;
652#endif
653
654    /* Allocate a ScrnInfoRec and claim the slot */
655    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, MGAPciChipsets,
656				NULL,
657#ifndef DISABLE_VGA_IO
658				NULL, NULL, NULL, NULL
659#else
660				VgaIOSave, VgaIOSave, VgaIORestore, smga
661#endif
662				);
663    if (pScrn != NULL) {
664	/* Fill in what we can of the ScrnInfoRec */
665	pScrn->driverVersion	= MGA_VERSION;
666	pScrn->driverName	= MGA_DRIVER_NAME;
667	pScrn->name		= MGA_NAME;
668	pScrn->Probe		= NULL;
669	pScrn->PreInit		= MGAPreInit;
670	pScrn->ScreenInit	= MGAScreenInit;
671	pScrn->SwitchMode	= MGASwitchMode;
672	pScrn->AdjustFrame	= MGAAdjustFrame;
673	pScrn->EnterVT		= MGAEnterVT;
674	pScrn->LeaveVT		= MGALeaveVT;
675	pScrn->FreeScreen	= MGAFreeScreen;
676	pScrn->ValidMode	= MGAValidMode;
677
678
679	/* Allocate the MGARec driverPrivate */
680	if (!MGAGetRec(pScrn)) {
681	    return FALSE;
682	}
683
684	pMga = MGAPTR(pScrn);
685	pMga->chip_attribs = & attribs[ match_data ];
686	pMga->PciInfo = dev;
687
688
689	/*
690	 * For cards that can do dual head per entity, mark the entity
691	 * as sharable.
692	 */
693	pEnt = xf86GetEntityInfo(entity_num);
694	if (pMga->chip_attribs->dual_head_possible) {
695	    MGAEntPtr pMgaEnt = NULL;
696	    DevUnion *pPriv;
697
698	    xf86SetEntitySharable(entity_num);
699	    /* Allocate an entity private if necessary */
700	    if (MGAEntityIndex < 0)
701	      MGAEntityIndex = xf86AllocateEntityPrivateIndex();
702	    pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
703	    if (!pPriv->ptr) {
704		pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
705		pMgaEnt = pPriv->ptr;
706		pMgaEnt->lastInstance = -1;
707	    } else {
708		pMgaEnt = pPriv->ptr;
709	    }
710	    /*
711	     * Set the entity instance for this instance of the driver.  For
712	     * dual head per card, instance 0 is the "master" instance, driving
713	     * the primary head, and instance 1 is the "slave".
714	     */
715	    pMgaEnt->lastInstance++;
716	    xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
717					   pMgaEnt->lastInstance);
718	}
719    }
720
721    return (pScrn != NULL);
722}
723
724#else
725
726/* Mandatory */
727static Bool
728MGAProbe(DriverPtr drv, int flags)
729{
730    int i;
731    GDevPtr *devSections;
732    int *usedChips = NULL;
733    int numDevSections;
734    int numUsed;
735    Bool foundScreen = FALSE;
736
737    /*
738     * The aim here is to find all cards that this driver can handle,
739     * and for the ones not already claimed by another driver, claim the
740     * slot, and allocate a ScrnInfoRec.
741     *
742     * This should be a minimal probe, and it should under no circumstances
743     * change the state of the hardware.  Because a device is found, don't
744     * assume that it will be used.  Don't do any initialisations other than
745     * the required ScrnInfoRec initialisations.  Don't allocate any new
746     * data structures.
747     */
748
749    /*
750     * Check if there has been a chipset override in the config file.
751     * For this we must find out if there is an active device section which
752     * is relevant, i.e., which has no driver specified or has THIS driver
753     * specified.
754     */
755
756    if ((numDevSections = xf86MatchDevice(MGA_DRIVER_NAME,
757					  &devSections)) <= 0) {
758	/*
759	 * There's no matching device section in the config file, so quit
760	 * now.
761	 */
762	return FALSE;
763    }
764
765    /*
766     * We need to probe the hardware first.  We then need to see how this
767     * fits in with what is given in the config file, and allow the config
768     * file info to override any contradictions.
769     */
770
771    /*
772     * All of the cards this driver supports are PCI, so the "probing" just
773     * amounts to checking the PCI data that the server has already collected.
774     */
775    if (xf86GetPciVideoInfo() == NULL) {
776	/*
777	 * We won't let anything in the config file override finding no
778	 * PCI video cards at all.  This seems reasonable now, but we'll see.
779	 */
780	return FALSE;
781    }
782
783    numUsed = xf86MatchPciInstances(MGA_NAME, PCI_VENDOR_MATROX,
784			            MGAChipsets, MGAPciChipsets, devSections,
785			            numDevSections, drv, &usedChips);
786    /* Free it since we don't need that list after this */
787    xfree(devSections);
788    if (numUsed <= 0)
789	return FALSE;
790
791
792    if (flags & PROBE_DETECT)
793	foundScreen = TRUE;
794    else for (i = 0; i < numUsed; i++) {
795	ScrnInfoPtr pScrn = NULL;
796	EntityInfoPtr pEnt;
797	int attrib_no;
798#ifdef DISABLE_VGA_IO
799	MgaSavePtr smga;
800#endif
801
802	/* Allocate a ScrnInfoRec and claim the slot */
803#ifndef DISABLE_VGA_IO
804	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
805				    MGAPciChipsets, NULL, NULL,
806				    NULL, NULL, NULL);
807#else
808	smga = xnfalloc(sizeof(MgaSave));
809	smga->pvp = xf86GetPciInfoForEntity(usedChips[i]);
810	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
811				    MGAPciChipsets, NULL,VgaIOSave,
812				    VgaIOSave, VgaIORestore,smga);
813#endif
814        if (pScrn != NULL) {
815	    MGAPtr pMga;
816
817	    /* Fill in what we can of the ScrnInfoRec */
818	    pScrn->driverVersion = MGA_VERSION;
819	    pScrn->driverName	= MGA_DRIVER_NAME;
820	    pScrn->name		= MGA_NAME;
821	    pScrn->Probe	= MGAProbe;
822	    pScrn->PreInit	= MGAPreInit;
823	    pScrn->ScreenInit	= MGAScreenInit;
824	    pScrn->SwitchMode	= MGASwitchMode;
825	    pScrn->AdjustFrame	= MGAAdjustFrame;
826	    pScrn->EnterVT	= MGAEnterVT;
827	    pScrn->LeaveVT	= MGALeaveVT;
828	    pScrn->FreeScreen	= MGAFreeScreen;
829	    pScrn->ValidMode	= MGAValidMode;
830
831	    foundScreen = TRUE;
832
833	    /* Allocate the MGARec driverPrivate */
834	    if (!MGAGetRec(pScrn)) {
835		return FALSE;
836	    }
837
838	    pMga = MGAPTR(pScrn);
839
840	    /*
841	     * For cards that can do dual head per entity, mark the entity
842	     * as sharable.
843	     */
844	    pEnt = xf86GetEntityInfo(usedChips[i]);
845
846            switch (pEnt->chipset) {
847            case PCI_CHIP_MGA2064:
848                attrib_no = 0;
849                break;
850
851            case PCI_CHIP_MGA1064:
852                attrib_no = 1;
853                break;
854
855            case PCI_CHIP_MGA2164:
856            case PCI_CHIP_MGA2164_AGP:
857                attrib_no = 2;
858                break;
859
860            case PCI_CHIP_MGAG100:
861            case PCI_CHIP_MGAG100_PCI:
862                attrib_no = 3;
863                break;
864
865            case PCI_CHIP_MGAG200:
866            case PCI_CHIP_MGAG200_PCI:
867                attrib_no = 4;
868                break;
869
870            case PCI_CHIP_MGAG400:
871                attrib_no = 5;
872                break;
873
874            case PCI_CHIP_MGAG550:
875                attrib_no = 6;
876                break;
877
878            case PCI_CHIP_MGAG200_SE_A_PCI:
879            case PCI_CHIP_MGAG200_SE_B_PCI:
880                attrib_no = 7;
881                break;
882
883	    default:
884		return FALSE;
885            }
886
887	    pMga->chip_attribs = & attribs[attrib_no];
888
889	    if (pMga->chip_attribs->dual_head_possible) {
890		MGAEntPtr pMgaEnt = NULL;
891		DevUnion *pPriv;
892
893		xf86SetEntitySharable(usedChips[i]);
894		/* Allocate an entity private if necessary */
895		if (MGAEntityIndex < 0)
896		    MGAEntityIndex = xf86AllocateEntityPrivateIndex();
897		pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
898		if (!pPriv->ptr) {
899		    pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
900		    pMgaEnt = pPriv->ptr;
901		    pMgaEnt->lastInstance = -1;
902		} else {
903		    pMgaEnt = pPriv->ptr;
904		}
905		/*
906		 * Set the entity instance for this instance of the driver.  For
907		 * dual head per card, instance 0 is the "master" instance, driving
908		 * the primary head, and instance 1 is the "slave".
909		 */
910		pMgaEnt->lastInstance++;
911		xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
912					       pMgaEnt->lastInstance);
913	    }
914        }
915    }
916    xfree(usedChips);
917
918    return foundScreen;
919}
920#endif
921
922
923/*
924 * MGASoftReset --
925 *
926 * Resets drawing engine
927 */
928void
929MGASoftReset(ScrnInfoPtr pScrn)
930{
931	MGAPtr pMga = MGAPTR(pScrn);
932
933	pMga->FbMapSize = 8192 * 1024;
934	MGAMapMem(pScrn);
935
936	/* set soft reset bit */
937	OUTREG(MGAREG_Reset, 1);
938	usleep(200);
939	OUTREG(MGAREG_Reset, 0);
940
941	/* reset memory */
942	OUTREG(MGAREG_MACCESS, 1<<15);
943	usleep(10);
944
945#if 0
946	/* This will hang if the PLLs aren't on */
947
948	/* wait until drawing engine is ready */
949	while ( MGAISBUSY() )
950	    usleep(1000);
951
952	/* flush FIFO */
953	i = 32;
954	WAITFIFO(i);
955	while ( i-- )
956	    OUTREG(MGAREG_SHIFT, 0);
957#endif
958
959	MGAUnmapMem(pScrn);
960}
961
962/*
963 * MGACountRAM --
964 *
965 * Counts amount of installed RAM
966 */
967static int
968MGACountRam(ScrnInfoPtr pScrn)
969{
970    MGAPtr pMga = MGAPTR(pScrn);
971    int ProbeSize = 8192;
972    int SizeFound = 2048;
973    CARD32 biosInfo = 0;
974    CARD8 seq1;
975
976#if 0
977    /* This isn't correct. It looks like this can have arbitrary
978	data for the memconfig even when the bios has initialized
979	it.  At least, my cards don't advertise the documented
980	values (my 8 and 16 Meg G200s have the same values) */
981    if (pMga->Primary) { /* can only trust this for primary cards */
982#ifdef XSERVER_LIBPCIACCESS
983	pci_device_cfg_read_u32(pMga->PciInfo, & biosInfo,
984				PCI_OPTION_REG);
985#else
986	biosInfo = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
987#endif
988    }
989#endif
990
991    switch(pMga->Chipset) {
992    case PCI_CHIP_MGA2164:
993    case PCI_CHIP_MGA2164_AGP:
994	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
995		"Unable to probe memory amount due to hardware bug.  "
996		"Assuming 4096 KB\n");
997	return 4096;
998    case PCI_CHIP_MGAG400:
999    case PCI_CHIP_MGAG550:
1000	if(biosInfo) {
1001	    switch((biosInfo >> 10) & 0x07) {
1002	    case 0:
1003		return (biosInfo & (1 << 14)) ? 32768 : 16384;
1004	    case 1:
1005	    case 2:
1006		return 16384;
1007	    case 3:
1008	    case 5:
1009		return 65536;
1010	    case 4:
1011		return 32768;
1012	    }
1013	}
1014	ProbeSize = 32768;
1015	break;
1016    case PCI_CHIP_MGAG200_SE_A_PCI:
1017    case PCI_CHIP_MGAG200_SE_B_PCI:
1018	ProbeSize = 4096;
1019	break;
1020    case PCI_CHIP_MGAG200:
1021    case PCI_CHIP_MGAG200_PCI:
1022	if(biosInfo) {
1023	    switch((biosInfo >> 11) & 0x03) {
1024	    case 0:
1025		return 8192;
1026	    default:
1027		return 16384;
1028	    }
1029	}
1030	ProbeSize = 8192;
1031	break;
1032    case PCI_CHIP_MGAG100:
1033    case PCI_CHIP_MGAG100_PCI:
1034	if(biosInfo) /* I'm not sure if the docs are correct */
1035	    return (biosInfo & (1 << 12)) ? 16384 : 8192;
1036    case PCI_CHIP_MGA1064:
1037    case PCI_CHIP_MGA2064:
1038	ProbeSize = 8192;
1039        break;
1040    default:
1041        break;
1042    }
1043
1044    if (pMga->FbAddress) {
1045	volatile unsigned char* base;
1046	unsigned char tmp;
1047	int i;
1048
1049	pMga->FbMapSize = ProbeSize * 1024;
1050	if (!MGAMapMem(pScrn)) {
1051	    return 0;
1052	}
1053
1054	base = pMga->FbBase;
1055
1056	if (pMga->is_G200SE) {
1057	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1058	    seq1 = INREG8(MGAREG_SEQ_DATA);
1059	    seq1 |= 0x20;
1060	    MGAWAITVSYNC();
1061	    MGAWAITBUSY();
1062	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1063	    usleep(20000);
1064	}
1065
1066	/* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */
1067	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1068	tmp = INREG8(MGAREG_CRTCEXT_DATA);
1069	OUTREG8(MGAREG_CRTCEXT_DATA, tmp | 0x80);
1070
1071	/* apparently the G200SE doesn't have a BIOS to read */
1072	if (pMga->is_G200SE) {
1073	    CARD32 MemoryAt0, MemoryAt1, Offset;
1074	    CARD32 FirstMemoryVal1, FirstMemoryVal2;
1075	    CARD32 SecondMemoryVal1, SecondMemoryVal2;
1076	    CARD32 TestMemoryLocA, TestMemoryLocB;
1077	    CARD32 TestMemoryLoc0, TestMemoryLoc1;
1078	    CARD32 TestA, TestB;
1079
1080	    MemoryAt0 = base[0];
1081	    MemoryAt1 = base[1];
1082	    base[0] = 0;
1083	    base[1] = 0;
1084
1085	    for (Offset = 0x100000; Offset < (ProbeSize * 1024);
1086		    Offset += 0x1000) {
1087		FirstMemoryVal1 = base[Offset];
1088		FirstMemoryVal2 = base[Offset+1];
1089		SecondMemoryVal1 = base[Offset+0x100];
1090		SecondMemoryVal2 = base[Offset+0x101];
1091
1092		base[Offset] = 0x55;
1093		base[Offset+1] = 0xaa;
1094		base[Offset+0x100] = 0x55;
1095		base[Offset+0x101] = 0xaa;
1096
1097		OUTREG(MGAREG_CRTC_INDEX, 0);
1098		usleep(8);
1099
1100		TestMemoryLocA = base[Offset];
1101		TestMemoryLocB = base[Offset+1];
1102		TestMemoryLoc0 = base[0];
1103		TestMemoryLoc1 = base[1];
1104
1105		base[Offset] = FirstMemoryVal1;
1106		base[Offset+1] = FirstMemoryVal2;
1107		base[Offset+0x100] = SecondMemoryVal1;
1108		base[Offset+0x101] = SecondMemoryVal2;
1109
1110		TestA = ((TestMemoryLocB << 8) + TestMemoryLocA);
1111		TestB = ((TestMemoryLoc1 << 8) + TestMemoryLoc0);
1112		if ((TestA != 0xAA55) || (TestB)) {
1113		    break;
1114		}
1115	    }
1116
1117	    base[0] = MemoryAt0;
1118	    base[1] = MemoryAt1;
1119
1120	    SizeFound = (Offset / 1024) - 64;
1121	} else {
1122	    /* write, read and compare method
1123	       split into two loops to make it more reliable on RS/6k -ReneR */
1124	    for(i = ProbeSize; i > 2048; i -= 2048) {
1125		base[(i * 1024) - 1] = 0xAA;
1126	    }
1127	    OUTREG8(MGAREG_CRTC_INDEX, 0);  /* flush the cache */
1128	    usleep(4);  /* twart write combination */
1129	    for(i = ProbeSize; i > 2048; i -= 2048) {
1130		if(base[(i * 1024) - 1] == 0xAA) {
1131		    SizeFound = i;
1132		    break;
1133		}
1134	    }
1135	}
1136
1137	/* restore CRTCEXT3 state */
1138	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1139	OUTREG8(MGAREG_CRTCEXT_DATA, tmp);
1140
1141	if (pMga->is_G200SE) {
1142	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1143	    seq1 = INREG8(MGAREG_SEQ_DATA);
1144	    seq1 &= ~0x20;
1145	    MGAWAITVSYNC();
1146	    MGAWAITBUSY();
1147	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1148	    usleep(20000);
1149	}
1150	MGAUnmapMem(pScrn);
1151    }
1152   return SizeFound;
1153}
1154
1155static xf86MonPtr
1156MGAdoDDC(ScrnInfoPtr pScrn)
1157{
1158  vgaHWPtr hwp;
1159  MGAPtr pMga;
1160  xf86MonPtr MonInfo = NULL;
1161
1162  hwp = VGAHWPTR(pScrn);
1163  pMga = MGAPTR(pScrn);
1164
1165  /* Load DDC if we have the code to use it */
1166  /* This gives us DDC1 */
1167  if (pMga->ddc1Read || pMga->i2cInit) {
1168      if (xf86LoadSubModule(pScrn, "ddc")) {
1169	  xf86LoaderReqSymLists(ddcSymbols, NULL);
1170	} else {
1171	  /* ddc module not found, we can do without it */
1172	  pMga->ddc1Read = NULL;
1173	  pMga->DDC_Bus1 = NULL;
1174	  pMga->DDC_Bus2 = NULL;
1175	  return NULL;
1176	}
1177    } else
1178      return NULL;
1179
1180#if MGAuseI2C
1181    /* - DDC can use I2C bus */
1182    /* Load I2C if we have the code to use it */
1183    if (pMga->i2cInit) {
1184      if ( xf86LoadSubModule(pScrn, "i2c") ) {
1185	xf86LoaderReqSymLists(i2cSymbols,NULL);
1186      } else {
1187	/* i2c module not found, we can do without it */
1188	pMga->i2cInit = NULL;
1189	pMga->DDC_Bus1 = NULL;
1190	pMga->DDC_Bus2 = NULL;
1191      }
1192    }
1193#endif /* MGAuseI2C */
1194
1195  /* Map the MGA memory and MMIO areas */
1196  if (!MGAMapMem(pScrn))
1197    return NULL;
1198
1199  /* Initialise the MMIO vgahw functions */
1200  vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
1201  vgaHWGetIOBase(hwp);
1202
1203  /* Map the VGA memory when the primary video */
1204  if (pMga->Primary) {
1205    hwp->MapSize = 0x10000;
1206    if (!vgaHWMapMem(pScrn))
1207      return NULL;
1208  } else {
1209    /* XXX Need to write an MGA mode ddc1SetSpeed */
1210    if (pMga->DDC1SetSpeed == vgaHWddc1SetSpeedWeak()) {
1211      pMga->DDC1SetSpeed = NULL;
1212      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
1213		     "DDC1 disabled - chip not in VGA mode\n");
1214    }
1215  }
1216
1217  /* Save the current state */
1218  MGASave(pScrn);
1219
1220  /* It is now safe to talk to the card */
1221
1222#if MGAuseI2C
1223  /* Initialize I2C buses - used by DDC if available */
1224  if (pMga->i2cInit) {
1225    pMga->i2cInit(pScrn);
1226  }
1227
1228   /* DDC for second head... */
1229  if (pMga->SecondCrtc && pMga->DDC_Bus2) {
1230    MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pMga->DDC_Bus2);
1231    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n",
1232		(void *)MonInfo);
1233    xf86PrintEDID(MonInfo);
1234    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n");
1235    xf86SetDDCproperties(pScrn, MonInfo);
1236    return MonInfo;
1237  }
1238
1239  else {
1240	/* Its the first head... */
1241	  if (pMga->DDC_Bus1) {
1242	    MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pMga->DDC_Bus1);
1243	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n", (void *) MonInfo);
1244	    xf86PrintEDID(MonInfo);
1245	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n");
1246	  }
1247	  if (!MonInfo)
1248#endif /* MGAuseI2C */
1249	  /* Read and output monitor info using DDC1 */
1250	  if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
1251	    MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex,
1252						 pMga->DDC1SetSpeed,
1253						 pMga->ddc1Read ) ;
1254	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", (void *) MonInfo);
1255	    xf86PrintEDID( MonInfo );
1256	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor info\n");
1257	  }
1258	  if (!MonInfo){
1259	    vbeInfoPtr pVbe;
1260	    if (xf86LoadSubModule(pScrn, "vbe")) {
1261	      pVbe = VBEInit(NULL,pMga->pEnt->index);
1262	      MonInfo = vbeDoEDID(pVbe, NULL);
1263	      vbeFree(pVbe);
1264
1265	      if (MonInfo){
1266		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBE DDC Monitor info: %p\n", (void *) MonInfo);
1267		xf86PrintEDID( MonInfo );
1268		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of VBE DDC Monitor info\n\n");
1269	      }
1270	    }
1271	  }
1272#if MGAuseI2C
1273   }
1274#endif
1275  /* Restore previous state and unmap MGA memory and MMIO areas */
1276  MGARestore(pScrn);
1277  MGAUnmapMem(pScrn);
1278  /* Unmap vga memory if we mapped it */
1279  if (xf86IsPrimaryPci(pMga->PciInfo) && !pMga->FBDev) {
1280    vgaHWUnmapMem(pScrn);
1281  }
1282
1283  xf86SetDDCproperties(pScrn, MonInfo);
1284
1285  return MonInfo;
1286}
1287
1288#ifdef DISABLE_VGA_IO
1289static void
1290VgaIOSave(int i, void *arg)
1291{
1292    MgaSavePtr sMga = arg;
1293#ifndef XSERVER_LIBPCIACCESS
1294    PCITAG tag = pciTag(sMga->pvp->bus,sMga->pvp->device,sMga->pvp->func);
1295#endif
1296    uint32_t temp;
1297
1298#ifdef DEBUG
1299    ErrorF("mga: VgaIOSave: %d:%d:%d\n", sMga->pvp->bus, sMga->pvp->device,
1300	   sMga->pvp->func);
1301#endif
1302#ifdef XSERVER_LIBPCIACCESS
1303    pci_device_cfg_read_u32(pMga->PciInfo, & temp, PCI_OPTION_REG);
1304#else
1305    temp = pciReadLong(tag, PCI_OPTION_REG);
1306#endif
1307    sMga->enable = (temp & 0x100) != 0;
1308}
1309
1310static void
1311VgaIORestore(int i, void *arg)
1312{
1313    MgaSavePtr sMga = arg;
1314#ifndef XSERVER_LIBPCIACCESS
1315    PCITAG tag = pciTag(sMga->pvp->bus,sMga->pvp->device,sMga->pvp->func);
1316#endif
1317
1318#ifdef DEBUG
1319    ErrorF("mga: VgaIORestore: %d:%d:%d\n", sMga->pvp->bus, sMga->pvp->device,
1320	   sMga->pvp->func);
1321#endif
1322#ifdef XSERVER_LIBPCIACCESS
1323    pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, sMga->enable,
1324			      PCI_OPTION_REG);
1325#else
1326    pciSetBitsLong(tag, PCI_OPTION_REG, 0x100, sMga->enable ? 0x100 : 0x000);
1327#endif
1328}
1329
1330static void
1331VgaIODisable(void *arg)
1332{
1333    MGAPtr pMga = arg;
1334
1335#ifdef DEBUG
1336    ErrorF("mga: VgaIODisable: %d:%d:%d, %s, xf86ResAccessEnter is %s\n",
1337	   pMga->PciInfo->bus, pMga->PciInfo->device, pMga->PciInfo->func,
1338	   pMga->Primary ? "primary" : "secondary",
1339	   BOOLTOSTRING(xf86ResAccessEnter));
1340#endif
1341    /* Turn off the vgaioen bit. */
1342#ifdef XSERVER_LIBPCIACCESS
1343    pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
1344			      PCI_OPTION_REG);
1345#else
1346    pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
1347#endif
1348}
1349
1350static void
1351VgaIOEnable(void *arg)
1352{
1353    MGAPtr pMga = arg;
1354
1355#ifdef DEBUG
1356    ErrorF("mga: VgaIOEnable: %d:%d:%d, %s, xf86ResAccessEnter is %s\n",
1357	   pMga->PciInfo->bus, pMga->PciInfo->device, pMga->PciInfo->func,
1358	   pMga->Primary ? "primary" : "secondary",
1359	   BOOLTOSTRING(xf86ResAccessEnter));
1360#endif
1361    /* Turn on the vgaioen bit. */
1362    if (pMga->Primary) {
1363#ifdef XSERVER_LIBPCIACCESS
1364	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000100,
1365				  PCI_OPTION_REG);
1366#else
1367	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x100);
1368#endif
1369    }
1370}
1371#endif /* DISABLE_VGA_IO */
1372
1373void
1374MGAProbeDDC(ScrnInfoPtr pScrn, int index)
1375{
1376    vbeInfoPtr pVbe;
1377    if (xf86LoadSubModule(pScrn, "vbe")) {
1378	pVbe = VBEInit(NULL,index);
1379	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1380	vbeFree(pVbe);
1381    }
1382}
1383
1384Bool
1385MGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
1386{
1387	MGAPtr pMga = MGAPTR(pScrn);
1388
1389	if (!pMga->Maven) return FALSE;
1390
1391	/* FIXME: Using private interfaces for the moment until a more
1392	 * flexible xf86I2CWriteRead() variant shows up for us
1393	 *
1394	 * MAVEN does _not_ like a start bit in the middle of its transaction
1395	 * MAVEN does _not_ like ACK at the end of the transaction
1396	 */
1397
1398	if (!pMga->Maven_Bus->I2CStart(pMga->Maven_Bus, pMga->Maven->ByteTimeout)) return FALSE;
1399	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, MAVEN_READ)) return FALSE;
1400	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, reg)) return FALSE;
1401	pMga->Maven_Bus->I2CStop(pMga->Maven);
1402	if (!pMga->Maven_Bus->I2CGetByte(pMga->Maven, val, 0)) return FALSE;
1403	pMga->Maven_Bus->I2CStop(pMga->Maven);
1404
1405	return TRUE;
1406}
1407
1408/* Mandatory */
1409static Bool
1410MGAPreInit(ScrnInfoPtr pScrn, int flags)
1411{
1412    MGAPtr pMga;
1413    MessageType from;
1414    int i;
1415    double real;
1416    int bytesPerPixel;
1417    ClockRangePtr clockRanges;
1418    const char *s;
1419    int flags24;
1420    MGAEntPtr pMgaEnt = NULL;
1421    Bool Default;
1422#ifdef USEMGAHAL
1423    ULONG status;
1424    CARD8 MiscCtlReg;
1425#endif
1426
1427    /*
1428     * Note: This function is only called once at server startup, and
1429     * not at the start of each server generation.  This means that
1430     * only things that are persistent across server generations can
1431     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
1432     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
1433     * are too, and should be used for data that must persist across
1434     * server generations.
1435     *
1436     * Per-generation data should be allocated with
1437     * AllocateScreenPrivateIndex() from the ScreenInit() function.
1438     */
1439
1440    /* Check the number of entities, and fail if it isn't one. */
1441    if (pScrn->numEntities != 1)
1442	return FALSE;
1443
1444
1445    pMga = MGAPTR(pScrn);
1446    /* Set here until dri is enabled */
1447#ifdef XF86DRI
1448    pMga->haveQuiescense = 1;
1449#endif
1450    /* Get the entity, and make sure it is PCI. */
1451    pMga->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1452    if (pMga->pEnt->location.type != BUS_PCI)
1453	return FALSE;
1454
1455    /* Allocate an entity private if necessary */
1456    if (xf86IsEntityShared(pScrn->entityList[0])) {
1457	pMgaEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1458					MGAEntityIndex)->ptr;
1459        pMga->entityPrivate = pMgaEnt;
1460    }
1461
1462    /* Set pMga->device to the relevant Device section */
1463    pMga->device = xf86GetDevFromEntity(pScrn->entityList[0],
1464					pScrn->entityInstanceList[0]);
1465
1466    if (flags & PROBE_DETECT) {
1467	MGAProbeDDC(pScrn, pMga->pEnt->index);
1468	return TRUE;
1469    }
1470
1471    /* The vgahw module should be loaded here when needed */
1472    if (!xf86LoadSubModule(pScrn, "vgahw"))
1473	return FALSE;
1474
1475    xf86LoaderReqSymLists(vgahwSymbols, NULL);
1476
1477    /*
1478     * Allocate a vgaHWRec
1479     */
1480    if (!vgaHWGetHWRec(pScrn))
1481	return FALSE;
1482
1483#ifndef XSERVER_LIBPCIACCESS
1484    /* Find the PCI info for this screen */
1485    pMga->PciInfo = xf86GetPciInfoForEntity(pMga->pEnt->index);
1486    pMga->PciTag = pciTag(pMga->PciInfo->bus, pMga->PciInfo->device,
1487			  pMga->PciInfo->func);
1488#endif
1489
1490    pMga->Primary = xf86IsPrimaryPci(pMga->PciInfo);
1491
1492#ifndef DISABLE_VGA_IO
1493    xf86SetOperatingState(resVgaIo, pMga->pEnt->index, ResUnusedOpr);
1494    xf86SetOperatingState(resVgaMem, pMga->pEnt->index, ResDisableOpr);
1495#else
1496    /*
1497     * Set our own access functions, which control the vgaioen bit.
1498     */
1499    pMga->Access.AccessDisable = VgaIODisable;
1500    pMga->Access.AccessEnable = VgaIOEnable;
1501    pMga->Access.arg = pMga;
1502    xf86SetAccessFuncs(pMga->pEnt, &pMga->Access, &pMga->Access);
1503#endif
1504
1505    /* Set pScrn->monitor */
1506    pScrn->monitor = pScrn->confScreen->monitor;
1507
1508    /*
1509     * Set the Chipset and ChipRev, allowing config file entries to
1510     * override.
1511     */
1512    if (pMga->device->chipset && *pMga->device->chipset) {
1513	pScrn->chipset = pMga->device->chipset;
1514        pMga->Chipset = xf86StringToToken(MGAChipsets, pScrn->chipset);
1515        from = X_CONFIG;
1516    } else if (pMga->device->chipID >= 0) {
1517	pMga->Chipset = pMga->device->chipID;
1518	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1519	from = X_CONFIG;
1520	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
1521		   pMga->Chipset);
1522    } else {
1523	from = X_PROBED;
1524	pMga->Chipset = DEVICE_ID(pMga->PciInfo);
1525	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1526    }
1527
1528    if (pMga->device->chipRev >= 0) {
1529	pMga->ChipRev = pMga->device->chipRev;
1530	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
1531		   pMga->ChipRev);
1532    } else {
1533	pMga->ChipRev = CHIP_REVISION(pMga->PciInfo);
1534    }
1535
1536    /*
1537     * This shouldn't happen because such problems should be caught in
1538     * MGAProbe(), but check it just in case.
1539     */
1540    if (pScrn->chipset == NULL) {
1541	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1542		   "ChipID 0x%04X is not recognised\n", pMga->Chipset);
1543	return FALSE;
1544    }
1545    if (pMga->Chipset < 0) {
1546	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1547		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
1548	return FALSE;
1549    }
1550
1551    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"", pScrn->chipset);
1552    if (pMga->Chipset == PCI_CHIP_MGAG400) {
1553	if (pMga->ChipRev >= 0x80)
1554	    xf86ErrorF(" (G450)\n");
1555	else
1556	    xf86ErrorF(" (G400)\n");
1557    } else {
1558	xf86ErrorF("\n");
1559    }
1560
1561    pMga->is_Gx50 = ((pMga->Chipset == PCI_CHIP_MGAG400) && (pMga->ChipRev >= 0x80))
1562	|| (pMga->Chipset == PCI_CHIP_MGAG550);
1563    pMga->is_G200SE = (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI)
1564	|| (pMga->Chipset == PCI_CHIP_MGAG200_SE_B_PCI);
1565
1566#ifdef USEMGAHAL
1567    if (pMga->chip_attribs->HAL_chipset) {
1568	Bool loadHal = TRUE;
1569
1570	from = X_DEFAULT;
1571	if (xf86FindOption(pMga->device->options, "NoHal")) {
1572	    loadHal = !xf86SetBoolOption(pMga->device->options,
1573					 "NoHal", !loadHal);
1574	    from = X_CONFIG;
1575	} else if (xf86FindOption(pMga->device->options, "Hal")) {
1576	    loadHal = xf86SetBoolOption(pMga->device->options,
1577					"Hal", loadHal);
1578	    from = X_CONFIG;
1579	}
1580        if (loadHal && xf86LoadSubModule(pScrn, "mga_hal")) {
1581	  xf86LoaderReqSymLists(halSymbols, NULL);
1582	  xf86DrvMsg(pScrn->scrnIndex, from,"Matrox HAL module used\n");
1583	  pMga->HALLoaded = TRUE;
1584	} else {
1585	  xf86DrvMsg(pScrn->scrnIndex, from, "Matrox HAL module not loaded "
1586		     "- using builtin mode setup instead\n");
1587	  pMga->HALLoaded = FALSE;
1588	}
1589    }
1590#endif
1591
1592    pMga->DualHeadEnabled = FALSE;
1593    if (xf86IsEntityShared(pScrn->entityList[0])) {/* dual-head mode requested*/
1594	if (
1595#ifdef USEMGAHAL
1596	    pMga->HALLoaded ||
1597#endif
1598	    !MGA_DH_NEEDS_HAL(pMga)) {
1599	    pMga->DualHeadEnabled = TRUE;
1600	} else if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1601	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1602	 "This card requires the \"mga_hal\" module for dual-head operation\n"
1603	 "\tIt can be found at the Matrox web site <http://www.matrox.com>\n");
1604	}
1605    }
1606
1607    /*
1608     * In case of DualHead, we need to determine if we are the 'master' head
1609     * or the 'slave' head. In order to do that, at the end of the first
1610     * initialisation, PrimInit is set as DONE to the shared entity. So that
1611     * the second initialisation knows that something has been done before it.
1612     * This always assume that the first device initialised is the master
1613     * head, and the second the slave.
1614     *
1615     */
1616    if (xf86IsEntityShared(pScrn->entityList[0])) {      /* dual-head mode */
1617        if (!xf86IsPrimInitDone(pScrn->entityList[0])) { /* Is it the first initialisation? */
1618            /* First CRTC  */
1619            pMga->SecondCrtc = FALSE;
1620            pMga->HWCursor = TRUE;
1621            pMgaEnt->pScrn_1 = pScrn;
1622        } else if (pMga->DualHeadEnabled) {
1623            /* Second CRTC */
1624            pMga->SecondCrtc = TRUE;
1625            pMga->HWCursor = FALSE;
1626            pMgaEnt->pScrn_2 = pScrn;
1627            pScrn->AdjustFrame = MGAAdjustFrameCrtc2;
1628	    /*
1629	     * Fail initialization of second head if we are in MergeFB mode,
1630	     * since we do it ourselfs.
1631             */
1632            if(pMgaEnt->pScrn_1 && MGAPTR(pMgaEnt->pScrn_1)->MergedFB) {
1633		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1634			   "Primary head in Merged framebuffer mode. \n"
1635			   "Don't let Xfree try to manage the second head.\n"
1636			   "Remove the second screen in the \"ServerLayout\"\n"
1637			   "Section of the config file.");
1638		return FALSE;
1639	    }
1640        } else {
1641	    return FALSE;
1642	}
1643    }
1644
1645    if (pMga->DualHeadEnabled) {
1646#ifdef XF86DRI
1647        pMga->GetQuiescence = MGAGetQuiescenceShared;
1648#endif
1649    } else {                                              /* single-head mode */
1650        pMga->SecondCrtc = FALSE;
1651        pMga->HWCursor = TRUE;
1652#ifdef XF86DRI
1653        pMga->GetQuiescence = MGAGetQuiescence;
1654#endif
1655    }
1656
1657
1658
1659    /*
1660     * The first thing we should figure out is the depth, bpp, etc.
1661     * Our default depth is 8, so pass it to the helper function.
1662     * We support both 24bpp and 32bpp layouts, so indicate that.
1663     */
1664
1665    /* Prefer 24bpp fb unless the Overlay option is set, or DRI is
1666     * supported.
1667     */
1668    flags24 = Support24bppFb | Support32bppFb | SupportConvert32to24;
1669    s = xf86TokenToOptName(MGAOptions, OPTION_OVERLAY);
1670#ifndef XF86DRI
1671    if (!(xf86FindOption(pScrn->confScreen->options, s) ||
1672	  xf86FindOption(pMga->device->options, s))) {
1673	flags24 |= PreferConvert32to24;
1674    }
1675#endif
1676
1677    if (pMga->SecondCrtc)
1678	flags24 = Support32bppFb;
1679
1680    if (pMga->is_G200SE)
1681	pScrn->confScreen->defaultdepth = 16;
1682
1683    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
1684	return FALSE;
1685    } else {
1686	/* Check that the returned depth is one we support */
1687	switch (pScrn->depth) {
1688	case 8:
1689	case 15:
1690	case 16:
1691	case 24:
1692	    /* OK */
1693	    break;
1694	default:
1695	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1696		       "Given depth (%d) is not supported by this driver\n",
1697		       pScrn->depth);
1698	    return FALSE;
1699	}
1700    }
1701    xf86PrintDepthBpp(pScrn);
1702
1703    /*
1704     * This must happen after pScrn->display has been set because
1705     * xf86SetWeight references it.
1706     */
1707    if (pScrn->depth > 8) {
1708	/* The defaults are OK for us */
1709	rgb zeros = {0, 0, 0};
1710
1711	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1712	    return FALSE;
1713	} else {
1714	    /* XXX check that weight returned is supported */
1715            ;
1716        }
1717    }
1718
1719    bytesPerPixel = pScrn->bitsPerPixel / 8;
1720
1721    /* We use a programmable clock */
1722    pScrn->progClock = TRUE;
1723
1724    /* Collect all of the relevant option flags (fill in pScrn->options) */
1725    xf86CollectOptions(pScrn, NULL);
1726
1727    /* Process the options */
1728    if (!(pMga->Options = xalloc(sizeof(MGAOptions))))
1729	return FALSE;
1730    memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions));
1731    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options);
1732
1733    if (pMga->is_G200SE) {
1734        /* Disable MTRR support on PCIe systems */
1735#ifdef XSERVER_LIBPCIACCESS
1736	uint32_t temp;
1737
1738	pci_device_cfg_read_u32(pMga->PciInfo, & temp, 0xDC);
1739#else
1740        CARD32 temp = pciReadLong(pMga->PciTag, 0xDC);
1741#endif
1742
1743        if ((temp & 0x0000FF00) != 0x0) {
1744            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling MTRR support.\n");
1745            pScrn->options = xf86ReplaceBoolOption(pScrn->options, "MTRR", FALSE);
1746        }
1747    }
1748
1749#if !defined(__powerpc__)
1750    pMga->softbooted = FALSE;
1751    Default = (pMga->chip_attribs->dual_head_possible
1752	       && !pMga->Primary && !pMga->SecondCrtc);
1753
1754    if (xf86ReturnOptValBool(pMga->Options, OPTION_INT10, Default) &&
1755        xf86LoadSubModule(pScrn, "int10")) {
1756        xf86Int10InfoPtr pInt;
1757
1758	xf86LoaderReqSymLists(int10Symbols, NULL);
1759        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
1760        pInt = xf86InitInt10(pMga->pEnt->index);
1761	if (pInt) pMga->softbooted = TRUE;
1762        xf86FreeInt10(pInt);
1763    }
1764#endif
1765
1766    /* Set the bits per RGB for 8bpp mode */
1767    if (pScrn->depth == 8)
1768	pScrn->rgbBits = 8;
1769
1770#ifdef XF86DRI
1771    from = X_DEFAULT;
1772    pMga->agpMode = MGA_DEFAULT_AGP_MODE;
1773
1774    if (xf86GetOptValInteger(pMga->Options,
1775			     OPTION_AGP_MODE, &(pMga->agpMode))) {
1776       if (pMga->agpMode < 1) {
1777	  pMga->agpMode = 1;
1778       }
1779       if (pMga->agpMode > MGA_MAX_AGP_MODE) {
1780	  pMga->agpMode = MGA_MAX_AGP_MODE;
1781       }
1782       from = X_CONFIG;
1783    }
1784    if (xf86GetOptValInteger(pMga->Options,
1785                             OPTION_AGP_SIZE, &(pMga->agpSize))) {
1786                             /* check later */
1787       xf86DrvMsg(pScrn->scrnIndex, from, "Using %d MB of AGP memory\n",
1788	          pMga->agpSize);
1789    }
1790
1791    xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n",
1792	       pMga->agpMode);
1793
1794    if (xf86ReturnOptValBool(pMga->Options, OPTION_OLDDMA, FALSE)) {
1795	pMga->useOldDmaInit = TRUE;
1796    }
1797
1798    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCIDMA, FALSE)) {
1799	pMga->forcePciDma = TRUE;
1800    }
1801#endif
1802
1803    from = X_DEFAULT;
1804
1805    /*
1806     * The preferred method is to use the "hw cursor" option as a tri-state
1807     * option, with the default set above.
1808     */
1809    if (xf86GetOptValBool(pMga->Options, OPTION_HW_CURSOR, &pMga->HWCursor)) {
1810	from = X_CONFIG;
1811    }
1812
1813    /* For compatibility, accept this too (as an override) */
1814    if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) {
1815	pMga->NoAccel = TRUE;
1816	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1817    } else {
1818	int from = X_DEFAULT;
1819#ifdef USE_EXA
1820	char *s = xf86GetOptValString(pMga->Options, OPTION_ACCELMETHOD);
1821#endif
1822	pMga->NoAccel = FALSE;
1823	pMga->Exa = FALSE;
1824#ifdef USE_EXA
1825	if (!xf86NameCmp(s, "EXA")) {
1826	    pMga->Exa = TRUE;
1827	    from = X_CONFIG;
1828	}
1829#endif
1830	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
1831		   pMga->Exa ? "EXA" : "XAA");
1832    }
1833    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) {
1834	pMga->UsePCIRetry = TRUE;
1835	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
1836    }
1837    if (xf86ReturnOptValBool(pMga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
1838	pMga->SyncOnGreen = TRUE;
1839	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
1840    }
1841    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHOWCACHE, FALSE)) {
1842	pMga->ShowCache = TRUE;
1843	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
1844    }
1845    if (xf86ReturnOptValBool(pMga->Options, OPTION_MGA_SDRAM, FALSE)) {
1846	pMga->HasSDRAM = TRUE;
1847	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Has SDRAM\n");
1848    }
1849    if (xf86GetOptValFreq(pMga->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
1850	pMga->MemClk = (int)(real * 1000.0);
1851    }
1852    if ((s = xf86GetOptValString(pMga->Options, OPTION_OVERLAY))) {
1853      if (!*s || !xf86NameCmp(s, "8,24") || !xf86NameCmp(s, "24,8")) {
1854	if(pScrn->bitsPerPixel == 32 && pMga->SecondCrtc == FALSE) {
1855	    pMga->Overlay8Plus24 = TRUE;
1856	    if(!xf86GetOptValInteger(
1857			pMga->Options, OPTION_COLOR_KEY,&(pMga->colorKey)))
1858		pMga->colorKey = TRANSPARENCY_KEY;
1859	    pScrn->colorKey = pMga->colorKey;
1860	    pScrn->overlayFlags = OVERLAY_8_32_PLANAR;
1861	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1862				"PseudoColor overlay enabled\n");
1863	} else {
1864	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1865	         "Option \"Overlay\" is only supported in 32 bits per pixel on"
1866		 "the first CRTC\n");
1867	}
1868      } else {
1869	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1870		"\"%s\" is not a valid value for Option \"Overlay\"\n", s);
1871      }
1872    }
1873
1874    if(xf86GetOptValInteger(pMga->Options, OPTION_VIDEO_KEY, &(pMga->videoKey))) {
1875	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1876				pMga->videoKey);
1877    } else {
1878	pMga->videoKey =  (1 << pScrn->offset.red) |
1879			  (1 << pScrn->offset.green) |
1880        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
1881    }
1882    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHADOW_FB, FALSE)) {
1883	pMga->ShadowFB = TRUE;
1884	pMga->NoAccel = TRUE;
1885	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1886		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
1887    }
1888    if (xf86ReturnOptValBool(pMga->Options, OPTION_FBDEV, FALSE)) {
1889	pMga->FBDev = TRUE;
1890	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1891		"Using framebuffer device\n");
1892    }
1893    if (xf86ReturnOptValBool(pMga->Options, OPTION_OVERCLOCK_MEM, FALSE)) {
1894	pMga->OverclockMem = TRUE;
1895	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overclocking memory\n");
1896    }
1897    if (xf86ReturnOptValBool(pMga->Options, OPTION_TEXTURED_VIDEO, FALSE)) {
1898	pMga->TexturedVideo = TRUE;
1899    }
1900    if (xf86ReturnOptValBool(pMga->Options, OPTION_MERGEDFB, FALSE)) {
1901        if(!MGAISGx50(pMga)) {
1902            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1903                "\"Merged Framebuffer\" mode only supported on G450 and G550 boards.\n");
1904        } else {
1905#ifdef USEMGAHAL
1906            if(pMga->HALLoaded)
1907            {
1908                pMga->MergedFB = TRUE;
1909                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1910                        "Using \"Merged Framebuffer\" mode.\n");
1911                /*
1912                * a few options that won't work well together
1913                */
1914                if(pMga->HWCursor) /*Should we give the choice? */
1915                    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1916                        " -- Hardware Cursor disabled.\n");
1917                pMga->HWCursor = FALSE;
1918                if(pMga->ShadowFB)
1919                    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1920                        " -- Shadow Framebuffer disabled.\n");
1921                pMga->ShadowFB = FALSE;
1922                if(pMga->FBDev)
1923                    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1924                        " -- Framebuffer device disabled.\n");
1925                pMga->FBDev = FALSE;
1926            } /* MGA_HAL */
1927            else
1928#endif
1929            {
1930                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1931                    "HALLib not loaded! NOT using \"Merged Framebuffer\" mode.\n");
1932            } /* MGA_NOT_HAL */
1933        } /* ISMGAGx50() */
1934    }
1935    if (pMga->FBDev) {
1936	/* check for linux framebuffer device */
1937	if (!xf86LoadSubModule(pScrn, "fbdevhw"))
1938	    return FALSE;
1939	xf86LoaderReqSymLists(fbdevHWSymbols, NULL);
1940	if (!fbdevHWInit(pScrn, pMga->PciInfo, NULL))
1941	    return FALSE;
1942	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
1943	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
1944	pScrn->EnterVT       = MGAEnterVTFBDev;
1945	pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
1946	pScrn->ValidMode     = fbdevHWValidModeWeak();
1947    }
1948    pMga->Rotate = 0;
1949    if ((s = xf86GetOptValString(pMga->Options, OPTION_ROTATE))) {
1950        if(!pMga->MergedFB) {
1951            if(!xf86NameCmp(s, "CW")) {
1952                pMga->ShadowFB = TRUE;
1953                pMga->NoAccel = TRUE;
1954                pMga->HWCursor = FALSE;
1955                pMga->Rotate = 1;
1956                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1957                        "Rotating screen clockwise - acceleration disabled\n");
1958            } else
1959            if(!xf86NameCmp(s, "CCW")) {
1960                pMga->ShadowFB = TRUE;
1961                pMga->NoAccel = TRUE;
1962                pMga->HWCursor = FALSE;
1963                pMga->Rotate = -1;
1964                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1965                        "Rotating screen counter clockwise - acceleration disabled\n");
1966            } else {
1967                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1968                        "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
1969                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1970                        "Valid options are \"CW\" or \"CCW\"\n");
1971            }
1972        } else {
1973            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1974                " -- Rotation disabled.\n");
1975        }
1976    }
1977
1978    switch (pMga->Chipset) {
1979    case PCI_CHIP_MGA2064:
1980    case PCI_CHIP_MGA2164:
1981    case PCI_CHIP_MGA2164_AGP:
1982	MGA2064SetupFuncs(pScrn);
1983	break;
1984    case PCI_CHIP_MGA1064:
1985    case PCI_CHIP_MGAG100:
1986    case PCI_CHIP_MGAG100_PCI:
1987    case PCI_CHIP_MGAG200:
1988    case PCI_CHIP_MGAG200_PCI:
1989    case PCI_CHIP_MGAG200_SE_A_PCI:
1990    case PCI_CHIP_MGAG200_SE_B_PCI:
1991    case PCI_CHIP_MGAG400:
1992    case PCI_CHIP_MGAG550:
1993	MGAGSetupFuncs(pScrn);
1994	break;
1995    }
1996
1997    /* ajv changes to reflect actual values. see sdk pp 3-2. */
1998    /* these masks just get rid of the crap in the lower bits */
1999
2000    /* For the 2064 and older rev 1064, base0 is the MMIO and base1 is
2001     * the framebuffer.
2002     */
2003
2004    switch (pMga->chip_attribs->BARs) {
2005    case old_BARs:
2006	pMga->framebuffer_bar = 1;
2007	pMga->io_bar = 0;
2008	pMga->iload_bar = -1;
2009	break;
2010    case probe_BARs:
2011	if (pMga->ChipRev < 3) {
2012	    pMga->framebuffer_bar = 1;
2013	    pMga->io_bar = 0;
2014	    pMga->iload_bar = 2;
2015	    break;
2016	}
2017	/* FALLTHROUGH */
2018    case new_BARs:
2019	pMga->framebuffer_bar = 0;
2020	pMga->io_bar = 1;
2021	pMga->iload_bar = 2;
2022	break;
2023    }
2024
2025
2026#ifdef XSERVER_LIBPCIACCESS
2027    pMga->FbAddress = pMga->PciInfo->regions[pMga->framebuffer_bar].base_addr;
2028#else
2029    pMga->FbAddress = pMga->PciInfo->memBase[pMga->framebuffer_bar] & 0xff800000;
2030#endif
2031
2032    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n",
2033	       (unsigned long)pMga->FbAddress);
2034
2035#ifdef XSERVER_LIBPCIACCESS
2036    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lX\n",
2037	       (unsigned long) pMga->PciInfo->regions[pMga->io_bar].base_addr);
2038#else
2039    pMga->IOAddress = pMga->PciInfo->memBase[pMga->io_bar] & 0xffffc000;
2040
2041    xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
2042	       (unsigned long)pMga->IOAddress);
2043#endif
2044
2045    if (pMga->iload_bar != -1) {
2046#ifdef XSERVER_LIBPCIACCESS
2047	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2048		   "Pseudo-DMA transfer window at 0x%lX\n",
2049		   (unsigned long) pMga->PciInfo->regions[pMga->iload_bar].base_addr);
2050#else
2051	if (pMga->PciInfo->memBase[2] != 0) {
2052	    pMga->ILOADAddress = pMga->PciInfo->memBase[2] & 0xffffc000;
2053	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2054		       "Pseudo-DMA transfer window at 0x%lX\n",
2055		       (unsigned long)pMga->ILOADAddress);
2056	}
2057#endif
2058    }
2059
2060
2061#ifndef XSERVER_LIBPCIACCESS
2062    /*
2063     * Find the BIOS base.  Get it from the PCI config if possible.  Otherwise
2064     * use the VGA default.  Allow the config file to override this.
2065     */
2066
2067    pMga->BiosFrom = X_NONE;
2068    if (pMga->device->BiosBase != 0) {
2069	/* XXX This isn't used */
2070	pMga->BiosAddress = pMga->device->BiosBase;
2071	pMga->BiosFrom = X_CONFIG;
2072    } else {
2073	/* details: rombase sdk pp 4-15 */
2074	if (pMga->PciInfo->biosBase != 0) {
2075	    pMga->BiosAddress = pMga->PciInfo->biosBase & 0xffff0000;
2076	    pMga->BiosFrom = X_PROBED;
2077	} else if (pMga->Primary) {
2078	    pMga->BiosAddress = 0xc0000;
2079	    pMga->BiosFrom = X_DEFAULT;
2080	}
2081    }
2082    if (pMga->BiosAddress) {
2083	xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom, "BIOS at 0x%lX\n",
2084		   (unsigned long)pMga->BiosAddress);
2085    }
2086#endif
2087
2088
2089    if (xf86RegisterResources(pMga->pEnt->index, NULL, ResExclusive)) {
2090	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2091		"xf86RegisterResources() found resource conflicts\n");
2092	MGAFreeRec(pScrn);
2093	return FALSE;
2094    }
2095
2096    /*
2097     * Read the BIOS data struct
2098     */
2099
2100#if defined(__alpha__) && !defined(XSERVER_LIBPCIACCESS)
2101    /*
2102     * Some old Digital-OEMed Matrox Millennium I cards have a VGA
2103     * disable switch.  If the disable is on, we can't read the BIOS,
2104     * and pMga->BiosAddress = 0x0. The disable switch is needed to
2105     * allow multi-head operation with brain-dead console code... ;-}
2106     */
2107
2108    if ((pMga->BiosAddress == 0) && !xf86IsPrimaryPci(pMga->PciInfo))
2109        xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom,
2110                   "BIOS not found, skipping read\n");
2111    else
2112#endif
2113    mga_read_and_process_bios( pScrn );
2114
2115
2116    /* Since the BIOS can swap DACs during the initialisation of G550, we need to
2117     * store which DAC this instance of the driver is taking care of. This is done
2118     * by checking a flag stored in the ROM by the BIOS at a fixed address. */
2119
2120    if (!pMga->SecondCrtc)
2121        pMga->SecondOutput = FALSE;
2122    else
2123        pMga->SecondOutput = TRUE;
2124
2125    if (pMga->Chipset == PCI_CHIP_MGAG550) {
2126        if (!pMga->SecondCrtc) {
2127            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? TRUE : FALSE;
2128        } else {
2129            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? FALSE : TRUE;
2130        }
2131    }
2132
2133
2134    /* HW bpp matches reported bpp */
2135    pMga->HwBpp = pScrn->bitsPerPixel;
2136
2137    /*
2138     * Reset card if it isn't primary one
2139     */
2140    if ( (!pMga->Primary && !pMga->FBDev) || xf86IsPc98() )
2141        MGASoftReset(pScrn);
2142
2143    /*
2144     * If the user has specified the amount of memory in the XF86Config
2145     * file, we respect that setting.
2146     */
2147    from = X_PROBED;
2148    if (pMga->device->videoRam != 0) {
2149	pScrn->videoRam = pMga->device->videoRam;
2150	from = X_CONFIG;
2151    } else if (pMga->FBDev) {
2152	pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024;
2153    } else {
2154	pScrn->videoRam = MGACountRam(pScrn);
2155    }
2156
2157    if (pScrn->videoRam == 0) {
2158	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2159		   "Unable to detect video RAM.\n");
2160	return FALSE;
2161    }
2162
2163    if (pMga->DualHeadEnabled) {
2164       /* This takes gives either half or 8 meg to the second head
2165	* whichever is less. */
2166        if(pMga->SecondCrtc == FALSE) {
2167	    Bool UseHalf = FALSE;
2168	    int adjust;
2169
2170	    xf86GetOptValBool(pMga->Options, OPTION_CRTC2HALF, &UseHalf);
2171	    adjust = pScrn->videoRam / 2;
2172
2173	    if (UseHalf == TRUE ||
2174		  xf86GetOptValInteger(pMga->Options, OPTION_CRTC2RAM, &adjust)) {
2175	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2176			   "Crtc2 will use %dK of VideoRam\n",
2177			   adjust);
2178	    } else {
2179	        adjust = min(adjust, 8192);
2180	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2181			   "Crtc2 will use %dK of VideoRam\n",
2182			   adjust);
2183	    }
2184	    pMgaEnt->mastervideoRam = pScrn->videoRam - adjust;
2185	    pScrn->videoRam = pMgaEnt->mastervideoRam;
2186	    pMgaEnt->slavevideoRam = adjust;
2187	    pMgaEnt->masterFbAddress = pMga->FbAddress;
2188	    pMga->FbMapSize =
2189	       pMgaEnt->masterFbMapSize = pScrn->videoRam * 1024;
2190	    pMgaEnt->slaveFbAddress = pMga->FbAddress +
2191	       pMgaEnt->masterFbMapSize;
2192	    pMgaEnt->slaveFbMapSize = pMgaEnt->slavevideoRam * 1024;
2193	    pMga->realSrcOrg = pMga->SrcOrg = 0;
2194	    pMga->DstOrg = 0;
2195	} else {
2196	    pMga->FbAddress = pMgaEnt->slaveFbAddress;
2197	    pMga->FbMapSize = pMgaEnt->slaveFbMapSize;
2198	    pScrn->videoRam = pMgaEnt->slavevideoRam;
2199	    pMga->DstOrg = pMga->realSrcOrg =
2200	      pMgaEnt->slaveFbAddress - pMgaEnt->masterFbAddress;
2201	    pMga->SrcOrg = 0; /* This is not stored in hw format!! */
2202	}
2203        pMgaEnt->refCount++;
2204    } else {
2205        /* Normal Handling of video ram etc */
2206        pMga->FbMapSize = pScrn->videoRam * 1024;
2207        switch(pMga->Chipset) {
2208	  case PCI_CHIP_MGAG550:
2209	  case PCI_CHIP_MGAG400:
2210	  case PCI_CHIP_MGAG200:
2211	  case PCI_CHIP_MGAG200_PCI:
2212	  case PCI_CHIP_MGAG200_SE_A_PCI:
2213	  case PCI_CHIP_MGAG200_SE_B_PCI:
2214	    pMga->SrcOrg = 0;
2215	    pMga->DstOrg = 0;
2216	    break;
2217	  default:
2218	    break;
2219	}
2220    }
2221    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
2222               pScrn->videoRam);
2223
2224   /* Set the bpp shift value */
2225    pMga->BppShifts[0] = 0;
2226    pMga->BppShifts[1] = 1;
2227    pMga->BppShifts[2] = 0;
2228    pMga->BppShifts[3] = 2;
2229
2230    /*
2231     * fill MGAdac struct
2232     * Warning: currently, it should be after RAM counting
2233     */
2234    (*pMga->PreInit)(pScrn);
2235
2236#if !defined(__powerpc__)
2237
2238    /* Read and print the Monitor DDC info */
2239    pScrn->monitor->DDC = MGAdoDDC(pScrn);
2240#endif /* !__powerpc__ */
2241
2242    if (!pScrn->monitor->DDC && pMga->is_G200SE) {
2243	/* Jam in ranges big enough for 1024x768 */
2244	if (!pScrn->monitor->nHsync) {
2245	    pScrn->monitor->nHsync = 1;
2246	    pScrn->monitor->hsync[0].lo = 31.5;
2247	    pScrn->monitor->hsync[0].hi = 48.0;
2248	}
2249	if (!pScrn->monitor->nVrefresh) {
2250	    pScrn->monitor->nVrefresh = 1;
2251	    pScrn->monitor->vrefresh[0].lo = 56.0;
2252	    pScrn->monitor->vrefresh[0].hi = 75.0;
2253	}
2254    }
2255
2256
2257    /*
2258     * If the driver can do gamma correction, it should call xf86SetGamma()
2259     * here.
2260     */
2261
2262    {
2263	Gamma zeros = {0.0, 0.0, 0.0};
2264
2265	if (!xf86SetGamma(pScrn, zeros)) {
2266	    return FALSE;
2267	}
2268    }
2269
2270
2271    /* XXX Set HW cursor use */
2272
2273    /* Set the min pixel clock */
2274    pMga->MinClock = 17750;
2275    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
2276	       pMga->MinClock / 1000);
2277    /*
2278     * If the user has specified ramdac speed in the XF86Config
2279     * file, we respect that setting.
2280     */
2281    if (pMga->device->dacSpeeds[0]) {
2282	int speed = 0;
2283
2284	switch (pScrn->bitsPerPixel) {
2285	case 8:
2286	   speed = pMga->device->dacSpeeds[DAC_BPP8];
2287	   break;
2288	case 16:
2289	   speed = pMga->device->dacSpeeds[DAC_BPP16];
2290	   break;
2291	case 24:
2292	   speed = pMga->device->dacSpeeds[DAC_BPP24];
2293	   break;
2294	case 32:
2295	   speed = pMga->device->dacSpeeds[DAC_BPP32];
2296	   break;
2297	}
2298	if (speed == 0)
2299	    pMga->MaxClock = pMga->device->dacSpeeds[0];
2300	else
2301	    pMga->MaxClock = speed;
2302	from = X_CONFIG;
2303    } else {
2304	pMga->MaxClock = pMga->Dac.maxPixelClock;
2305	from = pMga->Dac.ClockFrom;
2306    }
2307    if(pMga->SecondCrtc == TRUE) {
2308        /* Override on 2nd crtc */
2309	if ((pMga->ChipRev >= 0x80) || (pMga->Chipset == PCI_CHIP_MGAG550)) {
2310	    /* G450, G550 */
2311	    pMga->MaxClock = 234000;
2312	} else {
2313	    pMga->MaxClock = 135000;
2314	}
2315    }
2316    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
2317	       pMga->MaxClock / 1000);
2318    /*
2319     * Setup the ClockRanges, which describe what clock ranges are available,
2320     * and what sort of modes they can be used for.
2321     */
2322    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
2323    clockRanges->next = NULL;
2324    clockRanges->minClock = pMga->MinClock;
2325    clockRanges->maxClock = pMga->MaxClock;
2326    clockRanges->clockIndex = -1;		/* programmable */
2327    clockRanges->interlaceAllowed = TRUE;
2328    clockRanges->doubleScanAllowed = TRUE;
2329#ifdef USEMGAHAL
2330    MGA_HAL(clockRanges->interlaceAllowed = FALSE);
2331    MGA_HAL(clockRanges->doubleScanAllowed = FALSE);
2332#endif
2333    if (pMga->SecondCrtc == TRUE)
2334	clockRanges->interlaceAllowed = FALSE;
2335
2336    clockRanges->ClockMulFactor = 1;
2337    clockRanges->ClockDivFactor = 1;
2338
2339    /* Only set MemClk if appropriate for the ramdac */
2340    if (pMga->Dac.SetMemClk) {
2341	if (pMga->MemClk == 0) {
2342	    pMga->MemClk = pMga->Dac.MemoryClock;
2343	    from = pMga->Dac.MemClkFrom;
2344	} else
2345	    from = X_CONFIG;
2346	xf86DrvMsg(pScrn->scrnIndex, from, "MCLK used is %.1f MHz\n",
2347		   pMga->MemClk / 1000.0);
2348    }
2349
2350    /*
2351     * xf86ValidateModes will check that the mode HTotal and VTotal values
2352     * don't exceed the chipset's limit if pScrn->maxHValue and
2353     * pScrn->maxVValue are set.  Since our MGAValidMode() already takes
2354     * care of this, we don't worry about setting them here.
2355     */
2356    {
2357	int Pitches1[] =
2358	  {640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
2359	int Pitches2[] =
2360	  {512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664,
2361		1920, 2048, 0};
2362	int *linePitches = NULL;
2363	int minPitch = 256;
2364	int maxPitch = 2048;
2365
2366        switch(pMga->Chipset) {
2367	case PCI_CHIP_MGA2064:
2368	   if (!pMga->NoAccel) {
2369		linePitches = xalloc(sizeof(Pitches1));
2370		memcpy(linePitches, Pitches1, sizeof(Pitches1));
2371		minPitch = maxPitch = 0;
2372	   }
2373	   break;
2374	case PCI_CHIP_MGA2164:
2375	case PCI_CHIP_MGA2164_AGP:
2376	case PCI_CHIP_MGA1064:
2377	   if (!pMga->NoAccel) {
2378		linePitches = xalloc(sizeof(Pitches2));
2379		memcpy(linePitches, Pitches2, sizeof(Pitches2));
2380		minPitch = maxPitch = 0;
2381	   }
2382	   break;
2383	case PCI_CHIP_MGAG100:
2384	case PCI_CHIP_MGAG100_PCI:
2385	   maxPitch = 2048;
2386	   break;
2387	case PCI_CHIP_MGAG200:
2388	case PCI_CHIP_MGAG200_PCI:
2389	case PCI_CHIP_MGAG200_SE_A_PCI:
2390	case PCI_CHIP_MGAG200_SE_B_PCI:
2391	case PCI_CHIP_MGAG400:
2392	case PCI_CHIP_MGAG550:
2393	   maxPitch = 4096;
2394	   break;
2395	}
2396
2397	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2398			      pScrn->display->modes, clockRanges,
2399			      linePitches, minPitch, maxPitch,
2400			      pMga->Roundings[(pScrn->bitsPerPixel >> 3) - 1] *
2401					pScrn->bitsPerPixel, 128, 2048,
2402			      pScrn->display->virtualX,
2403			      pScrn->display->virtualY,
2404			      pMga->FbMapSize,
2405			      LOOKUP_BEST_REFRESH);
2406
2407	if (linePitches)
2408	   xfree(linePitches);
2409    }
2410
2411
2412    if (i < 1 && pMga->FBDev) {
2413	fbdevHWUseBuildinMode(pScrn);
2414	pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
2415	i = 1;
2416    }
2417    if (i == -1) {
2418	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
2419	MGAFreeRec(pScrn);
2420	return FALSE;
2421    }
2422
2423    /* Prune the modes marked as invalid */
2424    xf86PruneDriverModes(pScrn);
2425
2426    if (i == 0 || pScrn->modes == NULL) {
2427	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2428	MGAFreeRec(pScrn);
2429	return FALSE;
2430    }
2431#ifdef USEMGAHAL
2432    MGA_HAL(
2433
2434    if(pMga->SecondCrtc == FALSE) {
2435
2436        pMga->pBoard = xalloc(sizeof(CLIENTDATA) + MGAGetBOARDHANDLESize());
2437        pMga->pClientStruct = xalloc(sizeof(CLIENTDATA));
2438        pMga->pClientStruct->pMga = (MGAPtr) pMga;
2439
2440        MGAMapMem(pScrn);
2441	/*
2442	 * For some reason the MGAOPM_DMA_BLIT bit needs to be set
2443	 * on G200 before opening the HALlib. I don't know why.
2444	 * MATROX: hint, hint.
2445	 */
2446	/*if (pMga->Chipset == PCI_CHIP_MGAG200 ||
2447	  pMga->Chipset == PCI_CHIP_MGAG200_PCI) */{
2448	    CARD32 opmode;
2449	    opmode = INREG(MGAREG_OPMODE);
2450	    OUTREG(MGAREG_OPMODE,  MGAOPM_DMA_BLIT | opmode);
2451	}
2452	/* wrapping OpenLibrary to fix broken registers. MATROX: hint, hint. */
2453	MiscCtlReg = inMGAdac(MGA1064_MISC_CTL);
2454        MGAOpenLibrary(pMga->pBoard,pMga->pClientStruct,sizeof(CLIENTDATA));
2455	outMGAdac(MGA1064_MISC_CTL,MiscCtlReg);
2456        MGAUnmapMem(pScrn);
2457        pMga->pMgaHwInfo = xalloc(sizeof(MGAHWINFO));
2458        MGAGetHardwareInfo(pMga->pBoard,pMga->pMgaHwInfo);
2459
2460        /* copy the board handles */
2461        if (pMga->DualHeadEnabled) {
2462            pMgaEnt->pClientStruct = pMga->pClientStruct;
2463            pMgaEnt->pBoard = pMga->pBoard;
2464            pMgaEnt->pMgaHwInfo = pMga->pMgaHwInfo;
2465        }
2466
2467    } else { /* Second CRTC && entity is shared */
2468        pMga->pBoard = pMgaEnt->pBoard;
2469        pMga->pClientStruct = pMgaEnt->pClientStruct;
2470        pMga->pMgaHwInfo = pMgaEnt->pMgaHwInfo;
2471
2472    }
2473
2474    MGAFillModeInfoStruct(pScrn,NULL);
2475    /* Fields usually handled by MGAFillModeInfoStruct, but are unavailable
2476     * because no mode is given
2477     */
2478    pMga->pMgaModeInfo->ulDispWidth = pScrn->virtualX;
2479    pMga->pMgaModeInfo->ulDispHeight = pScrn->virtualY;
2480
2481
2482    if (ISDIGITAL1(pMga))
2483        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2484                    "Digital screen detected on first head.\n");
2485    if (ISTV1(pMga))
2486        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2487                    "TV detected on first head.\n");
2488    if (ISDIGITAL2(pMga))
2489        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2490                    "Digital screen detected on second head.\n");
2491    if (ISTV2(pMga))
2492        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2493                    "TV detected on second head.\n");
2494
2495
2496    if((status = MGAValidateMode(pMga->pBoard,pMga->pMgaModeInfo)) != 0) {
2497	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2498		   "MGAValidateMode from HALlib found the mode to be invalid.\n"
2499		   "\tError: 0x%lx\n", status);
2500        return FALSE;
2501    }
2502    pScrn->displayWidth = pMga->pMgaModeInfo->ulFBPitch;
2503    );	/* MGA_HAL */
2504#endif
2505
2506    /* If the Device section explicitly set HasSDRAM, don't bother checking.
2507     */
2508    if (!pMga->HasSDRAM) {
2509	if ((pMga->softbooted || pMga->Primary)
2510	     && pMga->chip_attribs->probe_for_sdram) {
2511	    uint32_t option_reg;
2512
2513#ifdef XSERVER_LIBPCIACCESS
2514	    pci_device_cfg_read_u32(pMga->PciInfo, & option_reg,
2515				    PCI_OPTION_REG);
2516#else
2517	    option_reg = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
2518#endif
2519	    pMga->HasSDRAM = ((option_reg & (1 << 14)) == 0);
2520	}
2521	else {
2522	    pMga->HasSDRAM = pMga->chip_attribs->has_sdram;
2523	}
2524
2525	if (pMga->HasSDRAM) {
2526	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Has SDRAM\n");
2527	}
2528    }
2529
2530    /*
2531     * Set the CRTC parameters for all of the modes based on the type
2532     * of mode, and the chipset's interlace requirements.
2533     *
2534     * Calling this is required if the mode->Crtc* values are used by the
2535     * driver and if the driver doesn't provide code to set them.  They
2536     * are not pre-initialised at all.
2537     */
2538#ifdef USEMGAHAL
2539    MGA_HAL(xf86SetCrtcForModes(pScrn, 0));
2540#endif
2541    MGA_NOT_HAL(xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V));
2542
2543    /* Set the current mode to the first in the list */
2544    pScrn->currentMode = pScrn->modes;
2545
2546    /* Print the list of modes being used */
2547    xf86PrintModes(pScrn);
2548
2549    /* Set display resolution */
2550    xf86SetDpi(pScrn, 0, 0);
2551
2552    /*
2553     * Compute the byte offset into the linear frame buffer where the
2554     * frame buffer data should actually begin.  According to DDK misc.c
2555     * line 1023, if more than 4MB is to be displayed, YDSTORG must be set
2556     * appropriately to align memory bank switching, and this requires a
2557     * corresponding offset on linear frame buffer access.
2558     * This is only needed for WRAM.
2559     */
2560
2561    pMga->YDstOrg = 0;
2562    if (pMga->chip_attribs->fb_4mb_quirk &&
2563	(pScrn->virtualX * pScrn->virtualY * bytesPerPixel > 4*1024*1024)) {
2564	int offset;
2565	int offset_modulo = (pScrn->bitsPerPixel == 24) ? 12 : 4;
2566	int ydstorg_modulo = 64;
2567
2568
2569	if (pMga->Interleave) {
2570	    offset_modulo <<= 1;
2571	    ydstorg_modulo <<= 1;
2572	}
2573
2574	offset = (4*1024*1024) % (pScrn->displayWidth * bytesPerPixel);
2575	pMga->YDstOrg = offset / bytesPerPixel;
2576
2577	/*
2578	 * When this was unconditional, it caused a line of horizontal garbage
2579	 * at the middle right of the screen at the 4Meg boundary in 32bpp
2580	 * (and presumably any other modes that use more than 4M). But it's
2581	 * essential for 24bpp (it may not matter either way for 8bpp & 16bpp,
2582	 * I'm not sure; I didn't notice problems when I checked with and
2583	 * without.)
2584	 * DRM Doug Merritt 12/97, submitted to XFree86 6/98 (oops)
2585	 */
2586	if (bytesPerPixel < 4) {
2587	    while ((offset % offset_modulo) != 0 ||
2588		   (pMga->YDstOrg % ydstorg_modulo) != 0) {
2589		offset++;
2590		pMga->YDstOrg = offset / bytesPerPixel;
2591	    }
2592	}
2593    }
2594
2595    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "YDstOrg is set to %d\n",
2596		   pMga->YDstOrg);
2597    if(pMga->DualHeadEnabled) {
2598        if(pMga->SecondCrtc == FALSE) {
2599	    pMga->FbUsableSize = pMgaEnt->masterFbMapSize;
2600            /* Allocate HW cursor buffer at the end of video ram */
2601	    if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2602	        if( pScrn->virtualY * pScrn->displayWidth *
2603		    pScrn->bitsPerPixel / 8 <=
2604		    pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2605		    pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2606		    pMga->FbCursorOffset =
2607		      pMgaEnt->masterFbMapSize -
2608		      pMga->Dac.CursorOffscreenMemSize;
2609		} else {
2610		    pMga->HWCursor = FALSE;
2611		    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2612			       "Too little offscreen memory for HW cursor; "
2613			       "using SW cursor\n");
2614		}
2615	    }
2616	} else { /* Second CRTC */
2617	    pMga->FbUsableSize = pMgaEnt->slaveFbMapSize;
2618	    pMga->HWCursor = FALSE;
2619	}
2620    } else {
2621        pMga->FbUsableSize = pMga->FbMapSize - pMga->YDstOrg * bytesPerPixel;
2622           /* Allocate HW cursor buffer at the end of video ram */
2623        if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2624	    if( pScrn->virtualY * pScrn->displayWidth *
2625	        pScrn->bitsPerPixel / 8 <=
2626        	pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2627	        pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2628	        pMga->FbCursorOffset =
2629		  pMga->FbMapSize - pMga->Dac.CursorOffscreenMemSize;
2630	    } else {
2631	        pMga->HWCursor = FALSE;
2632	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2633			   "Too little offscreen memory for HW cursor; "
2634			   "using SW cursor\n");
2635	    }
2636	}
2637    }
2638    /*
2639     * XXX This should be taken into account in some way in the mode valdation
2640     * section.
2641     */
2642
2643
2644    /* Load the required framebuffer */
2645    if (pMga->Overlay8Plus24) {
2646	if (!xf86LoadSubModule(pScrn, "xf8_32bpp")) {
2647	    MGAFreeRec(pScrn);
2648	    return FALSE;
2649	}
2650	xf86LoaderReqSymLists(xf8_32bppSymbols, NULL);
2651    } else {
2652	if (!xf86LoadSubModule(pScrn, "fb")) {
2653	    MGAFreeRec(pScrn);
2654	    return FALSE;
2655	}
2656	xf86LoaderReqSymLists(fbSymbols, NULL);
2657    }
2658
2659
2660    /* Load XAA if needed */
2661    if (!pMga->NoAccel) {
2662#ifdef USE_EXA
2663	if (pMga->Exa) {
2664	    if (!xf86LoadSubModule(pScrn, "exa")) {
2665		MGAFreeRec(pScrn);
2666		return FALSE;
2667	    } else xf86LoaderReqSymLists(exaSymbols, NULL);
2668	} else {
2669#endif
2670#ifdef USE_XAA
2671	    if (!xf86LoadSubModule(pScrn, "xaa")) {
2672		MGAFreeRec(pScrn);
2673		return FALSE;
2674	    } else xf86LoaderReqSymLists(xaaSymbols, NULL);
2675#endif
2676#ifdef USE_EXA
2677	}
2678#endif
2679    }
2680
2681    /* Load ramdac if needed */
2682    if (pMga->HWCursor) {
2683	if (!xf86LoadSubModule(pScrn, "ramdac")) {
2684	    MGAFreeRec(pScrn);
2685	    return FALSE;
2686	}
2687	xf86LoaderReqSymLists(ramdacSymbols, NULL);
2688    }
2689
2690    /* Load shadowfb if needed */
2691    if (pMga->ShadowFB) {
2692	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2693	    MGAFreeRec(pScrn);
2694	    return FALSE;
2695	}
2696	xf86LoaderReqSymLists(shadowSymbols, NULL);
2697    }
2698
2699#ifdef XF86DRI
2700    /* Load the dri module if requested. */
2701    if (xf86ReturnOptValBool(pMga->Options, OPTION_DRI, FALSE)) {
2702       if (xf86LoadSubModule(pScrn, "dri")) {
2703	  xf86LoaderReqSymLists(driSymbols, drmSymbols, NULL);
2704       }
2705    }
2706#endif
2707    pMga->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
2708    pMga->CurrentLayout.depth = pScrn->depth;
2709    pMga->CurrentLayout.displayWidth = pScrn->displayWidth;
2710    pMga->CurrentLayout.weight.red = pScrn->weight.red;
2711    pMga->CurrentLayout.weight.green = pScrn->weight.green;
2712    pMga->CurrentLayout.weight.blue = pScrn->weight.blue;
2713    pMga->CurrentLayout.Overlay8Plus24 = pMga->Overlay8Plus24;
2714    pMga->CurrentLayout.mode = pScrn->currentMode;
2715
2716
2717
2718    if(pMga->MergedFB) {
2719        MGAPreInitMergedFB(pScrn,flags);
2720    };
2721
2722
2723#ifdef USEMGAHAL
2724    MGA_HAL(
2725    /* Close the library after preinit */
2726    /* This needs to only happen after this board has completed preinit
2727     * both times
2728     */
2729
2730      if(pMga->DualHeadEnabled) {
2731	  /* Entity is shared make sure refcount == 2 */
2732	  /* If ref count is 2 then reset it to 0 */
2733	  if(pMgaEnt->refCount == 2) {
2734	      /* Both boards have done there initialization */
2735	      MGACloseLibrary(pMga->pBoard);
2736
2737	      if (pMga->pBoard)
2738	        xfree(pMga->pBoard);
2739	      if (pMga->pClientStruct)
2740	        xfree(pMga->pClientStruct);
2741	      if (pMga->pMgaModeInfo)
2742	        xfree(pMga->pMgaModeInfo);
2743	      if (pMga->pMgaHwInfo)
2744	        xfree(pMga->pMgaHwInfo);
2745	      pMgaEnt->refCount = 0;
2746	  }
2747      } else {
2748	  MGACloseLibrary(pMga->pBoard);
2749
2750	  if (pMga->pBoard)
2751	    xfree(pMga->pBoard);
2752	  if (pMga->pClientStruct)
2753	    xfree(pMga->pClientStruct);
2754	  if (pMga->pMgaModeInfo)
2755	    xfree(pMga->pMgaModeInfo);
2756	  if (pMga->pMgaHwInfo)
2757	    xfree(pMga->pMgaHwInfo);
2758      }
2759
2760    );	/* MGA_HAL */
2761#endif
2762
2763    xf86SetPrimInitDone(pScrn->entityList[0]);
2764
2765    return TRUE;
2766}
2767
2768
2769/*
2770 * Map the framebuffer and MMIO memory.
2771 */
2772
2773static Bool
2774MGAMapMem(ScrnInfoPtr pScrn)
2775{
2776    MGAPtr pMga = MGAPTR(pScrn);
2777#ifdef XSERVER_LIBPCIACCESS
2778    struct pci_device *const dev = pMga->PciInfo;
2779    struct pci_mem_region *region;
2780    void **memory[2];
2781    int i, err;
2782#endif
2783
2784
2785    if (!pMga->FBDev) {
2786#ifdef XSERVER_LIBPCIACCESS
2787        memory[pMga->io_bar] = &pMga->IOBase;
2788        memory[pMga->framebuffer_bar] = &pMga->FbBase;
2789
2790        for (i = 0; i < 2; i++) {
2791            region = &dev->regions[i];
2792            err = pci_device_map_range(dev,
2793                                       region->base_addr, region->size,
2794                                       PCI_DEV_MAP_FLAG_WRITABLE,
2795                                       memory[i]);
2796
2797            if (err) {
2798                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2799                           "Unable to map BAR %i.  %s (%d)\n",
2800                           i, strerror(err), err);
2801                return FALSE;
2802            }
2803        }
2804#else
2805	/*
2806	 * For Alpha, we need to map SPARSE memory, since we need
2807	 * byte/short access.  This is taken care of automatically by the
2808	 * os-support layer.
2809	 */
2810	pMga->IOBase = xf86MapPciMem(pScrn->scrnIndex,
2811				     VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
2812				     pMga->PciTag, pMga->IOAddress, 0x4000);
2813	if (pMga->IOBase == NULL)
2814	    return FALSE;
2815
2816	pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
2817				     pMga->PciTag, pMga->FbAddress,
2818				     pMga->FbMapSize);
2819	if (pMga->FbBase == NULL)
2820	    return FALSE;
2821#endif
2822    }
2823    else {
2824	pMga->FbBase = fbdevHWMapVidmem(pScrn);
2825	if (pMga->FbBase == NULL) {
2826	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2827		       "Unable to map framebuffer.\n");
2828	    return FALSE;
2829	}
2830
2831	pMga->IOBase = fbdevHWMapMMIO(pScrn);
2832	if (pMga->IOBase == NULL) {
2833	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map MMIO.\n");
2834	    return FALSE;
2835	}
2836    }
2837
2838
2839    pMga->FbStart = pMga->FbBase + pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
2840
2841    pMga->ILOADBase = NULL;
2842    if (pMga->iload_bar != -1) {
2843#ifdef XSERVER_LIBPCIACCESS
2844        region = &dev->regions[pMga->iload_bar];
2845        err = pci_device_map_range(dev,
2846                                   region->base_addr, region->size,
2847                                   PCI_DEV_MAP_FLAG_WRITABLE,
2848                                   (void *) &pMga->ILOADBase);
2849	if (err) {
2850	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2851		       "Unable to map BAR 2 (ILOAD region).  %s (%d)\n",
2852		       strerror(err), err);
2853	    return FALSE;
2854	}
2855#else
2856	pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
2857					VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
2858					VIDMEM_READSIDEEFFECT,
2859					pMga->PciTag, pMga->ILOADAddress,
2860					0x800000);
2861#endif
2862    }
2863
2864
2865    return TRUE;
2866}
2867
2868
2869/*
2870 * Unmap the framebuffer and MMIO memory.
2871 */
2872
2873static Bool
2874MGAUnmapMem(ScrnInfoPtr pScrn)
2875{
2876    MGAPtr pMga = MGAPTR(pScrn);
2877#ifdef XSERVER_LIBPCIACCESS
2878    struct pci_device * const dev = pMga->PciInfo;
2879#endif
2880
2881
2882    if (!pMga->FBDev) {
2883#ifdef XSERVER_LIBPCIACCESS
2884        pci_device_unmap_range(dev, pMga->IOBase,
2885			       dev->regions[pMga->io_bar].size);
2886        pci_device_unmap_range(dev, pMga->FbBase,
2887			       dev->regions[pMga->framebuffer_bar].size);
2888#else
2889	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
2890	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase, pMga->FbMapSize);
2891#endif
2892    }
2893    else {
2894	fbdevHWUnmapVidmem(pScrn);
2895	fbdevHWUnmapMMIO(pScrn);
2896    }
2897
2898    if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
2899#ifdef XSERVER_LIBPCIACCESS
2900        pci_device_unmap_range(dev, pMga->ILOADBase,
2901			       dev->regions[pMga->iload_bar].size);
2902#else
2903	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
2904#endif
2905    }
2906
2907    pMga->IOBase = NULL;
2908    pMga->FbBase = NULL;
2909    pMga->FbStart = NULL;
2910    pMga->ILOADBase = NULL;
2911
2912    return TRUE;
2913}
2914
2915
2916/*
2917 * This function saves the video state.
2918 */
2919static void
2920MGASave(ScrnInfoPtr pScrn)
2921{
2922    vgaHWPtr hwp = VGAHWPTR(pScrn);
2923    vgaRegPtr vgaReg = &hwp->SavedReg;
2924    MGAPtr pMga = MGAPTR(pScrn);
2925    MGARegPtr mgaReg = &pMga->SavedReg;
2926
2927    if(pMga->SecondCrtc == TRUE) return;
2928#ifdef USEMGAHAL
2929    MGA_HAL(if (pMga->pBoard != NULL) MGASaveVgaState(pMga->pBoard));
2930#endif
2931
2932    /* I need to save the registers for the second head also */
2933    /* Save the register for 0x80 to 0xa0 */
2934    /* Could call it dac2Saved */
2935
2936    /* Only save text mode fonts/text for the primary card */
2937    (*pMga->Save)(pScrn, vgaReg, mgaReg, pMga->Primary);
2938}
2939
2940#ifdef USEMGAHAL
2941/* Convert DisplayModeRec parameters in MGAMODEINFO parameters.
2942*  mode parameter optionnal. */
2943void
2944MGAFillModeInfoStruct(ScrnInfoPtr pScrn, DisplayModePtr mode)
2945{
2946     const char *s;
2947    MGAPtr pMga = MGAPTR(pScrn);
2948
2949    Bool digital1 = FALSE;
2950    Bool digital2 = FALSE;
2951    Bool tv1 = FALSE;
2952    Bool tv2 = FALSE;
2953    Bool swap_head
2954      = xf86ReturnOptValBool(pMga->Options, OPTION_SWAPPED_HEAD, FALSE);
2955
2956    if(pMga->MergedFB && mode && mode->Private && (mode->PrivSize == 0)) {
2957        mode = pMga->SecondCrtc ?
2958             ((MergedDisplayModePtr)mode->Private)->Monitor2
2959            : ((MergedDisplayModePtr)mode->Private)->Monitor1;
2960    }
2961
2962
2963    if (pMga->pMgaHwInfo)
2964    {
2965	digital1 = ISDIGITAL1(pMga);
2966	digital2 = ISDIGITAL2(pMga);
2967	tv1 = ISTV1(pMga);
2968	tv2 = ISTV2(pMga);
2969    }
2970
2971    /*FIXME: causes segfault elsewhere if not commented*/
2972    /*if(!pMga->pMgaModeInfo)*/ pMga->pMgaModeInfo = xalloc(sizeof(MGAMODEINFO));
2973    pMga->pMgaModeInfo->flOutput = 0;
2974    pMga->pMgaModeInfo->ulDeskWidth = pScrn->virtualX;
2975    pMga->pMgaModeInfo->ulDeskHeight = pScrn->virtualY;
2976    pMga->pMgaModeInfo->ulFBPitch = 0;
2977    pMga->pMgaModeInfo->ulBpp = pScrn->bitsPerPixel;
2978    pMga->pMgaModeInfo->ulZoom = 1;
2979    pMga->pMgaModeInfo->flSignalMode = 0x10;
2980
2981    /* Set TV standard */
2982    if ((s = xf86GetOptValString(pMga->Options, OPTION_TVSTANDARD))) {
2983    	if (!xf86NameCmp(s, "PAL")) {
2984    		pMga->pMgaModeInfo->flSignalMode = 0x00;
2985    		pMga->pMgaModeInfo->ulRefreshRate = 50;
2986    		pMga->pMgaModeInfo->ulTVStandard = TV_PAL;
2987    	} else {
2988    		pMga->pMgaModeInfo->ulRefreshRate = 60;
2989    		pMga->pMgaModeInfo->ulTVStandard = TV_NTSC;
2990    	}
2991    } else {
2992    	pMga->pMgaModeInfo->ulRefreshRate = 0;
2993    	pMga->pMgaModeInfo->ulTVStandard = TV_NTSC;
2994    }
2995
2996    /* Set Cable Type */
2997    if ((s = xf86GetOptValString(pMga->Options, OPTION_CABLETYPE))) {
2998    	if (!xf86NameCmp(s, "SCART_RGB")) {
2999    		pMga->pMgaModeInfo->ulCableType = TV_SCART_RGB;
3000    	} else if (!xf86NameCmp(s, "SCART_COMPOSITE")) {
3001    		pMga->pMgaModeInfo->ulCableType = TV_SCART_COMPOSITE;
3002    	} else if (!xf86NameCmp(s, "SCART_TYPE2")) {
3003    		pMga->pMgaModeInfo->ulCableType = TV_SCART_TYPE2;
3004    	} else {
3005    		pMga->pMgaModeInfo->ulCableType = TV_YC_COMPOSITE;
3006    	}
3007    } else {
3008    	pMga->pMgaModeInfo->ulCableType = TV_YC_COMPOSITE;
3009    }
3010
3011    if(mode) {
3012        pMga->pMgaModeInfo->ulHorizRate = 0;
3013        pMga->pMgaModeInfo->ulDispWidth = mode->HDisplay;
3014        pMga->pMgaModeInfo->ulDispHeight = mode->VDisplay;
3015        pMga->pMgaModeInfo->ulPixClock = mode->Clock;
3016        pMga->pMgaModeInfo->ulHFPorch = mode->HSyncStart - mode->HDisplay;
3017        pMga->pMgaModeInfo->ulHSync = mode->HSyncEnd - mode->HSyncStart;
3018        pMga->pMgaModeInfo->ulHBPorch = mode->HTotal - mode->HSyncEnd;
3019        pMga->pMgaModeInfo->ulVFPorch = mode->VSyncStart - mode->VDisplay;
3020        pMga->pMgaModeInfo->ulVSync = mode->VSyncEnd - mode->VSyncStart;
3021        pMga->pMgaModeInfo->ulVBPorch = mode->VTotal - mode->VSyncEnd;
3022    }
3023    /* Use DstOrg directly */
3024    /* This is an offset in pixels not memory */
3025    pMga->pMgaModeInfo->ulDstOrg = pMga->DstOrg / (pScrn->bitsPerPixel / 8);
3026    pMga->pMgaModeInfo->ulDisplayOrg = pMga->DstOrg / (pScrn->bitsPerPixel / 8);
3027    pMga->pMgaModeInfo->ulPanXGran = 0;
3028    pMga->pMgaModeInfo->ulPanYGran = 0;
3029
3030    if(pMga->SecondCrtc == TRUE) {
3031	pMga->pMgaModeInfo->flOutput = MGAMODEINFO_SECOND_CRTC |
3032				       MGAMODEINFO_FORCE_PITCH |
3033				       MGAMODEINFO_FORCE_DISPLAYORG;
3034	if (digital2) {
3035	    pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_DIGITAL2;
3036	} else if (tv2) {
3037	    pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_TV;
3038	} else {
3039            if (!swap_head) {
3040	      pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_ANALOG2;
3041            } else {
3042              pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_ANALOG1;
3043            }
3044	}
3045    } else {
3046	pMga->pMgaModeInfo->flOutput = MGAMODEINFO_FORCE_PITCH;
3047        if (digital1) {
3048	    if ((pMga->Chipset == PCI_CHIP_MGAG200) ||
3049		(pMga->Chipset == PCI_CHIP_MGAG200_PCI)) {
3050		pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_FLATPANEL1;
3051		pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_DIGITAL2;
3052	    } else {
3053		pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_DIGITAL1;
3054	    }
3055        } else if (tv1) {
3056	    pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_TV;
3057       	} else {
3058            if (!swap_head) {
3059	        pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_ANALOG1;
3060            } else {
3061                pMga->pMgaModeInfo->flOutput |= MGAMODEINFO_ANALOG2;
3062            }
3063        }
3064    }
3065    pMga->pMgaModeInfo->ulFBPitch = pScrn->displayWidth;
3066}
3067#endif
3068
3069/*
3070 * Initialise a new mode.  This is currently still using the old
3071 * "initialise struct, restore/write struct to HW" model.  That could
3072 * be changed.
3073 */
3074
3075static Bool
3076MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
3077{
3078    vgaHWPtr hwp = VGAHWPTR(pScrn);
3079    vgaRegPtr vgaReg;
3080    MGAPtr pMga = MGAPTR(pScrn);
3081    MGARegPtr mgaReg;
3082
3083#ifdef USEMGAHAL
3084   ULONG status;
3085#endif
3086    vgaHWUnlock(hwp);
3087
3088/*    if(pMga->MergedFB && mode && mode->Private && (mode->PrivSize == 0)) {
3089        mode = (DisplayModePtr)mode->Private;
3090    }*/
3091
3092    /* Initialise the ModeReg values */
3093    if (!vgaHWInit(pScrn, mode))
3094	return FALSE;
3095    pScrn->vtSema = TRUE;
3096
3097    if (!(*pMga->ModeInit)(pScrn, mode))
3098	return FALSE;
3099
3100    /* Program the registers */
3101    if (pMga->is_G200SE) {
3102	MGAG200SEHWProtect(pScrn, TRUE);
3103    } else {
3104	vgaHWProtect(pScrn, TRUE);
3105    }
3106    vgaReg = &hwp->ModeReg;
3107    mgaReg = &pMga->ModeReg;
3108#ifdef USEMGAHAL
3109    MGA_HAL(
3110        MGAFillModeInfoStruct(pScrn,mode);
3111
3112        /* Validate the parameters */
3113        if ((status = MGAValidateMode(pMga->pBoard, pMga->pMgaModeInfo)) != 0) {
3114            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3115                    "MGAValidateMode from HALlib found the mode to be invalid.\n"
3116                    "\tError: %lx\n", status);
3117            return FALSE;
3118        }
3119
3120        /*
3121         * Find mode for second head.
3122         */
3123        if(pMga->MergedFB) {
3124
3125            MGAFillModeInfoStruct(pMga->pScrn2,mode);
3126            /* Validates the Video parameters */
3127            if ((status = MGAValidateVideoParameters(pMga->pBoard, MGAPTR(pMga->pScrn2)->pMgaModeInfo))
3128                != 0) {
3129                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3130                        "MGAValidateVideoParameters from HALlib found the mode to be invalid.\n\tError: %lx\n", status);
3131                return FALSE;
3132            }
3133        }
3134    );	 /*MGA_HAL */
3135
3136#endif
3137
3138#ifdef USEMGAHAL
3139MGA_HAL(
3140
3141    /*************************** ESC *****************************/
3142    TmpMgaModeInfo[0] =  *pMga->pMgaModeInfo;
3143
3144    if(pMga->SecondCrtc == TRUE)
3145        pMgaModeInfo[1] = pMga->pMgaModeInfo;
3146    else
3147        pMgaModeInfo[0] = pMga->pMgaModeInfo;
3148
3149	TmpMgaModeInfo[0].ulDispWidth = 0;
3150
3151    if(!pMga->MergedFB) /* FIXME: Must deal with this once PowerDesk & MergedFB
3152                           compatibility will exist */
3153        MGAFillDisplayModeStruct(mode, pMga->pMgaModeInfo);
3154    /*************************************************************/
3155
3156);	/* MGA_HAL */
3157#endif
3158
3159#ifdef XF86DRI
3160   if (pMga->directRenderingEnabled) {
3161       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
3162   }
3163#endif
3164
3165#ifdef USEMGAHAL
3166    MGA_HAL(
3167    /* Initialize the board */
3168    if(MGASetMode(pMga->pBoard,pMga->pMgaModeInfo) != 0) {
3169	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3170		"MGASetMode returned an error."
3171		"  Make sure to validate the mode before.\n");
3172	return FALSE;
3173    }
3174    if(pMga->MergedFB
3175       && MGASetMode(pMga->pBoard,MGAPTR(pMga->pScrn2)->pMgaModeInfo) != 0) {
3176  	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3177		   "MGASetMode returned an error."
3178		   "  Make sure to validate the mode before.\n");
3179    }
3180
3181    );	/* MGA_HAL */
3182
3183    /* getting around bugs in the HAL lib. MATROX: hint, hint. */
3184    MGA_HAL(
3185	    if (pMga->chip_attribs->hwcursor_1064) {
3186		if(pMga->SecondCrtc == FALSE && pMga->HWCursor == TRUE) {
3187		outMGAdac(MGA1064_CURSOR_BASE_ADR_LOW,
3188			  pMga->FbCursorOffset >> 10);
3189		outMGAdac(MGA1064_CURSOR_BASE_ADR_HI,
3190			  pMga->FbCursorOffset >> 18);
3191		outMGAdac(MGA1064_CURSOR_CTL, 0x00);
3192	      }
3193	      if (pMga->Overlay8Plus24 == TRUE) {
3194    		  outMGAdac(MGA1064_MUL_CTL, MGA1064_MUL_CTL_32bits);
3195    		  outMGAdac(MGA1064_COL_KEY_MSK_LSB,0xFF);
3196    		  outMGAdac(MGA1064_COL_KEY_LSB,pMga->colorKey);
3197  		  outMGAdac(MGA1064_COL_KEY_MSK_MSB,0xFF);
3198  		  outMGAdac(MGA1064_COL_KEY_MSB,0xFF);
3199	      }
3200	    }
3201    );	/* MGA_HAL */
3202#endif
3203
3204    MGA_NOT_HAL((*pMga->Restore)(pScrn, vgaReg, mgaReg, FALSE));
3205
3206    MGAStormSync(pScrn);
3207    MGAStormEngineInit(pScrn);
3208
3209    if (pMga->is_G200SE) {
3210	MGAG200SEHWProtect(pScrn,FALSE);
3211    } else {
3212	vgaHWProtect(pScrn, FALSE);
3213    }
3214
3215    if (xf86IsPc98()) {
3216	if (pMga->Chipset == PCI_CHIP_MGA2064)
3217	    outb(0xfac, 0x01);
3218	else
3219	    outb(0xfac, 0x02);
3220    }
3221
3222    MGA_NOT_HAL(
3223	if (pMga->is_G200SE) {
3224            OUTREG8(0x1FDE, 0x06);
3225            OUTREG8(0x1FDF, 0x14);
3226        }
3227    );
3228
3229    pMga->CurrentLayout.mode = mode;
3230
3231    if(pMga->MergedFB && mode->Private && (mode->PrivSize == 0)) {
3232	pMga->M1currentMode = (DisplayModePtr)mode->Private;
3233    }
3234
3235#ifdef XF86DRI
3236   if (pMga->directRenderingEnabled)
3237     DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
3238#endif
3239#ifdef DEBUG
3240   MGAG450PrintPLL(pScrn);
3241#endif
3242    return TRUE;
3243}
3244
3245static
3246void MGARestoreSecondCrtc(ScrnInfoPtr pScrn)
3247{
3248    MGAPtr pMga = MGAPTR(pScrn);
3249
3250    if (MGAISGx50(pMga)) {
3251        /* Force to return in clone mode */
3252        if (pMga->SecondOutput
3253                && (xf86IsEntityShared(pScrn->entityList[0]) || pMga->SecondCrtc)
3254                && !pMga->MergedFB) {
3255            /* Do this branch if
3256             * SecondOutput
3257             * and not Unshared Primary
3258             * and not Merged Mode (usualy means Unshared Primary)
3259             */
3260            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3261
3262            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3263            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3264
3265            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3266
3267       } else {
3268            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3269            CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3270
3271            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3272            ucXDispCtrl |= MGA1064_DISP_CTL_DAC1OUTSEL_EN;
3273            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3274
3275            /* crtcdacsel -> crtc1 */
3276            ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_CRTC2;
3277            ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC1;
3278
3279            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3280            OUTREG(MGAREG_C2CTL, ulC2CTL);
3281       }
3282
3283    } else {
3284        /* Force to close second crtc */
3285        CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3286
3287        ulC2CTL &= ~MGAREG_C2CTL_C2_EN;
3288
3289        OUTREG(MGAREG_C2CTL, ulC2CTL);
3290    }
3291}
3292
3293/*
3294 * Restore the initial (text) mode.
3295 */
3296static void
3297MGARestore(ScrnInfoPtr pScrn)
3298{
3299    vgaHWPtr hwp = VGAHWPTR(pScrn);
3300    vgaRegPtr vgaReg = &hwp->SavedReg;
3301    MGAPtr pMga = MGAPTR(pScrn);
3302    MGARegPtr mgaReg = &pMga->SavedReg;
3303
3304    if (pScrn->pScreen != NULL)
3305	MGAStormSync(pScrn);
3306
3307    /*
3308     * Restore the second crtc if:
3309     * first and only driver entity
3310     * second entity
3311     * Merged Framebuffer mode (first and only driver entity)
3312     */
3313    if((!xf86IsEntityShared(pScrn->entityList[0]) && !pMga->SecondCrtc)
3314       || pMga->SecondCrtc || pMga->MergedFB) {
3315	/*       if(pMga->MergedFB) {
3316		 if(pMga->pScrn2)
3317                 MGARestoreSecondCrtc(pMga->pScrn2);
3318		 } else*/
3319	MGARestoreSecondCrtc(pScrn);
3320	/* if we are second instance of driver, we've done our job, exit */
3321	if(pMga->SecondCrtc) return;
3322    }
3323
3324    /* Only restore text mode fonts/text for the primary card */
3325    if (pMga->is_G200SE) {
3326	MGAG200SEHWProtect(pScrn,TRUE);
3327    } else {
3328	vgaHWProtect(pScrn, TRUE);
3329    }
3330    if (pMga->Primary) {
3331#ifdef USEMGAHAL
3332	MGA_HAL(
3333	    if(pMga->pBoard != NULL) {
3334		MGASetVgaMode(pMga->pBoard);
3335		MGARestoreVgaState(pMga->pBoard);
3336	    }
3337	    );	/* MGA_HAL */
3338#endif
3339        (*pMga->Restore)(pScrn, vgaReg, mgaReg, TRUE);
3340    } else {
3341        vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
3342    }
3343
3344    if (pMga->is_G200SE) {
3345	MGAG200SEHWProtect(pScrn,FALSE);
3346    } else {
3347	vgaHWProtect(pScrn,FALSE);
3348    }
3349}
3350
3351
3352/* Workaround for a G400 CRTC2 display problem */
3353static void
3354MGACrtc2FillStrip(ScrnInfoPtr pScrn)
3355{
3356    MGAPtr pMga = MGAPTR(pScrn);
3357
3358    if (pMga->NoAccel) {
3359	/* Clears the whole screen, but ... */
3360	bzero(pMga->FbStart,
3361	    (pScrn->bitsPerPixel >> 3) * pScrn->displayWidth * pScrn->virtualY);
3362    } else {
3363	xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
3364	pMga->RestoreAccelState(pScrn);
3365	pMga->SetupForSolidFill(pScrn, 0, GXcopy, 0xFFFFFFFF);
3366	pMga->SubsequentSolidFillRect(pScrn, pScrn->virtualX, 0,
3367				  pScrn->displayWidth - pScrn->virtualX,
3368				  pScrn->virtualY);
3369	MGAStormSync(pScrn);
3370    }
3371}
3372
3373
3374/* Mandatory */
3375
3376/* This gets called at the start of each server generation */
3377
3378static Bool
3379MGAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
3380{
3381    ScrnInfoPtr pScrn;
3382    vgaHWPtr hwp;
3383    MGAPtr pMga;
3384    MGARamdacPtr MGAdac;
3385    int ret;
3386    VisualPtr visual;
3387    unsigned char *FBStart;
3388    int width, height, displayWidth;
3389    MGAEntPtr pMgaEnt = NULL;
3390    int f;
3391    CARD32 VRTemp, FBTemp;
3392#ifdef XF86DRI
3393    MessageType driFrom = X_DEFAULT;
3394#endif
3395    DPMSSetProcPtr mga_dpms_set_proc = NULL;
3396
3397    /*
3398     * First get the ScrnInfoRec
3399     */
3400    pScrn = xf86Screens[pScreen->myNum];
3401
3402    hwp = VGAHWPTR(pScrn);
3403    pMga = MGAPTR(pScrn);
3404    MGAdac = &pMga->Dac;
3405
3406    if (pMga->is_G200SE) {
3407	VRTemp = pScrn->videoRam;
3408	FBTemp = pMga->FbMapSize;
3409	pScrn->videoRam = 4096;
3410	pMga->FbMapSize = pScrn->videoRam * 1024;
3411    }
3412
3413
3414    /* Map the MGA memory and MMIO areas */
3415    if (!MGAMapMem(pScrn))
3416	return FALSE;
3417
3418
3419    /* Select functions that vary based on the CRTC configureation of the
3420     * screen.
3421     */
3422    if (!pMga->MergedFB) {
3423	if (pMga->SecondCrtc) {
3424	    mga_dpms_set_proc = MGADisplayPowerManagementSetCrtc2;
3425	    pScreen->SaveScreen = MGASaveScreenCrtc2;
3426	}
3427	else {
3428	    mga_dpms_set_proc = MGADisplayPowerManagementSet;
3429	    pScreen->SaveScreen = MGASaveScreen;
3430	}
3431    }
3432    else {
3433        pScreen->SaveScreen = MGASaveScreenMerged;
3434	mga_dpms_set_proc = MGADisplayPowerManagementSetMerged;
3435    }
3436
3437
3438    if ((pMga->Chipset == PCI_CHIP_MGAG100)
3439	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
3440        MGAG100BlackMagic(pScrn);
3441
3442    if (pMga->DualHeadEnabled) {
3443       DevUnion *pPriv;
3444       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3445       pMgaEnt = pPriv->ptr;
3446       pMgaEnt->refCount++;
3447#ifdef USEMGAHAL
3448       MGA_HAL(
3449       if(pMgaEnt->refCount == 1) {
3450	   CARD8 MiscCtlReg;
3451	  pMga->pBoard = xalloc(sizeof(CLIENTDATA) + MGAGetBOARDHANDLESize());
3452	  pMga->pClientStruct = xalloc(sizeof(CLIENTDATA));
3453	  pMga->pClientStruct->pMga = (MGAPtr) pMga;
3454
3455	  /* wrapping OpenLibrary to fix broken registers. MATROX: hint,hint.*/
3456          MiscCtlReg = inMGAdac(MGA1064_MISC_CTL);
3457	  MGAOpenLibrary(pMga->pBoard,pMga->pClientStruct,sizeof(CLIENTDATA));
3458	  outMGAdac(MGA1064_MISC_CTL,MiscCtlReg);
3459	  pMga->pMgaHwInfo = xalloc(sizeof(MGAHWINFO));
3460	  MGAGetHardwareInfo(pMga->pBoard,pMga->pMgaHwInfo);
3461
3462	  /* Detecting for type of display */
3463	  if (pMga->pMgaHwInfo->ulCapsSecondOutput & MGAHWINFOCAPS_OUTPUT_TV) {
3464	  	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TV detected\n");
3465	  }
3466	  if (pMga->pMgaHwInfo->ulCapsFirstOutput &
3467			MGAHWINFOCAPS_OUTPUT_DIGITAL) {
3468	  	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3469				"Digital Screen detected\n");
3470	  }
3471	  if (pMga->pMgaHwInfo->ulCapsSecondOutput &
3472			MGAHWINFOCAPS_OUTPUT_DIGITAL) {
3473	  	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3474				"Digital Screen detected\n");
3475	  }
3476
3477	  /* Now copy these to the entitystructure */
3478	  pMgaEnt->pClientStruct = pMga->pClientStruct;
3479	  pMgaEnt->pBoard = pMga->pBoard;
3480	  pMgaEnt->pMgaHwInfo = pMga->pMgaHwInfo;
3481       } else { /* Ref count is 2 */
3482	  pMga->pClientStruct = pMgaEnt->pClientStruct;
3483	  pMga->pBoard = pMgaEnt->pBoard;
3484	  pMga->pMgaHwInfo = pMgaEnt->pMgaHwInfo;
3485       }
3486       );	/* MGA_HAL */
3487#endif
3488    } else {
3489#ifdef USEMGAHAL
3490	CARD8 MiscCtlReg;
3491
3492	  MGA_HAL(
3493	  pMga->pBoard = xalloc(sizeof(CLIENTDATA) + MGAGetBOARDHANDLESize());
3494	  pMga->pClientStruct = xalloc(sizeof(CLIENTDATA));
3495	  pMga->pClientStruct->pMga = (MGAPtr) pMga;
3496
3497	  MiscCtlReg = inMGAdac(MGA1064_MISC_CTL);
3498	  /* wrapping OpenLibrary to fix broken registers. MATROX: hint,hint.*/
3499	  MGAOpenLibrary(pMga->pBoard,pMga->pClientStruct,sizeof(CLIENTDATA));
3500	  outMGAdac(MGA1064_MISC_CTL,MiscCtlReg);
3501	  pMga->pMgaHwInfo = xalloc(sizeof(MGAHWINFO));
3502	  MGAGetHardwareInfo(pMga->pBoard,pMga->pMgaHwInfo);
3503	  );	/* MGA_HAL */
3504#endif
3505    }
3506    if (pMga->is_G200SE) {
3507	pScrn->videoRam = VRTemp;
3508	pMga->FbMapSize = FBTemp;
3509    }
3510#ifdef USEMGAHAL
3511    MGA_HAL(
3512	/* There is a problem in the HALlib: set soft reset bit */
3513	/* MATROX: hint, hint. */
3514	if (!pMga->Primary && !pMga->FBDev &&
3515	    (SUBSYS_ID(pMga->PciInfo) == PCI_CARD_MILL_G200_SG)) {
3516	    OUTREG(MGAREG_Reset, 1);
3517	    usleep(200);
3518	    OUTREG(MGAREG_Reset, 0);
3519	}
3520    );	/* MGA_HAL */
3521#endif
3522
3523    /* Initialise the MMIO vgahw functions */
3524    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
3525    vgaHWGetIOBase(hwp);
3526
3527    /* Map the VGA memory when the primary video */
3528    if (!pMga->FBDev) {
3529	if (pMga->Primary) {
3530	    hwp->MapSize = 0x10000;
3531	    if (!vgaHWMapMem(pScrn))
3532		return FALSE;
3533	}
3534
3535	/* Save the current state */
3536	MGASave(pScrn);
3537	/* Initialise the first mode */
3538	if (!MGAModeInit(pScrn, pScrn->currentMode))
3539	    return FALSE;
3540    }
3541    else {
3542	fbdevHWSave(pScrn);
3543	/* Disable VGA core, and leave memory access on */
3544#ifdef XSERVER_LIBPCIACCESS
3545	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
3546				  PCI_OPTION_REG);
3547#else
3548	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
3549#endif
3550	if (!fbdevHWModeInit(pScrn, pScrn->currentMode))
3551	    return FALSE;
3552
3553        if (!pMga->SecondCrtc && pMga->HWCursor
3554	    && pMga->chip_attribs->hwcursor_1064) {
3555	    outMGAdac(MGA1064_CURSOR_BASE_ADR_LOW, pMga->FbCursorOffset >> 10);
3556	    outMGAdac(MGA1064_CURSOR_BASE_ADR_HI, pMga->FbCursorOffset >> 18);
3557	}
3558
3559	MGAStormEngineInit(pScrn);
3560    }
3561
3562    /* Darken the screen for aesthetic reasons and set the viewport
3563     */
3564    (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
3565    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
3566
3567
3568    /*
3569     * The next step is to setup the screen's visuals, and initialise the
3570     * framebuffer code.  In cases where the framebuffer's default
3571     * choices for things like visual layouts and bits per RGB are OK,
3572     * this may be as simple as calling the framebuffer's ScreenInit()
3573     * function.  If not, the visuals will need to be setup before calling
3574     * a fb ScreenInit() function and fixed up after.
3575     *
3576     * For most PC hardware at depths >= 8, the defaults that cfb uses
3577     * are not appropriate.  In this driver, we fixup the visuals after.
3578     */
3579
3580    /*
3581     * Reset the visual list.
3582     */
3583    miClearVisualTypes();
3584
3585    /* Setup the visuals we support. */
3586
3587    /* All MGA support DirectColor and can do overlays in 32bpp */
3588    if(pMga->Overlay8Plus24 && (pScrn->bitsPerPixel == 32)) {
3589	if (!miSetVisualTypes(8, PseudoColorMask | GrayScaleMask,
3590			      pScrn->rgbBits, PseudoColor))
3591		return FALSE;
3592	if (!miSetVisualTypes(24, TrueColorMask, pScrn->rgbBits, TrueColor))
3593		return FALSE;
3594    } else if (pMga->SecondCrtc) {
3595	/* No DirectColor on the second head */
3596	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
3597			      TrueColor))
3598		return FALSE;
3599	if (!miSetPixmapDepths ())
3600	    return FALSE;
3601    } else {
3602	if (!xf86SetDefaultVisual(pScrn, -1))
3603	    return FALSE;
3604
3605	if (!miSetVisualTypes(pScrn->depth,
3606			      miGetDefaultVisualMask(pScrn->depth),
3607			      pScrn->rgbBits, pScrn->defaultVisual))
3608	    return FALSE;
3609	if (!miSetPixmapDepths ())
3610	    return FALSE;
3611    }
3612
3613    /*
3614     * Call the framebuffer layer's ScreenInit function, and fill in other
3615     * pScreen fields.
3616     */
3617
3618    width = pScrn->virtualX;
3619    height = pScrn->virtualY;
3620    displayWidth = pScrn->displayWidth;
3621
3622
3623    if(pMga->Rotate) {
3624	height = pScrn->virtualX;
3625	width = pScrn->virtualY;
3626    }
3627
3628    if(pMga->ShadowFB) {
3629 	pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
3630	pMga->ShadowPtr = xalloc(pMga->ShadowPitch * height);
3631	displayWidth = pMga->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3632        FBStart = pMga->ShadowPtr;
3633    } else {
3634	pMga->ShadowPtr = NULL;
3635	FBStart = pMga->FbStart;
3636    }
3637
3638#ifdef XF86DRI
3639     /*
3640      * Setup DRI after visuals have been established, but before cfbScreenInit
3641      * is called.   cfbScreenInit will eventually call into the drivers
3642      * InitGLXVisuals call back.
3643      * The DRI does not work when textured video is enabled at this time.
3644      */
3645    if (pMga->is_G200SE) {
3646	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3647		   "Not supported by hardware, not initializing the DRI\n");
3648	pMga->directRenderingEnabled = FALSE;
3649	driFrom = X_PROBED;
3650    } else if (!xf86ReturnOptValBool(pMga->Options, OPTION_DRI, TRUE)) {
3651	driFrom = X_CONFIG;
3652    } else if ( pMga->NoAccel ) {
3653       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3654		   "Acceleration disabled, not initializing the DRI\n" );
3655       pMga->directRenderingEnabled = FALSE;
3656       driFrom = X_CONFIG;
3657    }
3658    else if ( pMga->TexturedVideo == TRUE ) {
3659       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3660		   "Textured video enabled, not initializing the DRI\n" );
3661       pMga->directRenderingEnabled = FALSE;
3662       driFrom = X_CONFIG;
3663    }
3664    else if (pMga->SecondCrtc == TRUE) {
3665       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3666		   "Not initializing the DRI on the second head\n" );
3667       pMga->directRenderingEnabled = FALSE;
3668    }
3669    else if ((pMga->FbMapSize /
3670	       (width * (pScrn->bitsPerPixel >> 3))) <= height * 3) {
3671       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3672	  "Static buffer allocation failed, not initializing the DRI\n");
3673       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3674	  "Need at least %d kB video memory at this resolution, bit depth\n",
3675	  (3 * displayWidth * height * (pScrn->bitsPerPixel >> 3)) / 1024 );
3676       pMga->directRenderingEnabled = FALSE;
3677       driFrom = X_PROBED;
3678    }
3679    else {
3680       pMga->directRenderingEnabled = MGADRIScreenInit(pScreen);
3681    }
3682#endif
3683
3684
3685    if (pMga->Overlay8Plus24) {
3686	ret = cfb8_32ScreenInit(pScreen, FBStart,
3687			width, height,
3688			pScrn->xDpi, pScrn->yDpi,
3689			displayWidth);
3690    } else {
3691	ret = fbScreenInit(pScreen, FBStart, width, height,
3692			   pScrn->xDpi, pScrn->yDpi,
3693			   displayWidth, pScrn->bitsPerPixel);
3694    }
3695
3696    if (!ret)
3697	return FALSE;
3698
3699
3700    if (pScrn->bitsPerPixel > 8) {
3701        /* Fixup RGB ordering */
3702        visual = pScreen->visuals + pScreen->numVisuals;
3703        while (--visual >= pScreen->visuals) {
3704	    if ((visual->class | DynamicClass) == DirectColor) {
3705		visual->offsetRed = pScrn->offset.red;
3706		visual->offsetGreen = pScrn->offset.green;
3707		visual->offsetBlue = pScrn->offset.blue;
3708		visual->redMask = pScrn->mask.red;
3709		visual->greenMask = pScrn->mask.green;
3710		visual->blueMask = pScrn->mask.blue;
3711	    }
3712	}
3713    }
3714
3715    /* must be after RGB ordering fixed */
3716    if (!pMga->Overlay8Plus24)
3717	fbPictureInit (pScreen, 0, 0);
3718
3719    xf86SetBlackWhitePixels(pScreen);
3720
3721    pMga->BlockHandler = pScreen->BlockHandler;
3722    pScreen->BlockHandler = MGABlockHandler;
3723
3724    if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */
3725	MGADGAInit(pScreen);
3726
3727    if (!pMga->NoAccel) {
3728#ifdef USE_EXA
3729	if (pMga->Exa)
3730	    mgaExaInit(pScreen);
3731	else
3732#endif
3733#ifdef USE_XAA
3734	    MGAStormAccelInit(pScreen);
3735#endif
3736    }
3737
3738    miInitializeBackingStore(pScreen);
3739    xf86SetBackingStore(pScreen);
3740    xf86SetSilkenMouse(pScreen);
3741
3742    /* Initialize software cursor.
3743	Must precede creation of the default colormap */
3744    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
3745
3746    /* Initialize HW cursor layer.
3747	Must follow software cursor initialization*/
3748    if (pMga->HWCursor) {
3749	if(!MGAHWCursorInit(pScreen))
3750	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3751		"Hardware cursor initialization failed\n");
3752    }
3753    if(pMga->MergedFB) {
3754        /* Rotate and MergedFB are mutiualy exclusive, so we can use this
3755         * variable.
3756         */
3757        if (!pMga->PointerMoved)
3758            pMga->PointerMoved = pScrn->PointerMoved;
3759        pScrn->PointerMoved = MGAMergePointerMoved;
3760
3761    }
3762
3763    /* Initialise default colourmap */
3764    if (!miCreateDefColormap(pScreen))
3765	return FALSE;
3766
3767    /* Initialize colormap layer.
3768	Must follow initialization of the default colormap */
3769    if (!pMga->SecondCrtc)
3770	f = CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH;
3771    else
3772	f = CMAP_RELOAD_ON_MODE_SWITCH;
3773    if(!xf86HandleColormaps(pScreen, 256, 8,
3774	pMga->FBDev ? fbdevHWLoadPaletteWeak() : MGAdac->LoadPalette,
3775	NULL, f))
3776	return FALSE;
3777
3778    if(pMga->Overlay8Plus24) { /* Must come after colormap initialization */
3779	if(!xf86Overlay8Plus32Init(pScreen))
3780	    return FALSE;
3781    }
3782
3783    if(pMga->ShadowFB) {
3784	RefreshAreaFuncPtr refreshArea = MGARefreshArea;
3785
3786	if(pMga->Rotate) {
3787	    if (!pMga->PointerMoved) {
3788	    pMga->PointerMoved = pScrn->PointerMoved;
3789	    pScrn->PointerMoved = MGAPointerMoved;
3790	    }
3791
3792	   switch(pScrn->bitsPerPixel) {
3793	   case 8:	refreshArea = MGARefreshArea8;	break;
3794	   case 16:	refreshArea = MGARefreshArea16;	break;
3795	   case 24:	refreshArea = MGARefreshArea24;	break;
3796	   case 32:	refreshArea = MGARefreshArea32;	break;
3797	   }
3798	}
3799
3800	ShadowFBInit(pScreen, refreshArea);
3801    }
3802
3803    xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
3804
3805    pScrn->memPhysBase = pMga->FbAddress;
3806    pScrn->fbOffset = pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
3807
3808    MGAInitVideo(pScreen);
3809
3810#ifdef XF86DRI
3811    if (pMga->directRenderingEnabled) {
3812       /* Now that mi, cfb, drm and others have done their thing,
3813	* complete the DRI setup.
3814	*/
3815       pMga->directRenderingEnabled = MGADRIFinishScreenInit(pScreen);
3816    }
3817    if (pMga->directRenderingEnabled) {
3818        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
3819    } else {
3820        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
3821    }
3822    if (pMga->DualHeadEnabled && pMga->SecondCrtc == FALSE)
3823	pMgaEnt->directRenderingEnabled = pMga->directRenderingEnabled;
3824    pMga->haveQuiescense = 1;
3825#endif
3826
3827    /* Wrap the current CloseScreen function */
3828    pMga->CloseScreen = pScreen->CloseScreen;
3829    pScreen->CloseScreen = MGACloseScreen;
3830
3831    /* Report any unused options (only for the first generation) */
3832    if (serverGeneration == 1) {
3833	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3834    }
3835
3836    /* For the second head, work around display problem. */
3837    if (!pMga->MergedFB && pMga->SecondCrtc) {
3838	MGACrtc2FillStrip(pScrn);
3839    }
3840
3841    /* Done */
3842    return TRUE;
3843}
3844
3845
3846/* Usually mandatory */
3847Bool
3848MGASwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
3849{
3850#ifdef USEMGAHAL
3851    char sCmdIn[256];
3852    char sCmdOut[256];
3853    FILE* fdIn;
3854# ifdef MATROX_WRITEBACK
3855    FILE* fdOut;
3856# endif
3857#endif
3858
3859    if  (mode->Flags & 0x80000000) {
3860#ifdef USEMGAHAL
3861
3862# ifdef MATROX_WRITEBACK
3863#  define MWB(x) { x; }
3864#  define MWB_COND(x) x
3865# else
3866#  define MWB(x)
3867#  define MWB_COND(x) 1
3868# endif
3869	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3870
3871	MGA_HAL(
3872	fdIn = fopen("/tmp/mgaDriverIn", "rt");
3873	MWB(fdOut = fopen("/tmp/mgaDriverOut", "wt"))
3874
3875	if(fdIn && MWB_COND(fdOut))
3876	{
3877
3878	    fgets(sCmdIn, 255, fdIn);
3879
3880	    if(sCmdIn)
3881	    {
3882
3883		MGAExecuteEscCmd(xf86Screens[scrnIndex], sCmdIn, sCmdOut, mode);
3884
3885		/* Remove file and close file descriptor */
3886		remove("/tmp/mgaDriverIn");
3887		fclose(fdIn);
3888		MWB(
3889		    /* Write output data to output file for
3890		       calling application */
3891		    fputs(sCmdOut, fdOut);
3892		    fclose(fdOut);
3893		    )
3894		mode->Flags &= 0x7FFFFFFF;
3895		return TRUE;
3896	    }
3897	    else
3898	    {
3899		mode->Flags &= 0x7FFFFFFF;
3900		return FALSE;
3901	    }
3902	}
3903	else
3904	{
3905	    mode->Flags &= 0x7FFFFFFF;
3906	    return FALSE;
3907	}
3908   )
3909#endif
3910 	return FALSE;
3911    }   else
3912	return MGAModeInit(xf86Screens[scrnIndex], mode);
3913}
3914
3915 /* Adjusts coordinates to match Panning granularity.
3916  * does nothing if the HALlib is not loaded
3917  */
3918void
3919MGAAdjustGranularity(ScrnInfoPtr pScrn, int* x, int* y)
3920{
3921#ifdef USEMGAHAL
3922    MGA_HAL(
3923	MGAPtr pMga = MGAPTR(pScrn);
3924	MGAPtr pMga2;
3925	int xg = 1;
3926	int yg = 1;
3927	if(pMga->pMgaModeInfo && pMga->pMgaModeInfo->ulPanXGran && pMga->pMgaModeInfo->ulPanYGran) {
3928	    xg = pMga->pMgaModeInfo->ulPanXGran;
3929	    yg = pMga->pMgaModeInfo->ulPanYGran;
3930	}
3931	if(pMga->pScrn2 && (pMga2 = MGAPTR(pMga->pScrn2)) ) {
3932
3933	    if(pMga2->pMgaModeInfo && pMga2->pMgaModeInfo->ulPanXGran && pMga2->pMgaModeInfo->ulPanYGran) {
3934		xg = max(xg,pMga2->pMgaModeInfo->ulPanXGran);
3935		yg = max(yg,pMga2->pMgaModeInfo->ulPanYGran);
3936	    }
3937	}
3938	xg=16; /*ncoder: temporary */
3939	*x -= *x % xg;
3940	*y -= *y % yg;
3941	);
3942#endif
3943}
3944
3945
3946/*
3947 * This function is used to initialize the Start Address - the first
3948 * displayed location in the video memory.
3949 */
3950/* Usually mandatory */
3951void
3952MGAAdjustFrame(int scrnIndex, int x, int y, int flags)
3953{
3954    ScrnInfoPtr pScrn;
3955    int Base, tmp, count;
3956
3957    MGAFBLayout *pLayout;
3958    MGAPtr pMga;
3959
3960
3961    pScrn = xf86Screens[scrnIndex];
3962    pMga = MGAPTR(pScrn);
3963    pLayout = &pMga->CurrentLayout;
3964
3965        /* wanted to improve panning granularity problems without risking
3966         * compatibility issues. Existing code looked hardware dependent.
3967         */
3968#ifdef USEMGAHAL
3969    MGA_HAL(
3970	    pMga->HALGranularityOffX = x;
3971	    pMga->HALGranularityOffY = y;
3972        MGAAdjustGranularity(pScrn,&x,&y);
3973	    pMga->HALGranularityOffX = pMga->HALGranularityOffX - x;
3974	    pMga->HALGranularityOffY = pMga->HALGranularityOffY - y;
3975        HALSetDisplayStart(pMga->pBoard,x,y,0);
3976    );
3977#endif
3978    MGA_NOT_HAL(
3979        if(pMga->ShowCache && y && pScrn->vtSema)
3980            y += pScrn->virtualY - 1;
3981
3982        Base = (y * pLayout->displayWidth + x + pMga->YDstOrg) >>
3983                    (3 - pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]);
3984
3985        if (pLayout->bitsPerPixel == 24) {
3986            if (pMga->Chipset == PCI_CHIP_MGAG400
3987                || pMga->Chipset == PCI_CHIP_MGAG550)
3988                Base &= ~1;  /*1 Not sure why */
3989
3990            Base *= 3;
3991        }
3992
3993        /* find start of retrace */
3994        while (INREG8(0x1FDA) & 0x08);
3995        while (!(INREG8(0x1FDA) & 0x08));
3996        /* wait until we're past the start (fixseg.c in the DDK) */
3997        count = INREG(MGAREG_VCOUNT) + 2;
3998        while(INREG(MGAREG_VCOUNT) < count);
3999
4000        OUTREG16(MGAREG_CRTC_INDEX, (Base & 0x00FF00) | 0x0C);
4001        OUTREG16(MGAREG_CRTC_INDEX, ((Base & 0x0000FF) << 8) | 0x0D);
4002        OUTREG8(MGAREG_CRTCEXT_INDEX, 0x00);
4003        tmp = INREG8(MGAREG_CRTCEXT_DATA);
4004        OUTREG8(MGAREG_CRTCEXT_DATA, (tmp & 0xF0) | ((Base & 0x0F0000) >> 16));
4005    );
4006
4007}
4008
4009void
4010MGAAdjustFrameCrtc2(int scrnIndex, int x, int y, int flags)
4011{
4012    ScrnInfoPtr pScrn;
4013    int Base;
4014    MGAFBLayout *pLayout;
4015    MGAPtr pMga;
4016
4017    pScrn = xf86Screens[scrnIndex];
4018    pMga = MGAPTR(pScrn);
4019    pLayout = &pMga->CurrentLayout;
4020#ifdef USEMGAHAL
4021    MGA_HAL(
4022        MGAAdjustGranularity(pScrn,&x,&y);
4023        HALSetDisplayStart(pMga->pBoard,x,y,1);
4024    );
4025#endif
4026    MGA_NOT_HAL(
4027        if(pMga->ShowCache && y && pScrn->vtSema)
4028            y += pScrn->virtualY - 1;
4029
4030        /* 3-85 c2offset
4031            * 3-93 c2startadd0
4032            * 3-96 c2vcount
4033            */
4034
4035        Base = (y * pLayout->displayWidth + x) * pLayout->bitsPerPixel >> 3;
4036        Base += pMga->DstOrg;
4037        Base &= 0x01ffffc0;
4038        OUTREG(MGAREG_C2STARTADD0, Base);
4039    );
4040}
4041
4042/*
4043 * This is called when VT switching back to the X server.  Its job is
4044 * to reinitialise the video mode.
4045 *
4046 * We may wish to unmap video/MMIO memory too.
4047 */
4048
4049/* Mandatory */
4050static Bool
4051MGAEnterVT(int scrnIndex, int flags)
4052{
4053    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4054    MGAPtr pMga;
4055
4056    pMga = MGAPTR(pScrn);
4057
4058#ifdef XF86DRI
4059    if (pMga->directRenderingEnabled) {
4060	if (pMga->irq) {
4061	    /* Need to make sure interrupts are enabled */
4062	    OUTREG(MGAREG_IEN, pMga->reg_ien);
4063	}
4064        DRIUnlock(screenInfo.screens[scrnIndex]);
4065    }
4066#endif
4067
4068    if (!MGAModeInit(pScrn, pScrn->currentMode))
4069	return FALSE;
4070    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
4071
4072    /* For the second head, work around display problem. */
4073   if (pMga->SecondCrtc) {
4074	MGACrtc2FillStrip(pScrn);
4075    }
4076
4077    return TRUE;
4078}
4079
4080static Bool
4081MGAEnterVTFBDev(int scrnIndex, int flags)
4082{
4083    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4084#ifdef XF86DRI
4085    ScreenPtr pScreen;
4086    MGAPtr pMga;
4087
4088    pMga = MGAPTR(pScrn);
4089    if (pMga->directRenderingEnabled) {
4090        pScreen = screenInfo.screens[scrnIndex];
4091        DRIUnlock(pScreen);
4092    }
4093#endif
4094
4095    fbdevHWEnterVT(scrnIndex,flags);
4096    MGAStormEngineInit(pScrn);
4097    return TRUE;
4098}
4099
4100#define RESTORE_TEXTMODE_ON_DVI(x)                      \
4101    if (MGAISGx50(x) &&                                 \
4102       (ISDIGITAL1(x) || ISDIGITAL2(x))) {              \
4103        /* Reset DUALDVI register */                    \
4104        outMGAdac(MGA1064_DVI_PIPE_CTL, 0x0);           \
4105        /* Set Panel mode between 20 and 54 MHz */      \
4106        outMGAdac(MGA1064_PAN_CTL, 0x7);                \
4107    }
4108
4109
4110/*
4111 * This is called when VT switching away from the X server.  Its job is
4112 * to restore the previous (text) mode.
4113 *
4114 * We may wish to remap video/MMIO memory too.
4115 */
4116
4117/* Mandatory */
4118static void
4119MGALeaveVT(int scrnIndex, int flags)
4120{
4121    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4122    vgaHWPtr hwp = VGAHWPTR(pScrn);
4123#ifdef XF86DRI
4124    MGAPtr pMga = MGAPTR(pScrn);
4125    ScreenPtr pScreen;
4126#endif
4127
4128    MGARestore(pScrn);
4129    vgaHWLock(hwp);
4130
4131    if (xf86IsPc98())
4132	outb(0xfac, 0x00);
4133#ifdef XF86DRI
4134    if (pMga->directRenderingEnabled) {
4135        pScreen = screenInfo.screens[scrnIndex];
4136        DRILock(pScreen, 0);
4137    }
4138#endif
4139#ifdef USEMGAHAL
4140    MGA_HAL( RESTORE_TEXTMODE_ON_DVI(pMga); );
4141#endif
4142}
4143
4144
4145/*
4146 * This is called at the end of each server generation.  It restores the
4147 * original (text) mode.  It should also unmap the video memory, and free
4148 * any per-generation data allocated by the driver.  It should finish
4149 * by unwrapping and calling the saved CloseScreen function.
4150 */
4151
4152/* Mandatory */
4153static Bool
4154MGACloseScreen(int scrnIndex, ScreenPtr pScreen)
4155{
4156    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4157    vgaHWPtr hwp = VGAHWPTR(pScrn);
4158    MGAPtr pMga = MGAPTR(pScrn);
4159    MGAEntPtr pMgaEnt = NULL;
4160
4161#ifdef USEMGAHAL
4162    MGA_HAL( RESTORE_TEXTMODE_ON_DVI(pMga); );
4163#endif
4164    if (pMga->MergedFB)
4165         MGACloseScreenMerged(scrnIndex, pScreen);
4166
4167    if (pScrn->vtSema) {
4168	if (pMga->FBDev) {
4169	    fbdevHWRestore(pScrn);
4170	    MGAUnmapMem(pScrn);
4171        } else {
4172	    MGARestore(pScrn);
4173	    vgaHWLock(hwp);
4174	    MGAUnmapMem(pScrn);
4175	    vgaHWUnmapMem(pScrn);
4176	}
4177    }
4178#ifdef XF86DRI
4179   if (pMga->directRenderingEnabled) {
4180       MGADRICloseScreen(pScreen);
4181       pMga->directRenderingEnabled=FALSE;
4182   }
4183#endif
4184
4185   if (pMga->DualHeadEnabled) {
4186       DevUnion *pPriv;
4187       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
4188       pMgaEnt = pPriv->ptr;
4189       pMgaEnt->refCount--;
4190   }
4191
4192#ifdef USEMGAHAL
4193   MGA_HAL(
4194   if(pMga->DualHeadEnabled) {
4195      if(pMgaEnt->refCount == 0) {
4196	 /* Both boards have closed there screen */
4197	 MGACloseLibrary(pMga->pBoard);
4198
4199	 if (pMga->pBoard)
4200	   xfree(pMga->pBoard);
4201	 if (pMga->pClientStruct)
4202	   xfree(pMga->pClientStruct);
4203	 if (pMga->pMgaModeInfo)
4204	   xfree(pMga->pMgaModeInfo);
4205	 if (pMga->pMgaHwInfo)
4206	   xfree(pMga->pMgaHwInfo);
4207      }
4208   } else {
4209      MGACloseLibrary(pMga->pBoard);
4210
4211      if (pMga->pBoard)
4212	xfree(pMga->pBoard);
4213      if (pMga->pClientStruct)
4214	xfree(pMga->pClientStruct);
4215      if (pMga->pMgaModeInfo)
4216	xfree(pMga->pMgaModeInfo);
4217      if (pMga->pMgaHwInfo)
4218	xfree(pMga->pMgaHwInfo);
4219   }
4220   );	/* MGA_HAL */
4221#endif
4222
4223#ifdef USE_XAA
4224    if (pMga->AccelInfoRec)
4225	XAADestroyInfoRec(pMga->AccelInfoRec);
4226#endif
4227#ifdef USE_EXA
4228    if (pMga->ExaDriver) {
4229	exaDriverFini(pScreen);
4230	xfree(pMga->ExaDriver);
4231    }
4232#endif
4233    if (pMga->CursorInfoRec)
4234    	xf86DestroyCursorInfoRec(pMga->CursorInfoRec);
4235    if (pMga->ShadowPtr)
4236	xfree(pMga->ShadowPtr);
4237    if (pMga->DGAModes)
4238	xfree(pMga->DGAModes);
4239    if (pMga->adaptor)
4240	xfree(pMga->adaptor);
4241    if (pMga->portPrivate)
4242	xfree(pMga->portPrivate);
4243    if (pMga->ScratchBuffer)
4244	xfree(pMga->ScratchBuffer);
4245
4246    pScrn->vtSema = FALSE;
4247
4248    if (xf86IsPc98())
4249	outb(0xfac, 0x00);
4250
4251    xf86ClearPrimInitDone(pScrn->entityList[0]);
4252
4253    if(pMga->BlockHandler)
4254	pScreen->BlockHandler = pMga->BlockHandler;
4255
4256    pScreen->CloseScreen = pMga->CloseScreen;
4257
4258    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
4259}
4260
4261
4262/* Free up any persistent data structures */
4263
4264/* Optional */
4265static void
4266MGAFreeScreen(int scrnIndex, int flags)
4267{
4268
4269    /*
4270     * This only gets called when a screen is being deleted.  It does not
4271     * get called routinely at the end of a server generation.
4272     */
4273    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
4274	vgaHWFreeHWRec(xf86Screens[scrnIndex]);
4275    MGAFreeRec(xf86Screens[scrnIndex]);
4276
4277}
4278
4279
4280/* Checks if a mode is suitable for the selected chipset. */
4281
4282/* Optional */
4283static ModeStatus
4284MGAValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
4285{
4286    int lace;
4287    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4288    MGAPtr pMga = MGAPTR(pScrn);
4289
4290    if (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI) {
4291	if (mode->HDisplay > 1600)
4292	    return MODE_VIRTUAL_X;
4293	if (mode->VDisplay > 1200)
4294	    return MODE_VIRTUAL_Y;
4295    }
4296
4297    lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
4298
4299    if ((mode->CrtcHDisplay <= 2048) &&
4300	(mode->CrtcHSyncStart <= 4096) &&
4301	(mode->CrtcHSyncEnd <= 4096) &&
4302	(mode->CrtcHTotal <= 4096) &&
4303	(mode->CrtcVDisplay <= 2048 * lace) &&
4304	(mode->CrtcVSyncStart <= 4096 * lace) &&
4305	(mode->CrtcVSyncEnd <= 4096 * lace) &&
4306	(mode->CrtcVTotal <= 4096 * lace)) {
4307
4308	/* Can't have horizontal panning for second head of G400 */
4309	if (pMga->SecondCrtc) {
4310	    if (flags == MODECHECK_FINAL) {
4311		if (pMga->allowedWidth == 0)
4312		    pMga->allowedWidth = pScrn->virtualX;
4313		if (mode->HDisplay != pMga->allowedWidth)
4314		    return(MODE_ONE_WIDTH);
4315	    }
4316	}
4317
4318	return(MODE_OK);
4319    } else {
4320	return(MODE_BAD);
4321    }
4322}
4323
4324
4325/*
4326 * This routine is required but since we can't easily blank the
4327 * second display without risking powering off the monitor, return
4328 * FALSE and let the X server do something generic.
4329 */
4330static Bool
4331MGASaveScreenCrtc2(ScreenPtr pScreen, int mode)
4332{
4333    return FALSE;
4334}
4335
4336/* Do screen blanking */
4337
4338static Bool
4339MGASaveScreen(ScreenPtr pScreen, int mode)
4340{
4341    return vgaHWSaveScreen(pScreen, mode);
4342}
4343
4344
4345/*
4346 * MGADisplayPowerManagementSet --
4347 *
4348 * Sets VESA Display Power Management Signaling (DPMS) Mode.
4349 *
4350 * XXX This needs fixing for sync-on-green!
4351 */
4352void
4353MGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
4354			     int flags)
4355{
4356	MGAPtr pMga = MGAPTR(pScrn);
4357	unsigned char seq1 = 0, crtcext1 = 0;
4358
4359	switch (PowerManagementMode)
4360	{
4361	case DPMSModeOn:
4362	    /* Screen: On; HSync: On, VSync: On */
4363	    seq1 = 0x00;
4364	    crtcext1 = 0x00;
4365	    break;
4366	case DPMSModeStandby:
4367	    /* Screen: Off; HSync: Off, VSync: On */
4368	    seq1 = 0x20;
4369	    crtcext1 = 0x10;
4370	    break;
4371	case DPMSModeSuspend:
4372	    /* Screen: Off; HSync: On, VSync: Off */
4373	    seq1 = 0x20;
4374	    crtcext1 = 0x20;
4375	    break;
4376	case DPMSModeOff:
4377	    /* Screen: Off; HSync: Off, VSync: Off */
4378	    seq1 = 0x20;
4379	    crtcext1 = 0x30;
4380	    break;
4381	}
4382
4383	/* XXX Prefer an implementation that doesn't depend on VGA specifics */
4384	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
4385	seq1 |= INREG8(MGAREG_SEQ_DATA) & ~0x20;
4386	MGAWAITVSYNC();
4387	MGAWAITBUSY();
4388	OUTREG8(MGAREG_SEQ_DATA, seq1);
4389	usleep(20000);
4390	OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);	/* Select CRTCEXT1 */
4391	crtcext1 |= INREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
4392	OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1);
4393}
4394
4395
4396void
4397MGADisplayPowerManagementSetCrtc2(ScrnInfoPtr pScrn, int PowerManagementMode,
4398				  int flags)
4399{
4400	MGAPtr pMga = MGAPTR(pScrn);
4401	CARD32 val = INREG(MGAREG_C2CTL);
4402
4403	if (PowerManagementMode==DPMSModeOn) {
4404		/* Enable CRTC2 */
4405		val |= MGAREG_C2CTL_C2_EN;
4406		val &= ~MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4407		OUTREG(MGAREG_C2CTL, val);
4408		/* Restore normal MAVEN values */
4409		if (pMga->Maven) {
4410			/* if TV MODE -- for later implementation
4411				MAVW(MONEN, 0xb3);
4412				MAVW(MONSET, 0x20);
4413				MAVW(OUTMODE, 0x08);    output: SVideo/Composite
4414			        MAVW(STABLE, 0x02);             makes picture stable?
4415				fixme? linux uses 0x14...
4416				MAVW(TEST, (MAVR(TEST) & 0x10));
4417
4418			 */
4419			/* else monitor mode */
4420
4421			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONEN, 0xb2);
4422			/* must be set to this in monitor mode */
4423			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONSET, 0x20);
4424			/* output: monitor mode */
4425			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x03);
4426			/* makes picture stable? */
4427			xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x22);
4428			/* turn off test signal */
4429			xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x00);
4430		}
4431	}
4432	else {
4433		/* Disable CRTC2 video */
4434		val |= MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4435		val &= ~MGAREG_C2CTL_C2_EN;
4436		OUTREG(MGAREG_C2CTL, val);
4437
4438		/* Disable MAVEN display */
4439		if (pMga->Maven) {
4440		/* In order to blank the 2nd display, we must set some MAVEN registers.
4441		 * It seems that not always the same values work on different hardware so
4442		 * we try a few different (possibly redundant) ones. */
4443			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x6a); */
4444			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x03); */
4445			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x10); */
4446			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x80);
4447		}
4448
4449	}
4450}
4451
4452
4453static void
4454MGABlockHandler (
4455    int i,
4456    pointer     blockData,
4457    pointer     pTimeout,
4458    pointer     pReadmask
4459){
4460    ScreenPtr      pScreen = screenInfo.screens[i];
4461    ScrnInfoPtr    pScrn = xf86Screens[i];
4462    MGAPtr         pMga = MGAPTR(pScrn);
4463
4464    if(pMga->PaletteLoadCallback)
4465	(*pMga->PaletteLoadCallback)(pScrn);
4466
4467    pScreen->BlockHandler = pMga->BlockHandler;
4468    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
4469    pScreen->BlockHandler = MGABlockHandler;
4470
4471    if(pMga->VideoTimerCallback) {
4472	UpdateCurrentTime();
4473	(*pMga->VideoTimerCallback)(pScrn, currentTime.milliseconds);
4474    }
4475
4476    if(pMga->RenderCallback)
4477	(*pMga->RenderCallback)(pScrn);
4478}
4479
4480#if defined (EXTRADEBUG)
4481/*
4482 * some functions to track input/output in the server
4483 */
4484
4485CARD8
4486MGAdbg_inreg8(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4487{
4488    CARD8 ret;
4489
4490    ret = MMIO_IN8(MGAPTR(pScrn)->IOBase,addr);
4491    if(verbose)
4492	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4493			"inreg8 : %s: 0x%8x = 0x%x\n",func, addr,ret);
4494    return ret;
4495}
4496
4497CARD16
4498MGAdbg_inreg16(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4499{
4500    CARD16 ret;
4501
4502    ret = MMIO_IN16(MGAPTR(pScrn)->IOBase,addr);
4503    if(verbose)
4504	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4505			"inreg16: %s: 0x%8x = 0x%x\n",func, addr,ret);
4506    return ret;
4507}
4508
4509CARD32
4510MGAdbg_inreg32(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4511{
4512    CARD32 ret;
4513
4514    ret = MMIO_IN32(MGAPTR(pScrn)->IOBase,addr);
4515    if(verbose)
4516	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4517			"inreg32: %s: 0x%8x = 0x%x\n",func, addr,ret);
4518    return ret;
4519}
4520
4521void
4522MGAdbg_outreg8(ScrnInfoPtr pScrn,int addr,int val, char* func)
4523{
4524    CARD8 ret;
4525
4526#if 0
4527    if( addr = MGAREG_CRTCEXT_DATA )
4528    	return;
4529#endif
4530    if( addr != 0x3c00 ) {
4531	ret = MGAdbg_inreg8(pScrn,addr,0,func);
4532	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4533			"outreg8 : %s: 0x%8x = 0x%x was 0x%x\n",
4534			func,addr,val,ret);
4535    }
4536    else {
4537	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "outreg8 : %s: index 0x%x\n",
4538	func,val);
4539    }
4540    MMIO_OUT8(MGAPTR(pScrn)->IOBase,addr,val);
4541}
4542
4543void
4544MGAdbg_outreg16(ScrnInfoPtr pScrn,int addr,int val, char* func)
4545{
4546    CARD16 ret;
4547
4548#if 0
4549    if (addr == MGAREG_CRTCEXT_INDEX)
4550    	return;
4551#endif
4552    ret = MGAdbg_inreg16(pScrn,addr,0, func);
4553    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4554			"outreg16: %s: 0x%8x = 0x%x was 0x%x\n",
4555			func,addr,val,ret);
4556    MMIO_OUT16(MGAPTR(pScrn)->IOBase,addr,val);
4557}
4558
4559void
4560MGAdbg_outreg32(ScrnInfoPtr pScrn,int addr,int val, char* func)
4561{
4562    CARD32 ret;
4563
4564    if (((addr & 0xff00) == 0x1c00)
4565    	&& (addr != 0x1c04)
4566/*    	&& (addr != 0x1c1c) */
4567    	&& (addr != 0x1c20)
4568    	&& (addr != 0x1c24)
4569    	&& (addr != 0x1c80)
4570    	&& (addr != 0x1c8c)
4571    	&& (addr != 0x1c94)
4572    	&& (addr != 0x1c98)
4573    	&& (addr != 0x1c9c)
4574	 ) {
4575	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: refused address 0x%x\n",
4576			func,addr);
4577    	return;
4578    }
4579    ret = MGAdbg_inreg32(pScrn,addr,0, func);
4580    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4581			"outreg32: %s: 0x%8x = 0x%x was 0x%x\n",
4582			func,addr,val,ret);
4583    MMIO_OUT32(MGAPTR(pScrn)->IOBase,addr,val);
4584}
4585#endif /* DEBUG */
4586
4587static void
4588MGAG100BlackMagic(ScrnInfoPtr pScrn)
4589{
4590    MGAPtr pMga = MGAPTR(pScrn);
4591
4592    OUTREG(MGAREG_PLNWT, ~(CARD32)0x0);
4593    /* reset memory */
4594    OUTREG(MGAREG_MACCESS, 1<<15);
4595    usleep(10);
4596}
4597
4598