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