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