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