mga_driver.c revision 6f68ce78
1fe5e51b7Smrg/*
2fe5e51b7Smrg * MGA Millennium (MGA2064W) with Ti3026 RAMDAC driver v.1.1
3fe5e51b7Smrg *
4fe5e51b7Smrg * The driver is written without any chip documentation. All extended ports
5fe5e51b7Smrg * and registers come from tracing the VESA-ROM functions.
6fe5e51b7Smrg * The BitBlt Engine comes from tracing the windows BitBlt function.
7fe5e51b7Smrg *
8fe5e51b7Smrg * Author:	Radoslaw Kapitan, Tarnow, Poland
9fe5e51b7Smrg *			kapitan@student.uci.agh.edu.pl
10fe5e51b7Smrg *		original source
11fe5e51b7Smrg *
12fe5e51b7Smrg * Now that MATROX has released documentation to the public, enhancing
13fe5e51b7Smrg * this driver has become much easier. Nevertheless, this work continues
14fe5e51b7Smrg * to be based on Radoslaw's original source
15fe5e51b7Smrg *
16fe5e51b7Smrg * Contributors:
17fe5e51b7Smrg *		Andrew van der Stock
18fe5e51b7Smrg *			ajv@greebo.net
19fe5e51b7Smrg *		additions, corrections, cleanups
20fe5e51b7Smrg *
21fe5e51b7Smrg *		Dirk Hohndel
22fe5e51b7Smrg *			hohndel@XFree86.Org
23fe5e51b7Smrg *		integrated into XFree86-3.1.2Gg
24fe5e51b7Smrg *		fixed some problems with PCI probing and mapping
25fe5e51b7Smrg *
26fe5e51b7Smrg *		David Dawes
27fe5e51b7Smrg *			dawes@XFree86.Org
28fe5e51b7Smrg *		some cleanups, and fixed some problems
29fe5e51b7Smrg *
30fe5e51b7Smrg *		Andrew E. Mileski
31fe5e51b7Smrg *			aem@ott.hookup.net
32fe5e51b7Smrg *		RAMDAC timing, and BIOS stuff
33fe5e51b7Smrg *
34fe5e51b7Smrg *		Leonard N. Zubkoff
35fe5e51b7Smrg *			lnz@dandelion.com
36fe5e51b7Smrg *		Support for 8MB boards, RGB Sync-on-Green, and DPMS.
37fe5e51b7Smrg *		Guy DESBIEF
38fe5e51b7Smrg *			g.desbief@aix.pacwan.net
39fe5e51b7Smrg *		RAMDAC MGA1064 timing,
40fe5e51b7Smrg *		Doug Merritt
41fe5e51b7Smrg *			doug@netcom.com
42fe5e51b7Smrg *		Fixed 32bpp hires 8MB horizontal line glitch at middle right
43fe5e51b7Smrg *		Niels Gram Jeppesen
44fe5e51b7Smrg *		Added digital screen option for first head
45fe5e51b7Smrg */
46fe5e51b7Smrg
47fe5e51b7Smrg#ifdef HAVE_CONFIG_H
48fe5e51b7Smrg#include "config.h"
49fe5e51b7Smrg#endif
50fe5e51b7Smrg
51fe5e51b7Smrg/* All drivers should typically include these */
52fe5e51b7Smrg#include "xf86.h"
53fe5e51b7Smrg#include "xf86_OSproc.h"
54643b027fSmrg
550bb88ba4Smrg#ifdef HAVE_XF86MODEBANDWIDTH
560bb88ba4Smrg#include "xf86Modes.h"
570bb88ba4Smrg#endif
580bb88ba4Smrg
59643b027fSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
60fe5e51b7Smrg#include "xf86Resources.h"
61643b027fSmrg#include "xf86RAC.h"
62643b027fSmrg#endif
63fe5e51b7Smrg
64fe5e51b7Smrg/* All drivers need this */
65fe5e51b7Smrg
66fe5e51b7Smrg#include "compiler.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#include "micmap.h"
77fe5e51b7Smrg
78fe5e51b7Smrg#include "xf86DDC.h"
79643b027fSmrg
80fe5e51b7Smrg#include "vbe.h"
81fe5e51b7Smrg
82fe5e51b7Smrg#include "fb.h"
83fe5e51b7Smrg#include "dixstruct.h"
84fe5e51b7Smrg
85fe5e51b7Smrg#include "mga_reg.h"
86fe5e51b7Smrg#include "mga.h"
87fe5e51b7Smrg#include "mga_macros.h"
88fe5e51b7Smrg#include "mga_maven.h"
89fe5e51b7Smrg
90acd6767fSmrg#ifdef USE_XAA
91fe5e51b7Smrg#include "xaa.h"
92fe5e51b7Smrg#endif
93fe5e51b7Smrg
94fe5e51b7Smrg#include "xf86cmap.h"
95fe5e51b7Smrg#include "shadowfb.h"
96fe5e51b7Smrg#include "fbdevhw.h"
97fe5e51b7Smrg
980bb88ba4Smrg#ifdef MGADRI
99fe5e51b7Smrg#include "dri.h"
100fe5e51b7Smrg#endif
101fe5e51b7Smrg
102fe5e51b7Smrg#include <unistd.h>
103fe5e51b7Smrg
104fe5e51b7Smrg/*
105fe5e51b7Smrg * Forward definitions for the functions that make up the driver.
106fe5e51b7Smrg */
107fe5e51b7Smrg
108fe5e51b7Smrg/* Mandatory functions */
109fe5e51b7Smrgstatic const OptionInfoRec *	MGAAvailableOptions(int chipid, int busid);
110fe5e51b7Smrgstatic void	MGAIdentify(int flags);
111fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
112fe5e51b7Smrgstatic Bool MGAPciProbe(DriverPtr drv, int entity_num,
113fe5e51b7Smrg    struct pci_device * dev, intptr_t match_data);
114fe5e51b7Smrg#else
115fe5e51b7Smrgstatic Bool	MGAProbe(DriverPtr drv, int flags);
116fe5e51b7Smrg#endif
117fe5e51b7Smrgstatic Bool	MGAPreInit(ScrnInfoPtr pScrn, int flags);
1180bb88ba4Smrgstatic Bool	MGAScreenInit(SCREEN_INIT_ARGS_DECL);
1190bb88ba4Smrgstatic Bool	MGAEnterVT(VT_FUNC_ARGS_DECL);
1200bb88ba4Smrgstatic Bool	MGAEnterVTFBDev(VT_FUNC_ARGS_DECL);
1210bb88ba4Smrgstatic void	MGALeaveVT(VT_FUNC_ARGS_DECL);
1220bb88ba4Smrgstatic Bool	MGACloseScreen(CLOSE_SCREEN_ARGS_DECL);
123fe5e51b7Smrgstatic Bool	MGASaveScreen(ScreenPtr pScreen, int mode);
124fe5e51b7Smrgstatic Bool	MGASaveScreenCrtc2(ScreenPtr pScreen, int mode);
125fe5e51b7Smrg
126fe5e51b7Smrg/* Optional functions */
1270bb88ba4Smrgstatic void	MGAFreeScreen(FREE_SCREEN_ARGS_DECL);
1280bb88ba4Smrgstatic ModeStatus MGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
129fe5e51b7Smrg			       Bool verbose, int flags);
130fe5e51b7Smrg
131fe5e51b7Smrg#if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ >= 4)
132fe5e51b7Smrg#define __must_check  __attribute__((warn_unused_result))
133fe5e51b7Smrg#else
134fe5e51b7Smrg#define __must_check  /* */
135fe5e51b7Smrg#endif
136fe5e51b7Smrg
137fe5e51b7Smrg/* Internally used functions */
138fe5e51b7Smrgstatic Bool __must_check MGAMapMem(ScrnInfoPtr pScrn);
139fe5e51b7Smrgstatic Bool	MGAUnmapMem(ScrnInfoPtr pScrn);
140fe5e51b7Smrgstatic void	MGASave(ScrnInfoPtr pScrn);
141fe5e51b7Smrgstatic void	MGARestore(ScrnInfoPtr pScrn);
142fe5e51b7Smrgstatic Bool	MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
1430bb88ba4Smrgstatic void 	MGABlockHandler(BLOCKHANDLER_ARGS_DECL);
144fe5e51b7Smrgstatic void	MGAG100BlackMagic(ScrnInfoPtr pScrn);
145fe5e51b7Smrg
146fe5e51b7Smrgstatic int MGAEntityIndex = -1;
147fe5e51b7Smrg
148fe5e51b7Smrg#include "mga_merge.h"
149fe5e51b7Smrg
150eda3803bSmrgstatic const struct mga_device_attributes attribs[] = {
151fe5e51b7Smrg    /* 2064 */
152fe5e51b7Smrg    [0] = { 1, 0, 0, 1, 0, 0, 0, 0, old_BARs,
153eda3803bSmrg	    (BLK_OPAQUE_EXPANSION | FASTBLT_BUG | USE_LINEAR_EXPANSION),
154eda3803bSmrg	{
155eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
156eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
157eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
158eda3803bSmrg	    50000,             /* Memory clock */
159eda3803bSmrg	    14318,             /* PLL reference frequency */
160eda3803bSmrg	    0,                 /* Supports fast bitblt? */
161eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
162eda3803bSmrg	},
163eda3803bSmrg
164eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
165eda3803bSmrg    },
166fe5e51b7Smrg
167fe5e51b7Smrg    /* 1064 */
168fe5e51b7Smrg    [1] = { 0, 1, 0, 0, 1, 0, 0, 0, probe_BARs,
169eda3803bSmrg            (USE_LINEAR_EXPANSION),
170eda3803bSmrg	{
171eda3803bSmrg	    /* There used to be code in MGARamdacInit (mga_dacG.c) that would
172eda3803bSmrg	     * set this to 170000 if the chip revision was less than 3.  Is
173eda3803bSmrg	     * that needed here?
174eda3803bSmrg	     */
175eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
176eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
177eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
178eda3803bSmrg	    50000,             /* Memory clock */
179eda3803bSmrg	    14318,             /* PLL reference frequency */
180eda3803bSmrg	    0,                 /* Supports fast bitblt? */
181eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
182eda3803bSmrg	},
183eda3803bSmrg
184eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
185eda3803bSmrg    },
186eda3803bSmrg
187eda3803bSmrg    /* 2164 */
188fe5e51b7Smrg    [2] = { 1, 0, 0, 1, 0, 0, 0, 0, new_BARs,
189fe5e51b7Smrg            (BLK_OPAQUE_EXPANSION | TRANSC_SOLID_FILL | USE_RECTS_FOR_LINES
190eda3803bSmrg	     | USE_LINEAR_EXPANSION),
191eda3803bSmrg	{
192eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
193eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
194eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
195eda3803bSmrg	    50000,             /* Memory clock */
196eda3803bSmrg	    14318,             /* PLL reference frequency */
197eda3803bSmrg	    0,                 /* Supports fast bitblt? */
198eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
199eda3803bSmrg	},
200eda3803bSmrg
201eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
202eda3803bSmrg    },
203eda3803bSmrg
204eda3803bSmrg    /* 2164 AGP */
205eda3803bSmrg    [3] = { 1, 0, 0, 1, 0, 0, 0, 0, new_BARs,
206eda3803bSmrg            (BLK_OPAQUE_EXPANSION | TRANSC_SOLID_FILL | USE_RECTS_FOR_LINES
207eda3803bSmrg	     | USE_LINEAR_EXPANSION),
208eda3803bSmrg	{
209eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
210eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
211eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
212eda3803bSmrg	    50000,             /* Memory clock */
213eda3803bSmrg	    14318,             /* PLL reference frequency */
214eda3803bSmrg	    0,                 /* Supports fast bitblt? */
215eda3803bSmrg	    MGA_HOST_AGP_1x    /* Host interface */
216eda3803bSmrg	},
217eda3803bSmrg
218eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
219eda3803bSmrg    },
220eda3803bSmrg
221eda3803bSmrg    /* G100 PCI */
222eda3803bSmrg    [4] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
223eda3803bSmrg            (MGA_NO_PLANEMASK | USE_LINEAR_EXPANSION),
224eda3803bSmrg	{
225eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
226eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
227eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
228eda3803bSmrg	    50000,             /* Memory clock */
229eda3803bSmrg	    27050,             /* PLL reference frequency */
230eda3803bSmrg	    0,                 /* Supports fast bitblt? */
231eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
232eda3803bSmrg	},
233eda3803bSmrg
234eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
235eda3803bSmrg    },
236eda3803bSmrg
237eda3803bSmrg    /* G100 AGP */
238eda3803bSmrg    [5] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
239eda3803bSmrg            (MGA_NO_PLANEMASK | USE_LINEAR_EXPANSION),
240eda3803bSmrg	{
241eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
242eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
243eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
244eda3803bSmrg	    50000,             /* Memory clock */
245eda3803bSmrg	    27050,             /* PLL reference frequency */
246eda3803bSmrg	    0,                 /* Supports fast bitblt? */
247eda3803bSmrg	    MGA_HOST_AGP_1x    /* Host interface */
248eda3803bSmrg	},
249eda3803bSmrg
250eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
251eda3803bSmrg    },
252eda3803bSmrg
253eda3803bSmrg    /* G200 PCI */
254eda3803bSmrg    [6] = { 0, 1, 0, 0, 1, 1, 1, 1, new_BARs,
255eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
256eda3803bSmrg	{
257eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
258eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
259eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
260eda3803bSmrg	    50000,             /* Memory clock */
261eda3803bSmrg	    27050,             /* PLL reference frequency */
262eda3803bSmrg	    0,                 /* Supports fast bitblt? */
263eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
264eda3803bSmrg	},
265eda3803bSmrg
266eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
267eda3803bSmrg    },
268eda3803bSmrg
269eda3803bSmrg    /* G200 AGP */
270eda3803bSmrg    [7] = { 0, 1, 0, 0, 1, 1, 1, 1, new_BARs,
271eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
272eda3803bSmrg	{
273eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
274eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
275eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
276eda3803bSmrg	    50000,             /* Memory clock */
277eda3803bSmrg	    27050,             /* PLL reference frequency */
278eda3803bSmrg	    0,                 /* Supports fast bitblt? */
279eda3803bSmrg	    MGA_HOST_AGP_2x    /* Host interface */
280eda3803bSmrg	},
281eda3803bSmrg
282eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
283eda3803bSmrg    },
284fe5e51b7Smrg
285fe5e51b7Smrg    /* G400 / G450 */
286eda3803bSmrg    [8] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
287eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
288eda3803bSmrg	{
289eda3803bSmrg	    { 50000, 252000 }, /* System VCO frequencies */
290eda3803bSmrg	    { 50000, 252000 }, /* Pixel VCO frequencies */
291eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
292eda3803bSmrg	    200000,            /* Memory clock */
293eda3803bSmrg	    27050,             /* PLL reference frequency */
294eda3803bSmrg	    0,                 /* Supports fast bitblt? */
295eda3803bSmrg	    MGA_HOST_AGP_4x    /* Host interface */
296eda3803bSmrg	},
297eda3803bSmrg
298eda3803bSmrg	32768, 0x1000,         /* Memory probe size & offset values */
299eda3803bSmrg    },
300fe5e51b7Smrg
301fe5e51b7Smrg    /* G550 */
302eda3803bSmrg    [9] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
303eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
304eda3803bSmrg	{
305eda3803bSmrg	    { 256000, 600000 }, /* System VCO frequencies */
306eda3803bSmrg	    { 256000, 600000 }, /* Pixel VCO frequencies */
307eda3803bSmrg	    { 256000, 600000 }, /* Video VCO frequencies */
308eda3803bSmrg	    284000,            /* Memory clock */
309eda3803bSmrg	    27050,             /* PLL reference frequency */
310eda3803bSmrg	    0,                 /* Supports fast bitblt? */
311eda3803bSmrg	    MGA_HOST_AGP_4x    /* Host interface */
312eda3803bSmrg	},
313eda3803bSmrg
314eda3803bSmrg	32768, 0x1000,         /* Memory probe size & offset values */
315eda3803bSmrg    },
316eda3803bSmrg
317eda3803bSmrg    /* G200SE A PCI */
3186f68ce78Smrg    [10] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
319eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
320eda3803bSmrg	{
321eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
322eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
323eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
324eda3803bSmrg	    50000,            /* Memory clock */
325eda3803bSmrg	    27050,             /* PLL reference frequency */
326eda3803bSmrg	    0,                 /* Supports fast bitblt? */
327eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
328eda3803bSmrg	},
329eda3803bSmrg
330eda3803bSmrg	4096, 0x800,           /* Memory probe size & offset values */
331eda3803bSmrg    },
332eda3803bSmrg
333eda3803bSmrg    /* G200SE B PCI */
3346f68ce78Smrg    [11] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
335eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
336eda3803bSmrg	{
337eda3803bSmrg	    { 50000, 114000 }, /* System VCO frequencies */
338eda3803bSmrg	    { 50000, 114000 }, /* Pixel VCO frequencies */
339eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
340eda3803bSmrg	    45000,            /* Memory clock */
341eda3803bSmrg	    27050,             /* PLL reference frequency */
342eda3803bSmrg	    0,                 /* Supports fast bitblt? */
343eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
344eda3803bSmrg	},
345eda3803bSmrg
346eda3803bSmrg	4096, 0x800,           /* Memory probe size & offset values */
347eda3803bSmrg    },
348eda3803bSmrg
349eda3803bSmrg    /* G200EV */
350eda3803bSmrg    [12] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
351eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
352eda3803bSmrg	{
353eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
354eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
355eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
356eda3803bSmrg	    45000,            /* Memory clock */
357eda3803bSmrg	    27050,             /* PLL reference frequency */
358eda3803bSmrg	    0,                 /* Supports fast bitblt? */
359eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
360eda3803bSmrg	},
361eda3803bSmrg
362a31a186aSmrg	16384, 0x4000,          /* Memory probe size & offset values */
363eda3803bSmrg    },
364eda3803bSmrg
365eda3803bSmrg    /* G200WB */
366eda3803bSmrg    [13] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
367eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
368eda3803bSmrg	{
369eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
370eda3803bSmrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
371eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
372eda3803bSmrg	    45000,            /* Memory clock */
373eda3803bSmrg	    27050,             /* PLL reference frequency */
374eda3803bSmrg	    0,                 /* Supports fast bitblt? */
375eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
376eda3803bSmrg	},
377eda3803bSmrg
378eda3803bSmrg	8192, 0x4000,          /* Memory probe size & offset values */
379eda3803bSmrg    },
380fe5e51b7Smrg
381a31a186aSmrg    /* G200EH */
382a31a186aSmrg    [14] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
383a31a186aSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
384a31a186aSmrg	{
385a31a186aSmrg	    { 50000, 230000 }, /* System VCO frequencies */
386a31a186aSmrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
387a31a186aSmrg	    { 0, 0 },          /* Video VCO frequencies */
388a31a186aSmrg	    45000,            /* Memory clock */
389a31a186aSmrg	    27050,             /* PLL reference frequency */
390a31a186aSmrg	    0,                 /* Supports fast bitblt? */
391a31a186aSmrg	    MGA_HOST_PCI       /* Host interface */
392a31a186aSmrg	},
393a31a186aSmrg
394a31a186aSmrg	8192, 0x4000,          /* Memory probe size & offset values */
395a31a186aSmrg    },
396a31a186aSmrg
3970bb88ba4Smrg    /* G200ER */
3980bb88ba4Smrg    [15] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
3990bb88ba4Smrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
4000bb88ba4Smrg	{
4010bb88ba4Smrg	    { 50000, 230000 }, /* System VCO frequencies */
4020bb88ba4Smrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
4030bb88ba4Smrg	    { 0, 0 },          /* Video VCO frequencies */
4040bb88ba4Smrg	    45000,            /* Memory clock */
4050bb88ba4Smrg	    27050,             /* PLL reference frequency */
4060bb88ba4Smrg	    0,                 /* Supports fast bitblt? */
4070bb88ba4Smrg	    MGA_HOST_PCI       /* Host interface */
4080bb88ba4Smrg	},
4090bb88ba4Smrg
4106f68ce78Smrg	16384, 0x4000,          /* Memory probe size & offset values */
4116f68ce78Smrg    },
4126f68ce78Smrg
4136f68ce78Smrg    /* G200WB */
4146f68ce78Smrg    [16] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
4156f68ce78Smrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
4166f68ce78Smrg	{
4176f68ce78Smrg	    { 50000, 230000 }, /* System VCO frequencies */
4186f68ce78Smrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
4196f68ce78Smrg	    { 0, 0 },          /* Video VCO frequencies */
4206f68ce78Smrg	    45000,            /* Memory clock */
4216f68ce78Smrg	    27050,             /* PLL reference frequency */
4226f68ce78Smrg	    0,                 /* Supports fast bitblt? */
4236f68ce78Smrg	    MGA_HOST_PCI       /* Host interface */
4246f68ce78Smrg	},
4256f68ce78Smrg
4260bb88ba4Smrg	16384, 0x4000,          /* Memory probe size & offset values */
4270bb88ba4Smrg    }
428fe5e51b7Smrg};
429fe5e51b7Smrg
430fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
431fe5e51b7Smrg#define MGA_DEVICE_MATCH(d, i) \
432fe5e51b7Smrg    { 0x102B, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
433fe5e51b7Smrg#define MGA_SUBDEVICE_MATCH(d, s, i) \
434fe5e51b7Smrg    { 0x102B, (d), 0x102B, (s), 0, 0, (i) }
435fe5e51b7Smrg
436fe5e51b7Smrgstatic const struct pci_id_match mga_device_match[] = {
437eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2064,     0),
438eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA1064,     1),
439eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164,     2),
440eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164_AGP, 3),
441eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100,     4),
442eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100_PCI, 5),
443eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200,     6),
444eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_PCI, 7),
445eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG400,     8),
446eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG550,     9),
447eda3803bSmrg
448eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_A_PCI, 10),
449eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_B_PCI, 11),
450eda3803bSmrg
451eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_EV_PCI, 12),
452eda3803bSmrg
453eda3803bSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_WINBOND_PCI, 13 ),
454fe5e51b7Smrg
455a31a186aSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EH_PCI, 14 ),
456a31a186aSmrg
4576f68ce78Smrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_ER_PCI, 15 ),
4586f68ce78Smrg
4596f68ce78Smrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EW3_PCI, 16 ),
4600bb88ba4Smrg
461fe5e51b7Smrg    { 0, 0, 0 },
462fe5e51b7Smrg};
463fe5e51b7Smrg#endif
464fe5e51b7Smrg
465fe5e51b7Smrg/* Supported chipsets */
466fe5e51b7Smrgstatic SymTabRec MGAChipsets[] = {
467fe5e51b7Smrg    { PCI_CHIP_MGA2064,		"mga2064w" },
468fe5e51b7Smrg    { PCI_CHIP_MGA1064,		"mga1064sg" },
469fe5e51b7Smrg    { PCI_CHIP_MGA2164,		"mga2164w" },
470fe5e51b7Smrg    { PCI_CHIP_MGA2164_AGP,	"mga2164w AGP" },
471fe5e51b7Smrg    { PCI_CHIP_MGAG100,		"mgag100" },
472fe5e51b7Smrg    { PCI_CHIP_MGAG100_PCI,	"mgag100 PCI" },
473fe5e51b7Smrg    { PCI_CHIP_MGAG200,		"mgag200" },
474fe5e51b7Smrg    { PCI_CHIP_MGAG200_PCI,	"mgag200 PCI" },
475fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI,	"mgag200 SE A PCI" },
476fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI,	"mgag200 SE B PCI" },
477eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI,	"mgag200 EV Maxim" },
4780bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI,	"mgag200 ER SH7757" },
479eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI,	"mgag200 eW Nuvoton" },
4806f68ce78Smrg    { PCI_CHIP_MGAG200_EW3_PCI,	"mgag200 eW3 Nuvoton" },
481a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI,	"mgag200eH" },
482fe5e51b7Smrg    { PCI_CHIP_MGAG400,		"mgag400" },
483fe5e51b7Smrg    { PCI_CHIP_MGAG550,		"mgag550" },
484fe5e51b7Smrg    {-1,			NULL }
485fe5e51b7Smrg};
486fe5e51b7Smrg
487fe5e51b7Smrgstatic PciChipsets MGAPciChipsets[] = {
488643b027fSmrg    { PCI_CHIP_MGA2064,	    PCI_CHIP_MGA2064,	RES_SHARED_VGA },
489643b027fSmrg    { PCI_CHIP_MGA1064,	    PCI_CHIP_MGA1064,	RES_SHARED_VGA },
490643b027fSmrg    { PCI_CHIP_MGA2164,	    PCI_CHIP_MGA2164,	RES_SHARED_VGA },
491643b027fSmrg    { PCI_CHIP_MGA2164_AGP, PCI_CHIP_MGA2164_AGP,RES_SHARED_VGA },
492643b027fSmrg    { PCI_CHIP_MGAG100,	    PCI_CHIP_MGAG100,	RES_SHARED_VGA },
493643b027fSmrg    { PCI_CHIP_MGAG100_PCI, PCI_CHIP_MGAG100_PCI,RES_SHARED_VGA },
494643b027fSmrg    { PCI_CHIP_MGAG200,	    PCI_CHIP_MGAG200,	RES_SHARED_VGA },
495643b027fSmrg    { PCI_CHIP_MGAG200_PCI, PCI_CHIP_MGAG200_PCI,RES_SHARED_VGA },
496fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI, PCI_CHIP_MGAG200_SE_B_PCI,
497643b027fSmrg	RES_SHARED_VGA },
498fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI, PCI_CHIP_MGAG200_SE_A_PCI,
499643b027fSmrg	RES_SHARED_VGA },
500eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI, PCI_CHIP_MGAG200_EV_PCI,
501643b027fSmrg	RES_SHARED_VGA },
5020bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI, PCI_CHIP_MGAG200_ER_PCI,
5030bb88ba4Smrg	RES_SHARED_VGA },
504eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI, PCI_CHIP_MGAG200_WINBOND_PCI,
505643b027fSmrg	RES_SHARED_VGA },
5066f68ce78Smrg    { PCI_CHIP_MGAG200_EW3_PCI, PCI_CHIP_MGAG200_EW3_PCI,
5076f68ce78Smrg	RES_SHARED_VGA },
508a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI, PCI_CHIP_MGAG200_EH_PCI,
509a31a186aSmrg	RES_SHARED_VGA },
510643b027fSmrg    { PCI_CHIP_MGAG400,	    PCI_CHIP_MGAG400,	RES_SHARED_VGA },
511643b027fSmrg    { PCI_CHIP_MGAG550,	    PCI_CHIP_MGAG550,	RES_SHARED_VGA },
512643b027fSmrg    { -1,			-1,		RES_UNDEFINED }
513fe5e51b7Smrg};
514fe5e51b7Smrg
515fe5e51b7Smrg/*
516fe5e51b7Smrg * This contains the functions needed by the server after loading the
517fe5e51b7Smrg * driver module.  It must be supplied, and gets added the driver list by
518fe5e51b7Smrg * the Module Setup funtion in the dynamic case.  In the static case a
519fe5e51b7Smrg * reference to this is compiled in, and this requires that the name of
520fe5e51b7Smrg * this DriverRec be an upper-case version of the driver name.
521fe5e51b7Smrg */
522fe5e51b7Smrg
523fe5e51b7Smrg_X_EXPORT DriverRec MGA_C_NAME = {
524fe5e51b7Smrg    MGA_VERSION,
525fe5e51b7Smrg    MGA_DRIVER_NAME,
526fe5e51b7Smrg    MGAIdentify,
527fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
528fe5e51b7Smrg    NULL,
529fe5e51b7Smrg#else
530fe5e51b7Smrg    MGAProbe,
531fe5e51b7Smrg#endif
532fe5e51b7Smrg    MGAAvailableOptions,
533fe5e51b7Smrg    NULL,
534fe5e51b7Smrg    0,
535fe5e51b7Smrg    NULL,
536fe5e51b7Smrg
537fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
538fe5e51b7Smrg    mga_device_match,
539fe5e51b7Smrg    MGAPciProbe
540fe5e51b7Smrg#endif
541fe5e51b7Smrg};
542fe5e51b7Smrg
543fe5e51b7Smrg
544fe5e51b7Smrgstatic const OptionInfoRec MGAOptions[] = {
545fe5e51b7Smrg    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
546fe5e51b7Smrg    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
547fe5e51b7Smrg    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
548fe5e51b7Smrg    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
549fe5e51b7Smrg    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
550fe5e51b7Smrg    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
551fe5e51b7Smrg    { OPTION_MGA_SDRAM,		"MGASDRAM",	OPTV_BOOLEAN,	{0}, FALSE },
552fe5e51b7Smrg    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
553fe5e51b7Smrg    { OPTION_FBDEV,		"UseFBDev",	OPTV_BOOLEAN,	{0}, FALSE },
554fe5e51b7Smrg    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
555fe5e51b7Smrg    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,	{0}, FALSE },
556fe5e51b7Smrg    { OPTION_OVERCLOCK_MEM,	"OverclockMem",	OPTV_BOOLEAN,	{0}, FALSE },
557fe5e51b7Smrg    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
558fe5e51b7Smrg    { OPTION_ROTATE,		"Rotate",	OPTV_ANYSTR,	{0}, FALSE },
559fe5e51b7Smrg    { OPTION_TEXTURED_VIDEO,	"TexturedVideo",OPTV_BOOLEAN,	{0}, FALSE },
560fe5e51b7Smrg    { OPTION_CRTC2HALF,		"Crtc2Half",	OPTV_BOOLEAN,	{0}, FALSE },
561fe5e51b7Smrg    { OPTION_CRTC2RAM,		"Crtc2Ram",	OPTV_INTEGER,	{0}, FALSE },
562fe5e51b7Smrg    { OPTION_INT10,		"Int10",	OPTV_BOOLEAN,	{0}, FALSE },
563fe5e51b7Smrg    { OPTION_AGP_MODE,		"AGPMode",	OPTV_INTEGER,	{0}, FALSE },
564fe5e51b7Smrg    { OPTION_AGP_SIZE,		"AGPSize",      OPTV_INTEGER,   {0}, FALSE },
565fe5e51b7Smrg    { OPTION_DIGITAL1,		"DigitalScreen1",OPTV_BOOLEAN,	{0}, FALSE },
566fe5e51b7Smrg    { OPTION_DIGITAL2,		"DigitalScreen2",OPTV_BOOLEAN,	{0}, FALSE },
567fe5e51b7Smrg    { OPTION_TV,		"TV",		OPTV_BOOLEAN,	{0}, FALSE },
568fe5e51b7Smrg    { OPTION_TVSTANDARD,	"TVStandard",	OPTV_ANYSTR,	{0}, FALSE },
569fe5e51b7Smrg    { OPTION_CABLETYPE,		"CableType",	OPTV_ANYSTR,	{0}, FALSE },
570fe5e51b7Smrg    { OPTION_NOHAL,		"NoHal",	OPTV_BOOLEAN,	{0}, FALSE },
571fe5e51b7Smrg    { OPTION_SWAPPED_HEAD,	"SwappedHead",	OPTV_BOOLEAN,	{0}, FALSE },
572fe5e51b7Smrg    { OPTION_DRI,		"DRI",		OPTV_BOOLEAN,	{0}, FALSE },
573fe5e51b7Smrg    { OPTION_MERGEDFB,		"MergedFB",	OPTV_BOOLEAN,	{0}, FALSE },
574fe5e51b7Smrg    { OPTION_HSYNC2,	"Monitor2HSync",	OPTV_ANYSTR,	{0}, FALSE },
575fe5e51b7Smrg    { OPTION_VREFRESH2,	"Monitor2VRefresh",	OPTV_ANYSTR,	{0}, FALSE },
576fe5e51b7Smrg    { OPTION_MONITOR2POS,   "Monitor2Position",	OPTV_ANYSTR,	{0}, FALSE },
577fe5e51b7Smrg    { OPTION_METAMODES,   "MetaModes",  	OPTV_ANYSTR,	{0}, FALSE },
578fe5e51b7Smrg    { OPTION_OLDDMA,		"OldDmaInit",	OPTV_BOOLEAN,	{0}, FALSE },
579fe5e51b7Smrg    { OPTION_PCIDMA,		"ForcePciDma",	OPTV_BOOLEAN,	{0}, FALSE },
580fe5e51b7Smrg    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
581eda3803bSmrg    { OPTION_KVM,		"KVM",		OPTV_BOOLEAN,	{0}, FALSE },
582fe5e51b7Smrg    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
583fe5e51b7Smrg};
584fe5e51b7Smrg
585fe5e51b7Smrg#ifdef XFree86LOADER
586fe5e51b7Smrg
587fe5e51b7Smrgstatic MODULESETUPPROTO(mgaSetup);
588fe5e51b7Smrg
589fe5e51b7Smrgstatic XF86ModuleVersionInfo mgaVersRec =
590fe5e51b7Smrg{
591fe5e51b7Smrg	MGA_DRIVER_NAME,
592fe5e51b7Smrg	MODULEVENDORSTRING,
593fe5e51b7Smrg	MODINFOSTRING1,
594fe5e51b7Smrg	MODINFOSTRING2,
595fe5e51b7Smrg	XORG_VERSION_CURRENT,
596fe5e51b7Smrg    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
597fe5e51b7Smrg	ABI_CLASS_VIDEODRV,			/* This is a video driver */
598fe5e51b7Smrg	ABI_VIDEODRV_VERSION,
599fe5e51b7Smrg	MOD_CLASS_VIDEODRV,
600fe5e51b7Smrg	{0,0,0,0}
601fe5e51b7Smrg};
602fe5e51b7Smrg
603fe5e51b7Smrg_X_EXPORT XF86ModuleData MGA_MODULE_DATA = { &mgaVersRec, mgaSetup, NULL };
604fe5e51b7Smrg
605fe5e51b7Smrgstatic pointer
606fe5e51b7SmrgmgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
607fe5e51b7Smrg{
608fe5e51b7Smrg    static Bool setupDone = FALSE;
609fe5e51b7Smrg
610fe5e51b7Smrg    /* This module should be loaded only once, but check to be sure. */
611fe5e51b7Smrg
612fe5e51b7Smrg    if (!setupDone) {
613fe5e51b7Smrg	setupDone = TRUE;
614fe5e51b7Smrg	xf86AddDriver(&MGA_C_NAME, module, 1);
615fe5e51b7Smrg	/*
616fe5e51b7Smrg	 * The return value must be non-NULL on success even though there
617fe5e51b7Smrg	 * is no TearDownProc.
618fe5e51b7Smrg	 */
619fe5e51b7Smrg	return (pointer)1;
620fe5e51b7Smrg    } else {
621fe5e51b7Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
622fe5e51b7Smrg	return NULL;
623fe5e51b7Smrg    }
624fe5e51b7Smrg}
625fe5e51b7Smrg
626fe5e51b7Smrg
627fe5e51b7Smrg#endif /* XFree86LOADER */
628fe5e51b7Smrg
629fe5e51b7Smrg/*
630fe5e51b7Smrg * ramdac info structure initialization
631fe5e51b7Smrg */
632fe5e51b7Smrgstatic MGARamdacRec DacInit = {
633fe5e51b7Smrg	FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
634fe5e51b7Smrg	90000, /* maxPixelClock */
635fe5e51b7Smrg	0, X_DEFAULT, X_DEFAULT, FALSE
636fe5e51b7Smrg};
637fe5e51b7Smrg
638fe5e51b7SmrgBool
639fe5e51b7SmrgMGAGetRec(ScrnInfoPtr pScrn)
640fe5e51b7Smrg{
641fe5e51b7Smrg    /*
642fe5e51b7Smrg     * Allocate an MGARec, and hook it into pScrn->driverPrivate.
643fe5e51b7Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
644fe5e51b7Smrg     * the allocation has already been done.
645fe5e51b7Smrg     */
646fe5e51b7Smrg    if (pScrn->driverPrivate != NULL)
647fe5e51b7Smrg	return TRUE;
648fe5e51b7Smrg
649fe5e51b7Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(MGARec), 1);
650fe5e51b7Smrg    /* Initialise it */
651fe5e51b7Smrg
652fe5e51b7Smrg    MGAPTR(pScrn)->Dac = DacInit;
653fe5e51b7Smrg    return TRUE;
654fe5e51b7Smrg}
655fe5e51b7Smrg
656fe5e51b7Smrgvoid
657fe5e51b7SmrgMGAFreeRec(ScrnInfoPtr pScrn)
658fe5e51b7Smrg{
6590bb88ba4Smrg    free(pScrn->driverPrivate);
660fe5e51b7Smrg    pScrn->driverPrivate = NULL;
661fe5e51b7Smrg}
662fe5e51b7Smrg
663fe5e51b7Smrgstatic const OptionInfoRec *
664fe5e51b7SmrgMGAAvailableOptions(int chipid, int busid)
665fe5e51b7Smrg{
666fe5e51b7Smrg    return MGAOptions;
667fe5e51b7Smrg}
668fe5e51b7Smrg
669fe5e51b7Smrg/* Mandatory */
670fe5e51b7Smrgstatic void
671fe5e51b7SmrgMGAIdentify(int flags)
672fe5e51b7Smrg{
673fe5e51b7Smrg    xf86PrintChipsets(MGA_NAME, "driver for Matrox chipsets", MGAChipsets);
674fe5e51b7Smrg}
675fe5e51b7Smrg
676fe5e51b7Smrg
677fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
678fe5e51b7SmrgBool
679fe5e51b7SmrgMGAPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev,
680fe5e51b7Smrg	    intptr_t match_data)
681fe5e51b7Smrg{
682fe5e51b7Smrg    ScrnInfoPtr pScrn = NULL;
683fe5e51b7Smrg    EntityInfoPtr pEnt;
684fe5e51b7Smrg    MGAPtr pMga;
685fe5e51b7Smrg
6860bb88ba4Smrg    if (pci_device_has_kernel_driver(dev)) {
687acd6767fSmrg	/* If it's a G200 server chip, it's probably on KMS, so bail; if not,
688acd6767fSmrg	 * it might be using matroxfb, which is ok. */
689acd6767fSmrg	switch (dev->device_id) {
690acd6767fSmrg	    case PCI_CHIP_MGAG200_SE_A_PCI:
691acd6767fSmrg	    case PCI_CHIP_MGAG200_SE_B_PCI:
692acd6767fSmrg	    case PCI_CHIP_MGAG200_EV_PCI:
693acd6767fSmrg	    case PCI_CHIP_MGAG200_ER_PCI:
694acd6767fSmrg	    case PCI_CHIP_MGAG200_WINBOND_PCI:
695acd6767fSmrg	    case PCI_CHIP_MGAG200_EH_PCI:
696acd6767fSmrg		xf86DrvMsg(0, X_ERROR,
697acd6767fSmrg	                   "mga: The PCI device 0x%x at %2.2d@%2.2d:%2.2d:%1.1d has a kernel module claiming it.\n",
698acd6767fSmrg	                   dev->device_id, dev->bus, dev->domain, dev->dev, dev->func);
699acd6767fSmrg	        xf86DrvMsg(0, X_ERROR,
700acd6767fSmrg	                   "mga: This driver cannot operate until it has been unloaded.\n");
701acd6767fSmrg	        return FALSE;
702acd6767fSmrg	}
7030bb88ba4Smrg    }
7040bb88ba4Smrg
705fe5e51b7Smrg    /* Allocate a ScrnInfoRec and claim the slot */
706fe5e51b7Smrg    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, MGAPciChipsets,
707fe5e51b7Smrg				NULL,
708fe5e51b7Smrg				NULL, NULL, NULL, NULL
709fe5e51b7Smrg				);
710fe5e51b7Smrg    if (pScrn != NULL) {
711fe5e51b7Smrg	/* Fill in what we can of the ScrnInfoRec */
712fe5e51b7Smrg	pScrn->driverVersion	= MGA_VERSION;
713fe5e51b7Smrg	pScrn->driverName	= MGA_DRIVER_NAME;
714fe5e51b7Smrg	pScrn->name		= MGA_NAME;
715fe5e51b7Smrg	pScrn->Probe		= NULL;
716fe5e51b7Smrg	pScrn->PreInit		= MGAPreInit;
717fe5e51b7Smrg	pScrn->ScreenInit	= MGAScreenInit;
718fe5e51b7Smrg	pScrn->SwitchMode	= MGASwitchMode;
719fe5e51b7Smrg	pScrn->AdjustFrame	= MGAAdjustFrame;
720fe5e51b7Smrg	pScrn->EnterVT		= MGAEnterVT;
721fe5e51b7Smrg	pScrn->LeaveVT		= MGALeaveVT;
722fe5e51b7Smrg	pScrn->FreeScreen	= MGAFreeScreen;
723fe5e51b7Smrg	pScrn->ValidMode	= MGAValidMode;
724fe5e51b7Smrg
725fe5e51b7Smrg
726fe5e51b7Smrg	/* Allocate the MGARec driverPrivate */
727fe5e51b7Smrg	if (!MGAGetRec(pScrn)) {
728fe5e51b7Smrg	    return FALSE;
729fe5e51b7Smrg	}
730fe5e51b7Smrg
731fe5e51b7Smrg	pMga = MGAPTR(pScrn);
732fe5e51b7Smrg	pMga->chip_attribs = & attribs[ match_data ];
733fe5e51b7Smrg	pMga->PciInfo = dev;
734fe5e51b7Smrg
735fe5e51b7Smrg
736fe5e51b7Smrg	/*
737fe5e51b7Smrg	 * For cards that can do dual head per entity, mark the entity
738fe5e51b7Smrg	 * as sharable.
739fe5e51b7Smrg	 */
740fe5e51b7Smrg	pEnt = xf86GetEntityInfo(entity_num);
741fe5e51b7Smrg	if (pMga->chip_attribs->dual_head_possible) {
742fe5e51b7Smrg	    MGAEntPtr pMgaEnt = NULL;
743fe5e51b7Smrg	    DevUnion *pPriv;
744fe5e51b7Smrg
745fe5e51b7Smrg	    xf86SetEntitySharable(entity_num);
746fe5e51b7Smrg	    /* Allocate an entity private if necessary */
747fe5e51b7Smrg	    if (MGAEntityIndex < 0)
748fe5e51b7Smrg	      MGAEntityIndex = xf86AllocateEntityPrivateIndex();
749fe5e51b7Smrg	    pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
750fe5e51b7Smrg	    if (!pPriv->ptr) {
751fe5e51b7Smrg		pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
752fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
753fe5e51b7Smrg		pMgaEnt->lastInstance = -1;
754fe5e51b7Smrg	    } else {
755fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
756fe5e51b7Smrg	    }
757fe5e51b7Smrg	    /*
758fe5e51b7Smrg	     * Set the entity instance for this instance of the driver.  For
759fe5e51b7Smrg	     * dual head per card, instance 0 is the "master" instance, driving
760fe5e51b7Smrg	     * the primary head, and instance 1 is the "slave".
761fe5e51b7Smrg	     */
762fe5e51b7Smrg	    pMgaEnt->lastInstance++;
763fe5e51b7Smrg	    xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
764fe5e51b7Smrg					   pMgaEnt->lastInstance);
765fe5e51b7Smrg	}
766fe5e51b7Smrg    }
767fe5e51b7Smrg
768fe5e51b7Smrg    return (pScrn != NULL);
769fe5e51b7Smrg}
770fe5e51b7Smrg
771fe5e51b7Smrg#else
772fe5e51b7Smrg
773fe5e51b7Smrg/* Mandatory */
774fe5e51b7Smrgstatic Bool
775fe5e51b7SmrgMGAProbe(DriverPtr drv, int flags)
776fe5e51b7Smrg{
777fe5e51b7Smrg    int i;
778fe5e51b7Smrg    GDevPtr *devSections;
779fe5e51b7Smrg    int *usedChips = NULL;
780fe5e51b7Smrg    int numDevSections;
781fe5e51b7Smrg    int numUsed;
782fe5e51b7Smrg    Bool foundScreen = FALSE;
783fe5e51b7Smrg
784fe5e51b7Smrg    /*
785fe5e51b7Smrg     * The aim here is to find all cards that this driver can handle,
786fe5e51b7Smrg     * and for the ones not already claimed by another driver, claim the
787fe5e51b7Smrg     * slot, and allocate a ScrnInfoRec.
788fe5e51b7Smrg     *
789fe5e51b7Smrg     * This should be a minimal probe, and it should under no circumstances
790fe5e51b7Smrg     * change the state of the hardware.  Because a device is found, don't
791fe5e51b7Smrg     * assume that it will be used.  Don't do any initialisations other than
792fe5e51b7Smrg     * the required ScrnInfoRec initialisations.  Don't allocate any new
793fe5e51b7Smrg     * data structures.
794fe5e51b7Smrg     */
795fe5e51b7Smrg
796fe5e51b7Smrg    /*
797fe5e51b7Smrg     * Check if there has been a chipset override in the config file.
798fe5e51b7Smrg     * For this we must find out if there is an active device section which
799fe5e51b7Smrg     * is relevant, i.e., which has no driver specified or has THIS driver
800fe5e51b7Smrg     * specified.
801fe5e51b7Smrg     */
802fe5e51b7Smrg
803fe5e51b7Smrg    if ((numDevSections = xf86MatchDevice(MGA_DRIVER_NAME,
804fe5e51b7Smrg					  &devSections)) <= 0) {
805fe5e51b7Smrg	/*
806fe5e51b7Smrg	 * There's no matching device section in the config file, so quit
807fe5e51b7Smrg	 * now.
808fe5e51b7Smrg	 */
809fe5e51b7Smrg	return FALSE;
810fe5e51b7Smrg    }
811fe5e51b7Smrg
812fe5e51b7Smrg    /*
813fe5e51b7Smrg     * We need to probe the hardware first.  We then need to see how this
814fe5e51b7Smrg     * fits in with what is given in the config file, and allow the config
815fe5e51b7Smrg     * file info to override any contradictions.
816fe5e51b7Smrg     */
817fe5e51b7Smrg
818fe5e51b7Smrg    /*
819fe5e51b7Smrg     * All of the cards this driver supports are PCI, so the "probing" just
820fe5e51b7Smrg     * amounts to checking the PCI data that the server has already collected.
821fe5e51b7Smrg     */
822fe5e51b7Smrg    if (xf86GetPciVideoInfo() == NULL) {
823fe5e51b7Smrg	/*
824fe5e51b7Smrg	 * We won't let anything in the config file override finding no
825fe5e51b7Smrg	 * PCI video cards at all.  This seems reasonable now, but we'll see.
826fe5e51b7Smrg	 */
827fe5e51b7Smrg	return FALSE;
828fe5e51b7Smrg    }
829fe5e51b7Smrg
830fe5e51b7Smrg    numUsed = xf86MatchPciInstances(MGA_NAME, PCI_VENDOR_MATROX,
831fe5e51b7Smrg			            MGAChipsets, MGAPciChipsets, devSections,
832fe5e51b7Smrg			            numDevSections, drv, &usedChips);
833fe5e51b7Smrg    /* Free it since we don't need that list after this */
8340bb88ba4Smrg    free(devSections);
835fe5e51b7Smrg    if (numUsed <= 0)
836fe5e51b7Smrg	return FALSE;
837fe5e51b7Smrg
838fe5e51b7Smrg
839fe5e51b7Smrg    if (flags & PROBE_DETECT)
840fe5e51b7Smrg	foundScreen = TRUE;
841fe5e51b7Smrg    else for (i = 0; i < numUsed; i++) {
842fe5e51b7Smrg	ScrnInfoPtr pScrn = NULL;
843fe5e51b7Smrg	EntityInfoPtr pEnt;
844fe5e51b7Smrg	int attrib_no;
845fe5e51b7Smrg
846fe5e51b7Smrg	/* Allocate a ScrnInfoRec and claim the slot */
847fe5e51b7Smrg	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
848fe5e51b7Smrg				    MGAPciChipsets, NULL, NULL,
849fe5e51b7Smrg				    NULL, NULL, NULL);
850fe5e51b7Smrg        if (pScrn != NULL) {
851fe5e51b7Smrg	    MGAPtr pMga;
852fe5e51b7Smrg
853fe5e51b7Smrg	    /* Fill in what we can of the ScrnInfoRec */
854fe5e51b7Smrg	    pScrn->driverVersion = MGA_VERSION;
855fe5e51b7Smrg	    pScrn->driverName	= MGA_DRIVER_NAME;
856fe5e51b7Smrg	    pScrn->name		= MGA_NAME;
857fe5e51b7Smrg	    pScrn->Probe	= MGAProbe;
858fe5e51b7Smrg	    pScrn->PreInit	= MGAPreInit;
859fe5e51b7Smrg	    pScrn->ScreenInit	= MGAScreenInit;
860fe5e51b7Smrg	    pScrn->SwitchMode	= MGASwitchMode;
861fe5e51b7Smrg	    pScrn->AdjustFrame	= MGAAdjustFrame;
862fe5e51b7Smrg	    pScrn->EnterVT	= MGAEnterVT;
863fe5e51b7Smrg	    pScrn->LeaveVT	= MGALeaveVT;
864fe5e51b7Smrg	    pScrn->FreeScreen	= MGAFreeScreen;
865fe5e51b7Smrg	    pScrn->ValidMode	= MGAValidMode;
866fe5e51b7Smrg
867fe5e51b7Smrg	    foundScreen = TRUE;
868fe5e51b7Smrg
869fe5e51b7Smrg	    /* Allocate the MGARec driverPrivate */
870fe5e51b7Smrg	    if (!MGAGetRec(pScrn)) {
871fe5e51b7Smrg		return FALSE;
872fe5e51b7Smrg	    }
873fe5e51b7Smrg
874fe5e51b7Smrg	    pMga = MGAPTR(pScrn);
875fe5e51b7Smrg
876fe5e51b7Smrg	    /*
877fe5e51b7Smrg	     * For cards that can do dual head per entity, mark the entity
878fe5e51b7Smrg	     * as sharable.
879fe5e51b7Smrg	     */
880fe5e51b7Smrg	    pEnt = xf86GetEntityInfo(usedChips[i]);
881fe5e51b7Smrg
882fe5e51b7Smrg            switch (pEnt->chipset) {
883fe5e51b7Smrg            case PCI_CHIP_MGA2064:
884fe5e51b7Smrg                attrib_no = 0;
885fe5e51b7Smrg                break;
886fe5e51b7Smrg
887fe5e51b7Smrg            case PCI_CHIP_MGA1064:
888fe5e51b7Smrg                attrib_no = 1;
889fe5e51b7Smrg                break;
890fe5e51b7Smrg
891fe5e51b7Smrg            case PCI_CHIP_MGA2164:
892fe5e51b7Smrg                attrib_no = 2;
893fe5e51b7Smrg                break;
894eda3803bSmrg
895eda3803bSmrg            case PCI_CHIP_MGA2164_AGP:
896eda3803bSmrg                attrib_no = 3;
897eda3803bSmrg                break;
898fe5e51b7Smrg
899fe5e51b7Smrg            case PCI_CHIP_MGAG100:
900eda3803bSmrg                attrib_no = 4;
901eda3803bSmrg                break;
902eda3803bSmrg
903fe5e51b7Smrg            case PCI_CHIP_MGAG100_PCI:
904eda3803bSmrg                attrib_no = 5;
905fe5e51b7Smrg                break;
906fe5e51b7Smrg
907fe5e51b7Smrg            case PCI_CHIP_MGAG200:
908eda3803bSmrg                attrib_no = 6;
909eda3803bSmrg                break;
910eda3803bSmrg
911fe5e51b7Smrg            case PCI_CHIP_MGAG200_PCI:
912eda3803bSmrg                attrib_no = 7;
913fe5e51b7Smrg                break;
914fe5e51b7Smrg
915fe5e51b7Smrg            case PCI_CHIP_MGAG400:
916eda3803bSmrg                attrib_no = 8;
917fe5e51b7Smrg                break;
918fe5e51b7Smrg
919fe5e51b7Smrg            case PCI_CHIP_MGAG550:
920eda3803bSmrg                attrib_no = 9;
921fe5e51b7Smrg                break;
922fe5e51b7Smrg
923fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_A_PCI:
924eda3803bSmrg                attrib_no = 10;
925eda3803bSmrg                break;
926eda3803bSmrg
927fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_B_PCI:
928eda3803bSmrg                attrib_no = 11;
929eda3803bSmrg                break;
930eda3803bSmrg
931eda3803bSmrg            case PCI_CHIP_MGAG200_EV_PCI:
932eda3803bSmrg                attrib_no = 12;
933eda3803bSmrg                break;
934eda3803bSmrg
935eda3803bSmrg            case PCI_CHIP_MGAG200_WINBOND_PCI:
936eda3803bSmrg                attrib_no = 13;
937fe5e51b7Smrg                break;
938fe5e51b7Smrg
939a31a186aSmrg            case PCI_CHIP_MGAG200_EH_PCI:
940a31a186aSmrg                attrib_no = 14;
941a31a186aSmrg                break;
9420bb88ba4Smrg
9430bb88ba4Smrg            case PCI_CHIP_MGAG200_ER_PCI:
9440bb88ba4Smrg                attrib_no = 15;
9450bb88ba4Smrg                break;
9460bb88ba4Smrg
9476f68ce78Smrg            case PCI_CHIP_MGAG200_EW3_PCI:
9486f68ce78Smrg                attrib_no = 16;
9496f68ce78Smrg                break;
950a31a186aSmrg
951fe5e51b7Smrg	    default:
952fe5e51b7Smrg		return FALSE;
953fe5e51b7Smrg            }
954fe5e51b7Smrg
955fe5e51b7Smrg	    pMga->chip_attribs = & attribs[attrib_no];
956fe5e51b7Smrg
957fe5e51b7Smrg	    if (pMga->chip_attribs->dual_head_possible) {
958fe5e51b7Smrg		MGAEntPtr pMgaEnt = NULL;
959fe5e51b7Smrg		DevUnion *pPriv;
960fe5e51b7Smrg
961fe5e51b7Smrg		xf86SetEntitySharable(usedChips[i]);
962fe5e51b7Smrg		/* Allocate an entity private if necessary */
963fe5e51b7Smrg		if (MGAEntityIndex < 0)
964fe5e51b7Smrg		    MGAEntityIndex = xf86AllocateEntityPrivateIndex();
965fe5e51b7Smrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
966fe5e51b7Smrg		if (!pPriv->ptr) {
967fe5e51b7Smrg		    pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
968fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
969fe5e51b7Smrg		    pMgaEnt->lastInstance = -1;
970fe5e51b7Smrg		} else {
971fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
972fe5e51b7Smrg		}
973fe5e51b7Smrg		/*
974fe5e51b7Smrg		 * Set the entity instance for this instance of the driver.  For
975fe5e51b7Smrg		 * dual head per card, instance 0 is the "master" instance, driving
976fe5e51b7Smrg		 * the primary head, and instance 1 is the "slave".
977fe5e51b7Smrg		 */
978fe5e51b7Smrg		pMgaEnt->lastInstance++;
979fe5e51b7Smrg		xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
980fe5e51b7Smrg					       pMgaEnt->lastInstance);
981fe5e51b7Smrg	    }
982fe5e51b7Smrg        }
983fe5e51b7Smrg    }
9840bb88ba4Smrg    free(usedChips);
985fe5e51b7Smrg
986fe5e51b7Smrg    return foundScreen;
987fe5e51b7Smrg}
988fe5e51b7Smrg#endif
989fe5e51b7Smrg
990fe5e51b7Smrg
991fe5e51b7Smrg/*
992fe5e51b7Smrg * MGASoftReset --
993fe5e51b7Smrg *
994fe5e51b7Smrg * Resets drawing engine
995fe5e51b7Smrg */
996fe5e51b7Smrgvoid
997fe5e51b7SmrgMGASoftReset(ScrnInfoPtr pScrn)
998fe5e51b7Smrg{
999fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1000fe5e51b7Smrg
1001fe5e51b7Smrg	pMga->FbMapSize = 8192 * 1024;
1002fe5e51b7Smrg	MGAMapMem(pScrn);
1003fe5e51b7Smrg
1004fe5e51b7Smrg	/* set soft reset bit */
1005fe5e51b7Smrg	OUTREG(MGAREG_Reset, 1);
1006fe5e51b7Smrg	usleep(200);
1007fe5e51b7Smrg	OUTREG(MGAREG_Reset, 0);
1008fe5e51b7Smrg
1009fe5e51b7Smrg	/* reset memory */
1010fe5e51b7Smrg	OUTREG(MGAREG_MACCESS, 1<<15);
1011fe5e51b7Smrg	usleep(10);
1012fe5e51b7Smrg
1013fe5e51b7Smrg#if 0
1014fe5e51b7Smrg	/* This will hang if the PLLs aren't on */
1015fe5e51b7Smrg
1016fe5e51b7Smrg	/* wait until drawing engine is ready */
1017fe5e51b7Smrg	while ( MGAISBUSY() )
1018fe5e51b7Smrg	    usleep(1000);
1019fe5e51b7Smrg
1020fe5e51b7Smrg	/* flush FIFO */
1021fe5e51b7Smrg	i = 32;
1022fe5e51b7Smrg	WAITFIFO(i);
1023fe5e51b7Smrg	while ( i-- )
1024fe5e51b7Smrg	    OUTREG(MGAREG_SHIFT, 0);
1025fe5e51b7Smrg#endif
1026fe5e51b7Smrg
1027fe5e51b7Smrg	MGAUnmapMem(pScrn);
1028fe5e51b7Smrg}
1029fe5e51b7Smrg
1030fe5e51b7Smrg/*
1031fe5e51b7Smrg * MGACountRAM --
1032fe5e51b7Smrg *
1033fe5e51b7Smrg * Counts amount of installed RAM
1034fe5e51b7Smrg */
1035fe5e51b7Smrgstatic int
1036fe5e51b7SmrgMGACountRam(ScrnInfoPtr pScrn)
1037fe5e51b7Smrg{
1038fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1039eda3803bSmrg    int ProbeSize = pMga->chip_attribs->probe_size;
1040eda3803bSmrg    int ProbeSizeOffset = pMga->chip_attribs->probe_offset;
1041fe5e51b7Smrg    int SizeFound = 2048;
1042fe5e51b7Smrg    CARD32 biosInfo = 0;
1043fe5e51b7Smrg    CARD8 seq1;
1044fe5e51b7Smrg
1045fe5e51b7Smrg#if 0
1046fe5e51b7Smrg    /* This isn't correct. It looks like this can have arbitrary
1047fe5e51b7Smrg	data for the memconfig even when the bios has initialized
1048fe5e51b7Smrg	it.  At least, my cards don't advertise the documented
1049fe5e51b7Smrg	values (my 8 and 16 Meg G200s have the same values) */
1050fe5e51b7Smrg    if (pMga->Primary) { /* can only trust this for primary cards */
1051fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1052fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & biosInfo,
1053fe5e51b7Smrg				PCI_OPTION_REG);
1054fe5e51b7Smrg#else
1055fe5e51b7Smrg	biosInfo = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1056fe5e51b7Smrg#endif
1057fe5e51b7Smrg    }
1058fe5e51b7Smrg#endif
1059fe5e51b7Smrg
1060fe5e51b7Smrg    switch(pMga->Chipset) {
1061fe5e51b7Smrg    case PCI_CHIP_MGA2164:
1062fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
1063fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1064fe5e51b7Smrg		"Unable to probe memory amount due to hardware bug.  "
1065fe5e51b7Smrg		"Assuming 4096 KB\n");
1066fe5e51b7Smrg	return 4096;
1067fe5e51b7Smrg    case PCI_CHIP_MGAG400:
1068fe5e51b7Smrg    case PCI_CHIP_MGAG550:
1069fe5e51b7Smrg	if(biosInfo) {
1070fe5e51b7Smrg	    switch((biosInfo >> 10) & 0x07) {
1071fe5e51b7Smrg	    case 0:
1072fe5e51b7Smrg		return (biosInfo & (1 << 14)) ? 32768 : 16384;
1073fe5e51b7Smrg	    case 1:
1074fe5e51b7Smrg	    case 2:
1075fe5e51b7Smrg		return 16384;
1076fe5e51b7Smrg	    case 3:
1077fe5e51b7Smrg	    case 5:
1078fe5e51b7Smrg		return 65536;
1079fe5e51b7Smrg	    case 4:
1080fe5e51b7Smrg		return 32768;
1081fe5e51b7Smrg	    }
1082fe5e51b7Smrg	}
1083fe5e51b7Smrg	break;
1084fe5e51b7Smrg    case PCI_CHIP_MGAG200:
1085fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
1086fe5e51b7Smrg	if(biosInfo) {
1087fe5e51b7Smrg	    switch((biosInfo >> 11) & 0x03) {
1088fe5e51b7Smrg	    case 0:
1089fe5e51b7Smrg		return 8192;
1090fe5e51b7Smrg	    default:
1091fe5e51b7Smrg		return 16384;
1092fe5e51b7Smrg	    }
1093fe5e51b7Smrg	}
1094fe5e51b7Smrg	break;
1095fe5e51b7Smrg    case PCI_CHIP_MGAG100:
1096fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
1097fe5e51b7Smrg	if(biosInfo) /* I'm not sure if the docs are correct */
1098fe5e51b7Smrg	    return (biosInfo & (1 << 12)) ? 16384 : 8192;
1099fe5e51b7Smrg        break;
1100fe5e51b7Smrg    default:
1101fe5e51b7Smrg        break;
1102fe5e51b7Smrg    }
1103fe5e51b7Smrg
1104fe5e51b7Smrg    if (pMga->FbAddress) {
1105fe5e51b7Smrg	volatile unsigned char* base;
1106fe5e51b7Smrg	unsigned char tmp;
1107fe5e51b7Smrg	int i;
1108fe5e51b7Smrg
1109fe5e51b7Smrg	pMga->FbMapSize = ProbeSize * 1024;
1110fe5e51b7Smrg	if (!MGAMapMem(pScrn)) {
1111fe5e51b7Smrg	    return 0;
1112fe5e51b7Smrg	}
1113fe5e51b7Smrg
1114fe5e51b7Smrg	base = pMga->FbBase;
1115fe5e51b7Smrg
1116eda3803bSmrg	if (pMga->is_G200SE)
1117eda3803bSmrg	    pMga->reg_1e24 = INREG(0x1e24); /* stash the model for later */
11180bb88ba4Smrg	if (pMga->reg_1e24 >= 0x01) {
1119eda3803bSmrg	    MGAUnmapMem(pScrn);
1120eda3803bSmrg	    ProbeSize = 16384;
1121eda3803bSmrg	    ProbeSizeOffset = 0x10000;
1122eda3803bSmrg	    pMga->FbMapSize = ProbeSize * 1024;
1123eda3803bSmrg	    MGAMapMem(pScrn);
1124eda3803bSmrg	    base = pMga->FbBase;
1125eda3803bSmrg	}
1126eda3803bSmrg
1127fe5e51b7Smrg	if (pMga->is_G200SE) {
1128fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1129fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1130fe5e51b7Smrg	    seq1 |= 0x20;
1131fe5e51b7Smrg	    MGAWAITVSYNC();
1132fe5e51b7Smrg	    MGAWAITBUSY();
1133fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1134fe5e51b7Smrg	    usleep(20000);
1135fe5e51b7Smrg	}
1136fe5e51b7Smrg
1137eda3803bSmrg        if (pMga->is_G200WB) {
1138eda3803bSmrg            CARD32 Option, MaxMapSize;
1139eda3803bSmrg
1140eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1141eda3803bSmrg            pci_device_cfg_read_u32(pMga->PciInfo, &Option,
1142eda3803bSmrg                                    PCI_OPTION_REG);
1143eda3803bSmrg            MaxMapSize = pMga->PciInfo->regions[0].size;
1144eda3803bSmrg#else
1145eda3803bSmrg            Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1146eda3803bSmrg            MaxMapSize = 1UL << pMga->PciInfo->size[0];
1147eda3803bSmrg#endif
1148eda3803bSmrg            Option = (Option & 0x3000000) >> 24 ;
1149eda3803bSmrg
1150eda3803bSmrg            if (Option == 2)
1151eda3803bSmrg                ProbeSize = 4*1024;
1152eda3803bSmrg            else if(Option == 1)
1153eda3803bSmrg                ProbeSize = 8*1024;
1154eda3803bSmrg            else if(Option == 0)
1155eda3803bSmrg                ProbeSize = 16*1024;
1156eda3803bSmrg
1157eda3803bSmrg            if (ProbeSize * 1024 > MaxMapSize)
1158eda3803bSmrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1159eda3803bSmrg                        "Fb size from config space doesn't fit option register\n");
1160eda3803bSmrg            else {
1161eda3803bSmrg                MGAUnmapMem(pScrn);
1162eda3803bSmrg                pMga->FbMapSize = ProbeSize * 1024;
1163eda3803bSmrg                MGAMapMem(pScrn);
1164eda3803bSmrg                base = pMga->FbBase;
1165eda3803bSmrg            }
1166eda3803bSmrg        }
1167eda3803bSmrg
1168fe5e51b7Smrg	/* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */
1169fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1170fe5e51b7Smrg	tmp = INREG8(MGAREG_CRTCEXT_DATA);
1171fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp | 0x80);
1172fe5e51b7Smrg
1173eda3803bSmrg	/* apparently the G200 IP don't have a BIOS to read */
1174a31a186aSmrg	if (pMga->is_G200SE || pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) {
1175fe5e51b7Smrg	    CARD32 MemoryAt0, MemoryAt1, Offset;
1176fe5e51b7Smrg	    CARD32 FirstMemoryVal1, FirstMemoryVal2;
1177fe5e51b7Smrg	    CARD32 SecondMemoryVal1, SecondMemoryVal2;
1178fe5e51b7Smrg	    CARD32 TestMemoryLocA, TestMemoryLocB;
1179fe5e51b7Smrg	    CARD32 TestMemoryLoc0, TestMemoryLoc1;
1180fe5e51b7Smrg	    CARD32 TestA, TestB;
1181fe5e51b7Smrg
1182fe5e51b7Smrg	    MemoryAt0 = base[0];
1183fe5e51b7Smrg	    MemoryAt1 = base[1];
1184fe5e51b7Smrg	    base[0] = 0;
1185fe5e51b7Smrg	    base[1] = 0;
1186fe5e51b7Smrg
1187fe5e51b7Smrg	    for (Offset = 0x100000; Offset < (ProbeSize * 1024);
1188eda3803bSmrg		    Offset += ProbeSizeOffset) {
1189fe5e51b7Smrg		FirstMemoryVal1 = base[Offset];
1190fe5e51b7Smrg		FirstMemoryVal2 = base[Offset+1];
1191fe5e51b7Smrg		SecondMemoryVal1 = base[Offset+0x100];
1192fe5e51b7Smrg		SecondMemoryVal2 = base[Offset+0x101];
1193fe5e51b7Smrg
1194fe5e51b7Smrg		base[Offset] = 0x55;
1195fe5e51b7Smrg		base[Offset+1] = 0xaa;
1196fe5e51b7Smrg		base[Offset+0x100] = 0x55;
1197fe5e51b7Smrg		base[Offset+0x101] = 0xaa;
1198fe5e51b7Smrg
1199eda3803bSmrg		OUTREG8(MGAREG_CRTC_INDEX, 0);
1200fe5e51b7Smrg		usleep(8);
1201fe5e51b7Smrg
1202fe5e51b7Smrg		TestMemoryLocA = base[Offset];
1203fe5e51b7Smrg		TestMemoryLocB = base[Offset+1];
1204fe5e51b7Smrg		TestMemoryLoc0 = base[0];
1205fe5e51b7Smrg		TestMemoryLoc1 = base[1];
1206fe5e51b7Smrg
1207fe5e51b7Smrg		base[Offset] = FirstMemoryVal1;
1208fe5e51b7Smrg		base[Offset+1] = FirstMemoryVal2;
1209fe5e51b7Smrg		base[Offset+0x100] = SecondMemoryVal1;
1210fe5e51b7Smrg		base[Offset+0x101] = SecondMemoryVal2;
1211fe5e51b7Smrg
1212fe5e51b7Smrg		TestA = ((TestMemoryLocB << 8) + TestMemoryLocA);
1213fe5e51b7Smrg		TestB = ((TestMemoryLoc1 << 8) + TestMemoryLoc0);
1214fe5e51b7Smrg		if ((TestA != 0xAA55) || (TestB)) {
1215fe5e51b7Smrg		    break;
1216fe5e51b7Smrg		}
1217fe5e51b7Smrg	    }
1218fe5e51b7Smrg
1219fe5e51b7Smrg	    base[0] = MemoryAt0;
1220fe5e51b7Smrg	    base[1] = MemoryAt1;
1221fe5e51b7Smrg
1222fe5e51b7Smrg	    SizeFound = (Offset / 1024) - 64;
1223fe5e51b7Smrg	} else {
1224fe5e51b7Smrg	    /* write, read and compare method
1225fe5e51b7Smrg	       split into two loops to make it more reliable on RS/6k -ReneR */
1226fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1227fe5e51b7Smrg		base[(i * 1024) - 1] = 0xAA;
1228fe5e51b7Smrg	    }
1229fe5e51b7Smrg	    OUTREG8(MGAREG_CRTC_INDEX, 0);  /* flush the cache */
1230fe5e51b7Smrg	    usleep(4);  /* twart write combination */
1231fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1232fe5e51b7Smrg		if(base[(i * 1024) - 1] == 0xAA) {
1233fe5e51b7Smrg		    SizeFound = i;
1234fe5e51b7Smrg		    break;
1235fe5e51b7Smrg		}
1236fe5e51b7Smrg	    }
1237fe5e51b7Smrg	}
1238fe5e51b7Smrg
1239fe5e51b7Smrg	/* restore CRTCEXT3 state */
1240fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1241fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp);
1242fe5e51b7Smrg
1243fe5e51b7Smrg	if (pMga->is_G200SE) {
1244fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1245fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1246fe5e51b7Smrg	    seq1 &= ~0x20;
1247fe5e51b7Smrg	    MGAWAITVSYNC();
1248fe5e51b7Smrg	    MGAWAITBUSY();
1249fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1250fe5e51b7Smrg	    usleep(20000);
1251fe5e51b7Smrg	}
1252fe5e51b7Smrg	MGAUnmapMem(pScrn);
1253fe5e51b7Smrg    }
1254fe5e51b7Smrg   return SizeFound;
1255fe5e51b7Smrg}
1256fe5e51b7Smrg
1257643b027fSmrg#ifdef  EDID_COMPLETE_RAWDATA
1258643b027fSmrg#undef  xf86DoEDID_DDC2
1259643b027fSmrg#define xf86DoEDID_DDC2(a, b) xf86DoEEDID(a, b, TRUE)
1260643b027fSmrg#endif
1261643b027fSmrg
1262fe5e51b7Smrgstatic xf86MonPtr
1263fe5e51b7SmrgMGAdoDDC(ScrnInfoPtr pScrn)
1264fe5e51b7Smrg{
1265643b027fSmrg    vgaHWPtr hwp;
1266643b027fSmrg    MGAPtr pMga;
1267643b027fSmrg    xf86MonPtr MonInfo = NULL;
12680bb88ba4Smrg    const char *from = NULL;
1269643b027fSmrg
1270643b027fSmrg    hwp = VGAHWPTR(pScrn);
1271643b027fSmrg    pMga = MGAPTR(pScrn);
1272643b027fSmrg
1273643b027fSmrg    /* Load DDC if we have the code to use it */
1274643b027fSmrg    /* This gives us DDC1 */
1275643b027fSmrg    if (pMga->ddc1Read || pMga->i2cInit) {
1276643b027fSmrg	if (!xf86LoadSubModule(pScrn, "ddc")) {
1277643b027fSmrg	    /* ddc module not found, we can do without it */
1278643b027fSmrg	    pMga->ddc1Read = NULL;
1279643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1280643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1281643b027fSmrg	    return NULL;
1282fe5e51b7Smrg	}
1283fe5e51b7Smrg    } else
1284643b027fSmrg	return NULL;
1285fe5e51b7Smrg
1286fe5e51b7Smrg    /* - DDC can use I2C bus */
1287fe5e51b7Smrg    /* Load I2C if we have the code to use it */
1288fe5e51b7Smrg    if (pMga->i2cInit) {
1289643b027fSmrg	if (!xf86LoadSubModule(pScrn, "i2c")) {
1290643b027fSmrg	    /* i2c module not found, we can do without it */
1291643b027fSmrg	    pMga->i2cInit = NULL;
1292643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1293643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1294643b027fSmrg	}
1295643b027fSmrg    }
1296643b027fSmrg
1297643b027fSmrg    /* Map the MGA memory and MMIO areas */
1298643b027fSmrg    if (!MGAMapMem(pScrn))
1299643b027fSmrg	return NULL;
1300643b027fSmrg
1301643b027fSmrg    /* Initialise the MMIO vgahw functions */
1302643b027fSmrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
1303643b027fSmrg    vgaHWGetIOBase(hwp);
1304643b027fSmrg
1305643b027fSmrg    /* Map the VGA memory when the primary video */
1306643b027fSmrg    if (pMga->Primary) {
1307643b027fSmrg	hwp->MapSize = 0x10000;
1308643b027fSmrg	if (!vgaHWMapMem(pScrn))
1309643b027fSmrg	    return NULL;
1310643b027fSmrg    } else {
1311643b027fSmrg	/* XXX Need to write an MGA mode ddc1SetSpeed */
1312643b027fSmrg	if (pMga->DDC1SetSpeed == vgaHWddc1SetSpeedWeak()) {
1313643b027fSmrg	    pMga->DDC1SetSpeed = NULL;
1314643b027fSmrg	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
1315643b027fSmrg			   "DDC1 disabled - chip not in VGA mode\n");
1316643b027fSmrg	}
1317643b027fSmrg    }
1318fe5e51b7Smrg
1319643b027fSmrg    /* Save the current state */
1320643b027fSmrg    MGASave(pScrn);
1321643b027fSmrg
1322643b027fSmrg    /* It is now safe to talk to the card */
13230bb88ba4Smrg    /* Allow access to DDC */
13240bb88ba4Smrg    if (pMga->is_G200ER) {
13250bb88ba4Smrg	 CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
13260bb88ba4Smrg     outMGAdac(MGA1064_GEN_IO_CTL2, ucData | 1);
13270bb88ba4Smrg    }
1328643b027fSmrg
1329643b027fSmrg    /* Initialize I2C buses - used by DDC if available */
1330643b027fSmrg    if (pMga->i2cInit) {
1331643b027fSmrg	pMga->i2cInit(pScrn);
1332643b027fSmrg    }
1333643b027fSmrg
1334643b027fSmrg    /* DDC for second head... */
1335643b027fSmrg    if (pMga->SecondCrtc && pMga->DDC_Bus2) {
13360bb88ba4Smrg	MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus2);
1337643b027fSmrg	from = "I2C";
1338643b027fSmrg    } else {
1339fe5e51b7Smrg	/* Its the first head... */
1340643b027fSmrg	if (pMga->DDC_Bus1) {
13410bb88ba4Smrg	    MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus1);
1342643b027fSmrg	    from = "I2C";
1343643b027fSmrg	}
1344643b027fSmrg	if (!MonInfo)
1345643b027fSmrg	    /* Read and output monitor info using DDC1 */
1346643b027fSmrg	    if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
13470bb88ba4Smrg		MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),
1348643b027fSmrg					  pMga->DDC1SetSpeed,
1349643b027fSmrg					  pMga->ddc1Read ) ;
1350643b027fSmrg		from = "DDC1";
1351643b027fSmrg	    }
1352643b027fSmrg	if (!MonInfo){
1353fe5e51b7Smrg	    vbeInfoPtr pVbe;
1354fe5e51b7Smrg	    if (xf86LoadSubModule(pScrn, "vbe")) {
1355643b027fSmrg		pVbe = VBEInit(NULL, pMga->pEnt->index);
1356643b027fSmrg		MonInfo = vbeDoEDID(pVbe, NULL);
1357643b027fSmrg		vbeFree(pVbe);
1358643b027fSmrg		from = "VBE";
1359fe5e51b7Smrg	    }
1360643b027fSmrg	}
1361643b027fSmrg    }
1362fe5e51b7Smrg
1363643b027fSmrg    if (MonInfo) {
1364643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s monitor info\n", from);
1365643b027fSmrg	xf86PrintEDID(MonInfo);
1366643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of monitor info\n");
1367643b027fSmrg    }
1368fe5e51b7Smrg
13690bb88ba4Smrg    /* Remove access to DDC */
13700bb88ba4Smrg    if (pMga->is_G200ER) {
13710bb88ba4Smrg	  CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
13720bb88ba4Smrg      outMGAdac(MGA1064_GEN_IO_CTL2, ucData & ~1);
13730bb88ba4Smrg    }
13740bb88ba4Smrg
1375643b027fSmrg    /* Restore previous state and unmap MGA memory and MMIO areas */
1376643b027fSmrg    MGARestore(pScrn);
1377643b027fSmrg    MGAUnmapMem(pScrn);
1378643b027fSmrg    /* Unmap vga memory if we mapped it */
1379643b027fSmrg    if (xf86IsPrimaryPci(pMga->PciInfo) && !pMga->FBDev) {
1380643b027fSmrg	vgaHWUnmapMem(pScrn);
1381643b027fSmrg    }
1382643b027fSmrg
1383643b027fSmrg    xf86SetDDCproperties(pScrn, MonInfo);
1384643b027fSmrg
1385643b027fSmrg    return MonInfo;
1386fe5e51b7Smrg}
1387fe5e51b7Smrg
1388fe5e51b7Smrg
1389fe5e51b7Smrgvoid
1390fe5e51b7SmrgMGAProbeDDC(ScrnInfoPtr pScrn, int index)
1391fe5e51b7Smrg{
1392fe5e51b7Smrg    vbeInfoPtr pVbe;
1393fe5e51b7Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1394fe5e51b7Smrg	pVbe = VBEInit(NULL,index);
1395fe5e51b7Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1396fe5e51b7Smrg	vbeFree(pVbe);
1397fe5e51b7Smrg    }
1398fe5e51b7Smrg}
1399fe5e51b7Smrg
1400fe5e51b7SmrgBool
1401fe5e51b7SmrgMGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
1402fe5e51b7Smrg{
1403fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1404fe5e51b7Smrg
1405fe5e51b7Smrg	if (!pMga->Maven) return FALSE;
1406fe5e51b7Smrg
1407fe5e51b7Smrg	/* FIXME: Using private interfaces for the moment until a more
1408fe5e51b7Smrg	 * flexible xf86I2CWriteRead() variant shows up for us
1409fe5e51b7Smrg	 *
1410fe5e51b7Smrg	 * MAVEN does _not_ like a start bit in the middle of its transaction
1411fe5e51b7Smrg	 * MAVEN does _not_ like ACK at the end of the transaction
1412fe5e51b7Smrg	 */
1413fe5e51b7Smrg
1414fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CStart(pMga->Maven_Bus, pMga->Maven->ByteTimeout)) return FALSE;
1415fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, MAVEN_READ)) return FALSE;
1416fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, reg)) return FALSE;
1417fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1418fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CGetByte(pMga->Maven, val, 0)) return FALSE;
1419fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1420fe5e51b7Smrg
1421fe5e51b7Smrg	return TRUE;
1422fe5e51b7Smrg}
1423fe5e51b7Smrg
1424fe5e51b7Smrg/* Mandatory */
1425fe5e51b7Smrgstatic Bool
1426fe5e51b7SmrgMGAPreInit(ScrnInfoPtr pScrn, int flags)
1427fe5e51b7Smrg{
1428fe5e51b7Smrg    MGAPtr pMga;
1429fe5e51b7Smrg    MessageType from;
1430fe5e51b7Smrg    int i;
1431fe5e51b7Smrg    double real;
1432fe5e51b7Smrg    int bytesPerPixel;
1433fe5e51b7Smrg    ClockRangePtr clockRanges;
1434fe5e51b7Smrg    const char *s;
1435fe5e51b7Smrg    int flags24;
1436fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
1437fe5e51b7Smrg    Bool Default;
1438fe5e51b7Smrg
1439fe5e51b7Smrg    /*
1440fe5e51b7Smrg     * Note: This function is only called once at server startup, and
1441fe5e51b7Smrg     * not at the start of each server generation.  This means that
1442fe5e51b7Smrg     * only things that are persistent across server generations can
1443fe5e51b7Smrg     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
1444fe5e51b7Smrg     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
1445fe5e51b7Smrg     * are too, and should be used for data that must persist across
1446fe5e51b7Smrg     * server generations.
1447fe5e51b7Smrg     *
1448fe5e51b7Smrg     * Per-generation data should be allocated with
1449fe5e51b7Smrg     * AllocateScreenPrivateIndex() from the ScreenInit() function.
1450fe5e51b7Smrg     */
1451fe5e51b7Smrg
1452fe5e51b7Smrg    /* Check the number of entities, and fail if it isn't one. */
1453fe5e51b7Smrg    if (pScrn->numEntities != 1)
1454fe5e51b7Smrg	return FALSE;
1455fe5e51b7Smrg
1456fe5e51b7Smrg
1457fe5e51b7Smrg    pMga = MGAPTR(pScrn);
1458fe5e51b7Smrg    /* Set here until dri is enabled */
14590bb88ba4Smrg#ifdef MGADRI
1460fe5e51b7Smrg    pMga->haveQuiescense = 1;
1461fe5e51b7Smrg#endif
1462fe5e51b7Smrg    /* Get the entity, and make sure it is PCI. */
1463fe5e51b7Smrg    pMga->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1464fe5e51b7Smrg    if (pMga->pEnt->location.type != BUS_PCI)
1465fe5e51b7Smrg	return FALSE;
1466fe5e51b7Smrg
1467fe5e51b7Smrg    /* Allocate an entity private if necessary */
1468fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {
1469fe5e51b7Smrg	pMgaEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1470fe5e51b7Smrg					MGAEntityIndex)->ptr;
1471fe5e51b7Smrg        pMga->entityPrivate = pMgaEnt;
1472fe5e51b7Smrg    }
1473fe5e51b7Smrg
1474fe5e51b7Smrg    /* Set pMga->device to the relevant Device section */
1475fe5e51b7Smrg    pMga->device = xf86GetDevFromEntity(pScrn->entityList[0],
1476fe5e51b7Smrg					pScrn->entityInstanceList[0]);
1477fe5e51b7Smrg
1478fe5e51b7Smrg    if (flags & PROBE_DETECT) {
1479fe5e51b7Smrg	MGAProbeDDC(pScrn, pMga->pEnt->index);
1480fe5e51b7Smrg	return TRUE;
1481fe5e51b7Smrg    }
1482fe5e51b7Smrg
1483fe5e51b7Smrg    /* The vgahw module should be loaded here when needed */
1484fe5e51b7Smrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
1485fe5e51b7Smrg	return FALSE;
1486fe5e51b7Smrg
1487fe5e51b7Smrg    /*
1488fe5e51b7Smrg     * Allocate a vgaHWRec
1489fe5e51b7Smrg     */
1490fe5e51b7Smrg    if (!vgaHWGetHWRec(pScrn))
1491fe5e51b7Smrg	return FALSE;
1492fe5e51b7Smrg
1493fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
1494fe5e51b7Smrg    /* Find the PCI info for this screen */
1495fe5e51b7Smrg    pMga->PciInfo = xf86GetPciInfoForEntity(pMga->pEnt->index);
1496fe5e51b7Smrg    pMga->PciTag = pciTag(pMga->PciInfo->bus, pMga->PciInfo->device,
1497fe5e51b7Smrg			  pMga->PciInfo->func);
1498fe5e51b7Smrg#endif
1499fe5e51b7Smrg
1500fe5e51b7Smrg    pMga->Primary = xf86IsPrimaryPci(pMga->PciInfo);
1501fe5e51b7Smrg
1502643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1503fe5e51b7Smrg    xf86SetOperatingState(resVgaIo, pMga->pEnt->index, ResUnusedOpr);
1504fe5e51b7Smrg    xf86SetOperatingState(resVgaMem, pMga->pEnt->index, ResDisableOpr);
1505643b027fSmrg#endif
1506fe5e51b7Smrg
1507fe5e51b7Smrg    /* Set pScrn->monitor */
1508fe5e51b7Smrg    pScrn->monitor = pScrn->confScreen->monitor;
1509fe5e51b7Smrg
1510fe5e51b7Smrg    /*
1511fe5e51b7Smrg     * Set the Chipset and ChipRev, allowing config file entries to
1512fe5e51b7Smrg     * override.
1513fe5e51b7Smrg     */
1514fe5e51b7Smrg    if (pMga->device->chipset && *pMga->device->chipset) {
1515fe5e51b7Smrg	pScrn->chipset = pMga->device->chipset;
1516fe5e51b7Smrg        pMga->Chipset = xf86StringToToken(MGAChipsets, pScrn->chipset);
1517fe5e51b7Smrg        from = X_CONFIG;
1518fe5e51b7Smrg    } else if (pMga->device->chipID >= 0) {
1519fe5e51b7Smrg	pMga->Chipset = pMga->device->chipID;
1520fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1521fe5e51b7Smrg	from = X_CONFIG;
1522fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
1523fe5e51b7Smrg		   pMga->Chipset);
1524fe5e51b7Smrg    } else {
1525fe5e51b7Smrg	from = X_PROBED;
1526fe5e51b7Smrg	pMga->Chipset = DEVICE_ID(pMga->PciInfo);
1527fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1528fe5e51b7Smrg    }
1529fe5e51b7Smrg
1530fe5e51b7Smrg    if (pMga->device->chipRev >= 0) {
1531fe5e51b7Smrg	pMga->ChipRev = pMga->device->chipRev;
1532fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
1533fe5e51b7Smrg		   pMga->ChipRev);
1534fe5e51b7Smrg    } else {
1535fe5e51b7Smrg	pMga->ChipRev = CHIP_REVISION(pMga->PciInfo);
1536fe5e51b7Smrg    }
1537fe5e51b7Smrg
1538fe5e51b7Smrg    /*
1539fe5e51b7Smrg     * This shouldn't happen because such problems should be caught in
1540fe5e51b7Smrg     * MGAProbe(), but check it just in case.
1541fe5e51b7Smrg     */
1542fe5e51b7Smrg    if (pScrn->chipset == NULL) {
1543fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1544fe5e51b7Smrg		   "ChipID 0x%04X is not recognised\n", pMga->Chipset);
1545fe5e51b7Smrg	return FALSE;
1546fe5e51b7Smrg    }
1547fe5e51b7Smrg    if (pMga->Chipset < 0) {
1548fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1549fe5e51b7Smrg		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
1550fe5e51b7Smrg	return FALSE;
1551fe5e51b7Smrg    }
1552fe5e51b7Smrg
1553fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"", pScrn->chipset);
1554fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG400) {
1555fe5e51b7Smrg	if (pMga->ChipRev >= 0x80)
1556fe5e51b7Smrg	    xf86ErrorF(" (G450)\n");
1557fe5e51b7Smrg	else
1558fe5e51b7Smrg	    xf86ErrorF(" (G400)\n");
1559fe5e51b7Smrg    } else {
1560fe5e51b7Smrg	xf86ErrorF("\n");
1561fe5e51b7Smrg    }
1562fe5e51b7Smrg
1563fe5e51b7Smrg    pMga->is_Gx50 = ((pMga->Chipset == PCI_CHIP_MGAG400) && (pMga->ChipRev >= 0x80))
1564fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG550);
1565fe5e51b7Smrg    pMga->is_G200SE = (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI)
1566fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG200_SE_B_PCI);
1567eda3803bSmrg    pMga->is_G200EV = (pMga->Chipset == PCI_CHIP_MGAG200_EV_PCI);
15686f68ce78Smrg    pMga->is_G200WB = (pMga->Chipset == PCI_CHIP_MGAG200_WINBOND_PCI)
15696f68ce78Smrg	|| (pMga->Chipset ==  PCI_CHIP_MGAG200_EW3_PCI);
1570a31a186aSmrg    pMga->is_G200EH = (pMga->Chipset == PCI_CHIP_MGAG200_EH_PCI);
15710bb88ba4Smrg    pMga->is_G200ER = (pMga->Chipset == PCI_CHIP_MGAG200_ER_PCI);
1572fe5e51b7Smrg
1573fe5e51b7Smrg    pMga->DualHeadEnabled = FALSE;
1574fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {/* dual-head mode requested*/
1575fe5e51b7Smrg	if (
1576fe5e51b7Smrg	    !MGA_DH_NEEDS_HAL(pMga)) {
1577fe5e51b7Smrg	    pMga->DualHeadEnabled = TRUE;
1578fe5e51b7Smrg	} else if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1579fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1580fe5e51b7Smrg	 "This card requires the \"mga_hal\" module for dual-head operation\n"
1581fe5e51b7Smrg	 "\tIt can be found at the Matrox web site <http://www.matrox.com>\n");
1582fe5e51b7Smrg	}
1583fe5e51b7Smrg    }
1584fe5e51b7Smrg
1585acd6767fSmrg    /*
1586acd6767fSmrg     * Disable HW cursor by default on G200 server chips as these
1587acd6767fSmrg     * chips are often used with a remote graphics link which cannot
1588acd6767fSmrg     * display the HW cursor.
1589acd6767fSmrg     */
1590acd6767fSmrg    switch (pMga->Chipset) {
1591acd6767fSmrg    case PCI_CHIP_MGAG200_SE_A_PCI:
1592acd6767fSmrg    case PCI_CHIP_MGAG200_SE_B_PCI:
1593acd6767fSmrg    case PCI_CHIP_MGAG200_EV_PCI:
1594acd6767fSmrg    case PCI_CHIP_MGAG200_ER_PCI:
1595acd6767fSmrg    case PCI_CHIP_MGAG200_WINBOND_PCI:
1596acd6767fSmrg    case PCI_CHIP_MGAG200_EH_PCI:
1597acd6767fSmrg	pMga->HWCursor = FALSE;
1598acd6767fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1599acd6767fSmrg		   "HW cursor is not supported with video redirection on"
1600acd6767fSmrg		   "G200 server chips.\n If you don't intend to use video "
1601acd6767fSmrg		   "redirection enable with Option \"HWCursor\" \"On\"\n");
1602acd6767fSmrg	break;
1603acd6767fSmrg    default:
1604acd6767fSmrg	pMga->HWCursor = TRUE;
1605acd6767fSmrg    }
1606acd6767fSmrg    from = X_DEFAULT;
1607acd6767fSmrg
1608acd6767fSmrg    /*
1609acd6767fSmrg     * The preferred method is to use the "hw cursor" option as a tri-state
1610acd6767fSmrg     * option, with the default set above.
1611acd6767fSmrg     */
1612acd6767fSmrg    if (xf86GetOptValBool(pMga->Options, OPTION_HW_CURSOR, &pMga->HWCursor))
1613acd6767fSmrg	from = X_CONFIG;
1614acd6767fSmrg
1615acd6767fSmrg    /* For compatibility, accept this too (as an override) */
1616acd6767fSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SW_CURSOR, FALSE)) {
1617acd6767fSmrg	from = X_CONFIG;
1618acd6767fSmrg	pMga->HWCursor = FALSE;
1619acd6767fSmrg    }
1620acd6767fSmrg
1621acd6767fSmrg    pMga->SecondCrtc = FALSE;
1622fe5e51b7Smrg    /*
1623fe5e51b7Smrg     * In case of DualHead, we need to determine if we are the 'master' head
1624fe5e51b7Smrg     * or the 'slave' head. In order to do that, at the end of the first
1625fe5e51b7Smrg     * initialisation, PrimInit is set as DONE to the shared entity. So that
1626fe5e51b7Smrg     * the second initialisation knows that something has been done before it.
1627fe5e51b7Smrg     * This always assume that the first device initialised is the master
1628fe5e51b7Smrg     * head, and the second the slave.
1629fe5e51b7Smrg     *
1630fe5e51b7Smrg     */
1631fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {      /* dual-head mode */
1632fe5e51b7Smrg        if (!xf86IsPrimInitDone(pScrn->entityList[0])) { /* Is it the first initialisation? */
1633fe5e51b7Smrg            /* First CRTC  */
1634fe5e51b7Smrg            pMgaEnt->pScrn_1 = pScrn;
1635fe5e51b7Smrg        } else if (pMga->DualHeadEnabled) {
1636fe5e51b7Smrg            /* Second CRTC */
1637fe5e51b7Smrg            pMga->SecondCrtc = TRUE;
1638fe5e51b7Smrg            pMga->HWCursor = FALSE;
1639acd6767fSmrg	    from = X_DEFAULT;
1640fe5e51b7Smrg            pMgaEnt->pScrn_2 = pScrn;
1641fe5e51b7Smrg            pScrn->AdjustFrame = MGAAdjustFrameCrtc2;
1642fe5e51b7Smrg	    /*
1643fe5e51b7Smrg	     * Fail initialization of second head if we are in MergeFB mode,
1644fe5e51b7Smrg	     * since we do it ourselfs.
1645fe5e51b7Smrg             */
1646fe5e51b7Smrg            if(pMgaEnt->pScrn_1 && MGAPTR(pMgaEnt->pScrn_1)->MergedFB) {
1647fe5e51b7Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1648fe5e51b7Smrg			   "Primary head in Merged framebuffer mode. \n"
1649fe5e51b7Smrg			   "Don't let Xfree try to manage the second head.\n"
1650fe5e51b7Smrg			   "Remove the second screen in the \"ServerLayout\"\n"
1651fe5e51b7Smrg			   "Section of the config file.");
1652fe5e51b7Smrg		return FALSE;
1653fe5e51b7Smrg	    }
1654fe5e51b7Smrg        } else {
1655fe5e51b7Smrg	    return FALSE;
1656fe5e51b7Smrg	}
1657fe5e51b7Smrg    }
1658acd6767fSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1659acd6767fSmrg	       pMga->HWCursor ? "HW" : "SW");
1660acd6767fSmrg
1661fe5e51b7Smrg
1662fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
16630bb88ba4Smrg#ifdef MGADRI
1664fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescenceShared;
1665fe5e51b7Smrg#endif
1666fe5e51b7Smrg    } else {                                              /* single-head mode */
16670bb88ba4Smrg#ifdef MGADRI
1668fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescence;
1669fe5e51b7Smrg#endif
1670fe5e51b7Smrg    }
1671fe5e51b7Smrg
16720bb88ba4Smrg    if (!(pMga->Options = malloc(sizeof(MGAOptions))))
1673eda3803bSmrg	return FALSE;
1674eda3803bSmrg    memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions));
1675eda3803bSmrg
1676eda3803bSmrg    /* ajv changes to reflect actual values. see sdk pp 3-2. */
1677eda3803bSmrg    /* these masks just get rid of the crap in the lower bits */
1678eda3803bSmrg
1679eda3803bSmrg    /* For the 2064 and older rev 1064, base0 is the MMIO and base1 is
1680eda3803bSmrg     * the framebuffer.
1681eda3803bSmrg     */
1682eda3803bSmrg
1683eda3803bSmrg    switch (pMga->chip_attribs->BARs) {
1684eda3803bSmrg    case old_BARs:
1685eda3803bSmrg	pMga->framebuffer_bar = 1;
1686eda3803bSmrg	pMga->io_bar = 0;
1687eda3803bSmrg	pMga->iload_bar = -1;
1688eda3803bSmrg	break;
1689eda3803bSmrg    case probe_BARs:
1690eda3803bSmrg	if (pMga->ChipRev < 3) {
1691eda3803bSmrg	    pMga->framebuffer_bar = 1;
1692eda3803bSmrg	    pMga->io_bar = 0;
1693eda3803bSmrg	    pMga->iload_bar = 2;
1694eda3803bSmrg	    break;
1695eda3803bSmrg	}
1696eda3803bSmrg	/* FALLTHROUGH */
1697eda3803bSmrg    case new_BARs:
1698eda3803bSmrg	pMga->framebuffer_bar = 0;
1699eda3803bSmrg	pMga->io_bar = 1;
1700eda3803bSmrg	pMga->iload_bar = 2;
1701eda3803bSmrg	break;
1702eda3803bSmrg    }
1703eda3803bSmrg
1704eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1705eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->regions[pMga->framebuffer_bar].base_addr;
1706eda3803bSmrg#else
1707eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->memBase[pMga->framebuffer_bar] & 0xff800000;
1708eda3803bSmrg#endif
1709eda3803bSmrg
1710eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n",
1711eda3803bSmrg	       (unsigned long)pMga->FbAddress);
1712eda3803bSmrg
1713eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1714eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lX\n",
1715eda3803bSmrg	       (unsigned long) pMga->PciInfo->regions[pMga->io_bar].base_addr);
1716eda3803bSmrg#else
1717eda3803bSmrg    pMga->IOAddress = pMga->PciInfo->memBase[pMga->io_bar] & 0xffffc000;
1718eda3803bSmrg
1719eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
1720eda3803bSmrg	       (unsigned long)pMga->IOAddress);
1721eda3803bSmrg#endif
1722eda3803bSmrg
1723eda3803bSmrg    if (pMga->iload_bar != -1) {
1724eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1725eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1726eda3803bSmrg		   "Pseudo-DMA transfer window at 0x%lX\n",
1727eda3803bSmrg		   (unsigned long) pMga->PciInfo->regions[pMga->iload_bar].base_addr);
1728eda3803bSmrg#else
1729eda3803bSmrg	if (pMga->PciInfo->memBase[2] != 0) {
1730eda3803bSmrg	    pMga->ILOADAddress = pMga->PciInfo->memBase[2] & 0xffffc000;
1731eda3803bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1732eda3803bSmrg		       "Pseudo-DMA transfer window at 0x%lX\n",
1733eda3803bSmrg		       (unsigned long)pMga->ILOADAddress);
1734eda3803bSmrg	}
1735eda3803bSmrg#endif
1736eda3803bSmrg    }
1737eda3803bSmrg
1738eda3803bSmrg#ifndef XSERVER_LIBPCIACCESS
1739eda3803bSmrg    /*
1740eda3803bSmrg     * Find the BIOS base.  Get it from the PCI config if possible.  Otherwise
17410bb88ba4Smrg     * use the VGA default.
1742eda3803bSmrg     */
1743eda3803bSmrg
1744eda3803bSmrg	/* details: rombase sdk pp 4-15 */
1745eda3803bSmrg	if (pMga->PciInfo->biosBase != 0) {
1746eda3803bSmrg	    pMga->BiosAddress = pMga->PciInfo->biosBase & 0xffff0000;
1747eda3803bSmrg	    pMga->BiosFrom = X_PROBED;
1748eda3803bSmrg	} else if (pMga->Primary) {
1749eda3803bSmrg	    pMga->BiosAddress = 0xc0000;
1750eda3803bSmrg	    pMga->BiosFrom = X_DEFAULT;
1751eda3803bSmrg	}
1752eda3803bSmrg    if (pMga->BiosAddress) {
1753eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom, "BIOS at 0x%lX\n",
1754eda3803bSmrg		   (unsigned long)pMga->BiosAddress);
1755eda3803bSmrg    }
1756eda3803bSmrg#endif
1757eda3803bSmrg
1758643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1759eda3803bSmrg    if (xf86RegisterResources(pMga->pEnt->index, NULL, ResExclusive)) {
1760eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1761eda3803bSmrg		"xf86RegisterResources() found resource conflicts\n");
1762eda3803bSmrg	MGAFreeRec(pScrn);
1763eda3803bSmrg	return FALSE;
1764eda3803bSmrg    }
1765643b027fSmrg#endif
1766eda3803bSmrg
1767fe5e51b7Smrg    /*
1768fe5e51b7Smrg     * The first thing we should figure out is the depth, bpp, etc.
1769fe5e51b7Smrg     * Our default depth is 8, so pass it to the helper function.
1770fe5e51b7Smrg     * We support both 24bpp and 32bpp layouts, so indicate that.
1771fe5e51b7Smrg     */
1772fe5e51b7Smrg
1773eda3803bSmrg    /* Prefer 32bpp */
1774eda3803bSmrg    flags24 = Support24bppFb | Support32bppFb | PreferConvert24to32;
1775fe5e51b7Smrg
1776fe5e51b7Smrg    if (pMga->SecondCrtc)
1777fe5e51b7Smrg	flags24 = Support32bppFb;
1778fe5e51b7Smrg
1779eda3803bSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_FBDEV, FALSE)) {
1780eda3803bSmrg	pMga->FBDev = TRUE;
1781eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1782eda3803bSmrg		"Using framebuffer device\n");
1783eda3803bSmrg	/* check for linux framebuffer device */
1784eda3803bSmrg	if (!xf86LoadSubModule(pScrn, "fbdevhw"))
1785eda3803bSmrg	    return FALSE;
1786eda3803bSmrg	if (!fbdevHWInit(pScrn, pMga->PciInfo, NULL))
1787eda3803bSmrg	    return FALSE;
1788eda3803bSmrg    }
1789eda3803bSmrg
1790eda3803bSmrg    /*
1791eda3803bSmrg     * If the user has specified the amount of memory in the XF86Config
1792eda3803bSmrg     * file, we respect that setting.
1793eda3803bSmrg     */
1794eda3803bSmrg    from = X_PROBED;
1795eda3803bSmrg    if (pMga->device->videoRam != 0) {
1796eda3803bSmrg	pScrn->videoRam = pMga->device->videoRam;
1797eda3803bSmrg	from = X_CONFIG;
1798eda3803bSmrg    } else if (pMga->FBDev) {
1799eda3803bSmrg	pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024;
1800eda3803bSmrg    } else {
1801eda3803bSmrg	pScrn->videoRam = MGACountRam(pScrn);
1802eda3803bSmrg    }
1803eda3803bSmrg
1804eda3803bSmrg    if (pMga->is_G200SE && pScrn->videoRam < 2048)
1805fe5e51b7Smrg	pScrn->confScreen->defaultdepth = 16;
1806fe5e51b7Smrg
1807fe5e51b7Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
1808fe5e51b7Smrg	return FALSE;
1809fe5e51b7Smrg    } else {
1810fe5e51b7Smrg	/* Check that the returned depth is one we support */
1811fe5e51b7Smrg	switch (pScrn->depth) {
1812fe5e51b7Smrg	case 8:
1813fe5e51b7Smrg	case 16:
1814fe5e51b7Smrg	case 24:
1815fe5e51b7Smrg	    /* OK */
1816fe5e51b7Smrg	    break;
1817eda3803bSmrg	case 15:
1818eda3803bSmrg	    if (pMga->Chipset != PCI_CHIP_MGAG200_SE_A_PCI)
1819eda3803bSmrg		break;
1820fe5e51b7Smrg	default:
1821fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1822fe5e51b7Smrg		       "Given depth (%d) is not supported by this driver\n",
1823fe5e51b7Smrg		       pScrn->depth);
1824fe5e51b7Smrg	    return FALSE;
1825fe5e51b7Smrg	}
1826fe5e51b7Smrg    }
1827fe5e51b7Smrg    xf86PrintDepthBpp(pScrn);
1828fe5e51b7Smrg
1829fe5e51b7Smrg    /*
1830fe5e51b7Smrg     * This must happen after pScrn->display has been set because
1831fe5e51b7Smrg     * xf86SetWeight references it.
1832fe5e51b7Smrg     */
1833fe5e51b7Smrg    if (pScrn->depth > 8) {
1834fe5e51b7Smrg	/* The defaults are OK for us */
1835fe5e51b7Smrg	rgb zeros = {0, 0, 0};
1836fe5e51b7Smrg
1837fe5e51b7Smrg	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1838fe5e51b7Smrg	    return FALSE;
1839fe5e51b7Smrg	} else {
1840fe5e51b7Smrg	    /* XXX check that weight returned is supported */
1841fe5e51b7Smrg            ;
1842fe5e51b7Smrg        }
1843fe5e51b7Smrg    }
1844fe5e51b7Smrg
1845fe5e51b7Smrg    bytesPerPixel = pScrn->bitsPerPixel / 8;
1846fe5e51b7Smrg
1847fe5e51b7Smrg    /* We use a programmable clock */
1848fe5e51b7Smrg    pScrn->progClock = TRUE;
1849fe5e51b7Smrg
1850fe5e51b7Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
1851fe5e51b7Smrg    xf86CollectOptions(pScrn, NULL);
1852fe5e51b7Smrg
1853fe5e51b7Smrg    /* Process the options */
1854fe5e51b7Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options);
1855fe5e51b7Smrg
1856fe5e51b7Smrg    if (pMga->is_G200SE) {
1857fe5e51b7Smrg        /* Disable MTRR support on PCIe systems */
1858fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1859fe5e51b7Smrg	uint32_t temp;
1860fe5e51b7Smrg
1861fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & temp, 0xDC);
1862fe5e51b7Smrg#else
1863fe5e51b7Smrg        CARD32 temp = pciReadLong(pMga->PciTag, 0xDC);
1864fe5e51b7Smrg#endif
1865fe5e51b7Smrg
1866fe5e51b7Smrg        if ((temp & 0x0000FF00) != 0x0) {
1867fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling MTRR support.\n");
1868fe5e51b7Smrg            pScrn->options = xf86ReplaceBoolOption(pScrn->options, "MTRR", FALSE);
1869fe5e51b7Smrg        }
1870fe5e51b7Smrg    }
1871eda3803bSmrg
1872eda3803bSmrg    if (pMga->is_G200WB && xf86ReturnOptValBool(pMga->Options, OPTION_KVM, TRUE)) {
1873eda3803bSmrg        pMga->KVM = TRUE;
1874eda3803bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling KVM\n");
1875eda3803bSmrg    }
1876fe5e51b7Smrg
1877fe5e51b7Smrg#if !defined(__powerpc__)
1878fe5e51b7Smrg    pMga->softbooted = FALSE;
1879fe5e51b7Smrg    Default = (pMga->chip_attribs->dual_head_possible
1880fe5e51b7Smrg	       && !pMga->Primary && !pMga->SecondCrtc);
1881fe5e51b7Smrg
1882fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_INT10, Default) &&
1883fe5e51b7Smrg        xf86LoadSubModule(pScrn, "int10")) {
1884fe5e51b7Smrg        xf86Int10InfoPtr pInt;
1885fe5e51b7Smrg
1886fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
1887fe5e51b7Smrg        pInt = xf86InitInt10(pMga->pEnt->index);
1888fe5e51b7Smrg	if (pInt) pMga->softbooted = TRUE;
1889fe5e51b7Smrg        xf86FreeInt10(pInt);
1890fe5e51b7Smrg    }
1891fe5e51b7Smrg#endif
1892fe5e51b7Smrg
1893fe5e51b7Smrg    /* Set the bits per RGB for 8bpp mode */
1894fe5e51b7Smrg    if (pScrn->depth == 8)
1895fe5e51b7Smrg	pScrn->rgbBits = 8;
1896fe5e51b7Smrg
18970bb88ba4Smrg#ifdef MGADRI
1898fe5e51b7Smrg    from = X_DEFAULT;
1899fe5e51b7Smrg    pMga->agpMode = MGA_DEFAULT_AGP_MODE;
1900fe5e51b7Smrg
1901fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1902fe5e51b7Smrg			     OPTION_AGP_MODE, &(pMga->agpMode))) {
1903fe5e51b7Smrg       if (pMga->agpMode < 1) {
1904fe5e51b7Smrg	  pMga->agpMode = 1;
1905fe5e51b7Smrg       }
1906fe5e51b7Smrg       if (pMga->agpMode > MGA_MAX_AGP_MODE) {
1907fe5e51b7Smrg	  pMga->agpMode = MGA_MAX_AGP_MODE;
1908fe5e51b7Smrg       }
1909fe5e51b7Smrg       from = X_CONFIG;
1910fe5e51b7Smrg    }
1911fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1912fe5e51b7Smrg                             OPTION_AGP_SIZE, &(pMga->agpSize))) {
1913fe5e51b7Smrg                             /* check later */
1914fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, from, "Using %d MB of AGP memory\n",
1915fe5e51b7Smrg	          pMga->agpSize);
1916fe5e51b7Smrg    }
1917fe5e51b7Smrg
1918fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n",
1919fe5e51b7Smrg	       pMga->agpMode);
1920fe5e51b7Smrg
1921fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OLDDMA, FALSE)) {
1922fe5e51b7Smrg	pMga->useOldDmaInit = TRUE;
1923fe5e51b7Smrg    }
1924fe5e51b7Smrg
1925fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCIDMA, FALSE)) {
1926fe5e51b7Smrg	pMga->forcePciDma = TRUE;
1927fe5e51b7Smrg    }
1928fe5e51b7Smrg#endif
1929fe5e51b7Smrg
1930fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) {
1931fe5e51b7Smrg	pMga->NoAccel = TRUE;
1932fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1933fe5e51b7Smrg    } else {
1934fe5e51b7Smrg	int from = X_DEFAULT;
1935fe5e51b7Smrg#ifdef USE_EXA
1936fe5e51b7Smrg	char *s = xf86GetOptValString(pMga->Options, OPTION_ACCELMETHOD);
1937fe5e51b7Smrg#endif
1938fe5e51b7Smrg	pMga->NoAccel = FALSE;
1939fe5e51b7Smrg	pMga->Exa = FALSE;
1940fe5e51b7Smrg#ifdef USE_EXA
1941fe5e51b7Smrg	if (!xf86NameCmp(s, "EXA")) {
1942fe5e51b7Smrg	    pMga->Exa = TRUE;
1943fe5e51b7Smrg	    from = X_CONFIG;
1944fe5e51b7Smrg	}
1945fe5e51b7Smrg#endif
1946fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
1947fe5e51b7Smrg		   pMga->Exa ? "EXA" : "XAA");
1948fe5e51b7Smrg    }
1949fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) {
1950fe5e51b7Smrg	pMga->UsePCIRetry = TRUE;
1951fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
1952fe5e51b7Smrg    }
1953fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
1954fe5e51b7Smrg	pMga->SyncOnGreen = TRUE;
1955fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
1956fe5e51b7Smrg    }
1957fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHOWCACHE, FALSE)) {
1958fe5e51b7Smrg	pMga->ShowCache = TRUE;
1959fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
1960fe5e51b7Smrg    }
1961fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MGA_SDRAM, FALSE)) {
1962fe5e51b7Smrg	pMga->HasSDRAM = TRUE;
1963fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Has SDRAM\n");
1964fe5e51b7Smrg    }
1965fe5e51b7Smrg    if (xf86GetOptValFreq(pMga->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
1966fe5e51b7Smrg	pMga->MemClk = (int)(real * 1000.0);
1967fe5e51b7Smrg    }
1968fe5e51b7Smrg
1969fe5e51b7Smrg    if(xf86GetOptValInteger(pMga->Options, OPTION_VIDEO_KEY, &(pMga->videoKey))) {
1970fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1971fe5e51b7Smrg				pMga->videoKey);
1972fe5e51b7Smrg    } else {
1973fe5e51b7Smrg	pMga->videoKey =  (1 << pScrn->offset.red) |
1974fe5e51b7Smrg			  (1 << pScrn->offset.green) |
1975fe5e51b7Smrg        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
1976fe5e51b7Smrg    }
1977fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHADOW_FB, FALSE)) {
1978fe5e51b7Smrg	pMga->ShadowFB = TRUE;
1979fe5e51b7Smrg	pMga->NoAccel = TRUE;
1980fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1981fe5e51b7Smrg		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
1982fe5e51b7Smrg    }
1983fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OVERCLOCK_MEM, FALSE)) {
1984fe5e51b7Smrg	pMga->OverclockMem = TRUE;
1985fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overclocking memory\n");
1986fe5e51b7Smrg    }
1987fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_TEXTURED_VIDEO, FALSE)) {
1988fe5e51b7Smrg	pMga->TexturedVideo = TRUE;
1989fe5e51b7Smrg    }
1990fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MERGEDFB, FALSE)) {
1991fe5e51b7Smrg        if(!MGAISGx50(pMga)) {
1992fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1993fe5e51b7Smrg                "\"Merged Framebuffer\" mode only supported on G450 and G550 boards.\n");
1994fe5e51b7Smrg        } else {
1995fe5e51b7Smrg            {
1996fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1997fe5e51b7Smrg                    "HALLib not loaded! NOT using \"Merged Framebuffer\" mode.\n");
1998fe5e51b7Smrg            } /* MGA_NOT_HAL */
1999fe5e51b7Smrg        } /* ISMGAGx50() */
2000fe5e51b7Smrg    }
2001fe5e51b7Smrg    if (pMga->FBDev) {
2002fe5e51b7Smrg	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
2003fe5e51b7Smrg	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
2004fe5e51b7Smrg	pScrn->EnterVT       = MGAEnterVTFBDev;
2005fe5e51b7Smrg	pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
2006fe5e51b7Smrg	pScrn->ValidMode     = fbdevHWValidModeWeak();
2007fe5e51b7Smrg    }
2008fe5e51b7Smrg    pMga->Rotate = 0;
2009fe5e51b7Smrg    if ((s = xf86GetOptValString(pMga->Options, OPTION_ROTATE))) {
2010fe5e51b7Smrg        if(!pMga->MergedFB) {
2011fe5e51b7Smrg            if(!xf86NameCmp(s, "CW")) {
2012fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2013fe5e51b7Smrg                pMga->NoAccel = TRUE;
2014fe5e51b7Smrg                pMga->HWCursor = FALSE;
2015fe5e51b7Smrg                pMga->Rotate = 1;
2016fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2017fe5e51b7Smrg                        "Rotating screen clockwise - acceleration disabled\n");
2018fe5e51b7Smrg            } else
2019fe5e51b7Smrg            if(!xf86NameCmp(s, "CCW")) {
2020fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2021fe5e51b7Smrg                pMga->NoAccel = TRUE;
2022fe5e51b7Smrg                pMga->HWCursor = FALSE;
2023fe5e51b7Smrg                pMga->Rotate = -1;
2024fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2025fe5e51b7Smrg                        "Rotating screen counter clockwise - acceleration disabled\n");
2026fe5e51b7Smrg            } else {
2027fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2028fe5e51b7Smrg                        "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
2029fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2030fe5e51b7Smrg                        "Valid options are \"CW\" or \"CCW\"\n");
2031fe5e51b7Smrg            }
2032fe5e51b7Smrg        } else {
2033fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2034fe5e51b7Smrg                " -- Rotation disabled.\n");
2035fe5e51b7Smrg        }
2036fe5e51b7Smrg    }
2037fe5e51b7Smrg
20380bb88ba4Smrg    /* Load XAA if needed */
20390bb88ba4Smrg    if (!pMga->NoAccel) {
20400bb88ba4Smrg#ifdef USE_EXA
20410bb88ba4Smrg	if (pMga->Exa) {
20420bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "exa")) {
20430bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
20440bb88ba4Smrg		           "Falling back to shadowfb\n");
20450bb88ba4Smrg		pMga->ShadowFB = TRUE;
20460bb88ba4Smrg		pMga->NoAccel = TRUE;
20470bb88ba4Smrg	    }
20480bb88ba4Smrg	} else {
20490bb88ba4Smrg#endif
2050acd6767fSmrg#ifdef USE_XAA
20510bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
20520bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
20530bb88ba4Smrg		           "Falling back to shadowfb\n");
20540bb88ba4Smrg		pMga->ShadowFB = TRUE;
20550bb88ba4Smrg		pMga->NoAccel = TRUE;
20560bb88ba4Smrg	    }
20570bb88ba4Smrg#endif
20580bb88ba4Smrg#ifdef USE_EXA
20590bb88ba4Smrg	}
20600bb88ba4Smrg#endif
20610bb88ba4Smrg    }
20620bb88ba4Smrg
2063fe5e51b7Smrg    switch (pMga->Chipset) {
2064fe5e51b7Smrg    case PCI_CHIP_MGA2064:
2065fe5e51b7Smrg    case PCI_CHIP_MGA2164:
2066fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
2067fe5e51b7Smrg	MGA2064SetupFuncs(pScrn);
2068fe5e51b7Smrg	break;
2069fe5e51b7Smrg    case PCI_CHIP_MGA1064:
2070fe5e51b7Smrg    case PCI_CHIP_MGAG100:
2071fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
2072fe5e51b7Smrg    case PCI_CHIP_MGAG200:
2073fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
2074fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_A_PCI:
2075fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_B_PCI:
2076eda3803bSmrg    case PCI_CHIP_MGAG200_WINBOND_PCI:
20776f68ce78Smrg    case PCI_CHIP_MGAG200_EW3_PCI:
2078eda3803bSmrg    case PCI_CHIP_MGAG200_EV_PCI:
2079a31a186aSmrg    case PCI_CHIP_MGAG200_EH_PCI:
20800bb88ba4Smrg    case PCI_CHIP_MGAG200_ER_PCI:
2081fe5e51b7Smrg    case PCI_CHIP_MGAG400:
2082fe5e51b7Smrg    case PCI_CHIP_MGAG550:
2083fe5e51b7Smrg	MGAGSetupFuncs(pScrn);
2084fe5e51b7Smrg	break;
2085fe5e51b7Smrg    }
2086fe5e51b7Smrg
2087fe5e51b7Smrg    /*
2088fe5e51b7Smrg     * Read the BIOS data struct
2089fe5e51b7Smrg     */
2090fe5e51b7Smrg
2091fe5e51b7Smrg#if defined(__alpha__) && !defined(XSERVER_LIBPCIACCESS)
2092fe5e51b7Smrg    /*
2093fe5e51b7Smrg     * Some old Digital-OEMed Matrox Millennium I cards have a VGA
2094fe5e51b7Smrg     * disable switch.  If the disable is on, we can't read the BIOS,
2095fe5e51b7Smrg     * and pMga->BiosAddress = 0x0. The disable switch is needed to
2096fe5e51b7Smrg     * allow multi-head operation with brain-dead console code... ;-}
2097fe5e51b7Smrg     */
2098fe5e51b7Smrg
2099fe5e51b7Smrg    if ((pMga->BiosAddress == 0) && !xf86IsPrimaryPci(pMga->PciInfo))
2100fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom,
2101fe5e51b7Smrg                   "BIOS not found, skipping read\n");
2102fe5e51b7Smrg    else
2103fe5e51b7Smrg#endif
2104fe5e51b7Smrg    mga_read_and_process_bios( pScrn );
2105fe5e51b7Smrg
2106fe5e51b7Smrg
2107fe5e51b7Smrg    /* Since the BIOS can swap DACs during the initialisation of G550, we need to
2108fe5e51b7Smrg     * store which DAC this instance of the driver is taking care of. This is done
2109fe5e51b7Smrg     * by checking a flag stored in the ROM by the BIOS at a fixed address. */
2110fe5e51b7Smrg
2111fe5e51b7Smrg    if (!pMga->SecondCrtc)
2112fe5e51b7Smrg        pMga->SecondOutput = FALSE;
2113fe5e51b7Smrg    else
2114fe5e51b7Smrg        pMga->SecondOutput = TRUE;
2115fe5e51b7Smrg
2116fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG550) {
2117fe5e51b7Smrg        if (!pMga->SecondCrtc) {
2118fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? TRUE : FALSE;
2119fe5e51b7Smrg        } else {
2120fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? FALSE : TRUE;
2121fe5e51b7Smrg        }
2122fe5e51b7Smrg    }
2123fe5e51b7Smrg
2124fe5e51b7Smrg
2125fe5e51b7Smrg    /* HW bpp matches reported bpp */
2126fe5e51b7Smrg    pMga->HwBpp = pScrn->bitsPerPixel;
2127fe5e51b7Smrg
2128fe5e51b7Smrg    /*
2129fe5e51b7Smrg     * Reset card if it isn't primary one
2130fe5e51b7Smrg     */
21310bb88ba4Smrg    if ( (!pMga->Primary && !pMga->FBDev) )
2132fe5e51b7Smrg        MGASoftReset(pScrn);
2133fe5e51b7Smrg
2134fe5e51b7Smrg    if (pScrn->videoRam == 0) {
2135fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2136fe5e51b7Smrg		   "Unable to detect video RAM.\n");
2137fe5e51b7Smrg	return FALSE;
2138fe5e51b7Smrg    }
2139fe5e51b7Smrg
2140fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
2141fe5e51b7Smrg       /* This takes gives either half or 8 meg to the second head
2142fe5e51b7Smrg	* whichever is less. */
2143fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2144fe5e51b7Smrg	    Bool UseHalf = FALSE;
2145fe5e51b7Smrg	    int adjust;
2146fe5e51b7Smrg
2147fe5e51b7Smrg	    xf86GetOptValBool(pMga->Options, OPTION_CRTC2HALF, &UseHalf);
2148fe5e51b7Smrg	    adjust = pScrn->videoRam / 2;
2149fe5e51b7Smrg
2150fe5e51b7Smrg	    if (UseHalf == TRUE ||
2151fe5e51b7Smrg		  xf86GetOptValInteger(pMga->Options, OPTION_CRTC2RAM, &adjust)) {
2152fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2153fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2154fe5e51b7Smrg			   adjust);
2155fe5e51b7Smrg	    } else {
2156fe5e51b7Smrg	        adjust = min(adjust, 8192);
2157fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2158fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2159fe5e51b7Smrg			   adjust);
2160fe5e51b7Smrg	    }
2161fe5e51b7Smrg	    pMgaEnt->mastervideoRam = pScrn->videoRam - adjust;
2162fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->mastervideoRam;
2163fe5e51b7Smrg	    pMgaEnt->slavevideoRam = adjust;
2164fe5e51b7Smrg	    pMgaEnt->masterFbAddress = pMga->FbAddress;
2165fe5e51b7Smrg	    pMga->FbMapSize =
2166fe5e51b7Smrg	       pMgaEnt->masterFbMapSize = pScrn->videoRam * 1024;
2167fe5e51b7Smrg	    pMgaEnt->slaveFbAddress = pMga->FbAddress +
2168fe5e51b7Smrg	       pMgaEnt->masterFbMapSize;
2169fe5e51b7Smrg	    pMgaEnt->slaveFbMapSize = pMgaEnt->slavevideoRam * 1024;
2170fe5e51b7Smrg	    pMga->realSrcOrg = pMga->SrcOrg = 0;
2171fe5e51b7Smrg	    pMga->DstOrg = 0;
2172fe5e51b7Smrg	} else {
2173fe5e51b7Smrg	    pMga->FbAddress = pMgaEnt->slaveFbAddress;
2174fe5e51b7Smrg	    pMga->FbMapSize = pMgaEnt->slaveFbMapSize;
2175fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->slavevideoRam;
2176fe5e51b7Smrg	    pMga->DstOrg = pMga->realSrcOrg =
2177fe5e51b7Smrg	      pMgaEnt->slaveFbAddress - pMgaEnt->masterFbAddress;
2178fe5e51b7Smrg	    pMga->SrcOrg = 0; /* This is not stored in hw format!! */
2179fe5e51b7Smrg	}
2180fe5e51b7Smrg        pMgaEnt->refCount++;
2181fe5e51b7Smrg    } else {
2182fe5e51b7Smrg        /* Normal Handling of video ram etc */
2183fe5e51b7Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
2184fe5e51b7Smrg        switch(pMga->Chipset) {
2185fe5e51b7Smrg	  case PCI_CHIP_MGAG550:
2186fe5e51b7Smrg	  case PCI_CHIP_MGAG400:
2187fe5e51b7Smrg	  case PCI_CHIP_MGAG200:
2188fe5e51b7Smrg	  case PCI_CHIP_MGAG200_PCI:
2189fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_A_PCI:
2190fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_B_PCI:
2191eda3803bSmrg          case PCI_CHIP_MGAG200_WINBOND_PCI:
21926f68ce78Smrg	  case PCI_CHIP_MGAG200_EW3_PCI:
2193eda3803bSmrg	  case PCI_CHIP_MGAG200_EV_PCI:
21946f68ce78Smrg	  case PCI_CHIP_MGAG200_EH_PCI:
21950bb88ba4Smrg	  case PCI_CHIP_MGAG200_ER_PCI:
2196fe5e51b7Smrg	    pMga->SrcOrg = 0;
2197fe5e51b7Smrg	    pMga->DstOrg = 0;
2198fe5e51b7Smrg	    break;
2199fe5e51b7Smrg	  default:
2200fe5e51b7Smrg	    break;
2201fe5e51b7Smrg	}
2202fe5e51b7Smrg    }
2203fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
2204fe5e51b7Smrg               pScrn->videoRam);
2205fe5e51b7Smrg
2206fe5e51b7Smrg   /* Set the bpp shift value */
2207fe5e51b7Smrg    pMga->BppShifts[0] = 0;
2208fe5e51b7Smrg    pMga->BppShifts[1] = 1;
2209fe5e51b7Smrg    pMga->BppShifts[2] = 0;
2210fe5e51b7Smrg    pMga->BppShifts[3] = 2;
2211fe5e51b7Smrg
2212fe5e51b7Smrg    /*
2213fe5e51b7Smrg     * fill MGAdac struct
2214fe5e51b7Smrg     * Warning: currently, it should be after RAM counting
2215fe5e51b7Smrg     */
2216fe5e51b7Smrg    (*pMga->PreInit)(pScrn);
2217fe5e51b7Smrg
2218fe5e51b7Smrg#if !defined(__powerpc__)
2219fe5e51b7Smrg
2220fe5e51b7Smrg    /* Read and print the Monitor DDC info */
2221fe5e51b7Smrg    pScrn->monitor->DDC = MGAdoDDC(pScrn);
2222fe5e51b7Smrg#endif /* !__powerpc__ */
2223fe5e51b7Smrg
2224fe5e51b7Smrg    if (!pScrn->monitor->DDC && pMga->is_G200SE) {
2225fe5e51b7Smrg	/* Jam in ranges big enough for 1024x768 */
2226fe5e51b7Smrg	if (!pScrn->monitor->nHsync) {
2227fe5e51b7Smrg	    pScrn->monitor->nHsync = 1;
2228fe5e51b7Smrg	    pScrn->monitor->hsync[0].lo = 31.5;
2229fe5e51b7Smrg	    pScrn->monitor->hsync[0].hi = 48.0;
2230fe5e51b7Smrg	}
2231fe5e51b7Smrg	if (!pScrn->monitor->nVrefresh) {
2232fe5e51b7Smrg	    pScrn->monitor->nVrefresh = 1;
2233fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].lo = 56.0;
2234fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].hi = 75.0;
2235fe5e51b7Smrg	}
2236fe5e51b7Smrg    }
2237fe5e51b7Smrg
2238fe5e51b7Smrg
2239fe5e51b7Smrg    /*
2240fe5e51b7Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
2241fe5e51b7Smrg     * here.
2242fe5e51b7Smrg     */
2243fe5e51b7Smrg
2244fe5e51b7Smrg    {
2245fe5e51b7Smrg	Gamma zeros = {0.0, 0.0, 0.0};
2246fe5e51b7Smrg
2247fe5e51b7Smrg	if (!xf86SetGamma(pScrn, zeros)) {
2248fe5e51b7Smrg	    return FALSE;
2249fe5e51b7Smrg	}
2250fe5e51b7Smrg    }
2251fe5e51b7Smrg
2252fe5e51b7Smrg
2253fe5e51b7Smrg    /* XXX Set HW cursor use */
2254fe5e51b7Smrg
2255fe5e51b7Smrg    /* Set the min pixel clock */
2256fe5e51b7Smrg    pMga->MinClock = 17750;
2257eda3803bSmrg    if (pMga->is_G200WB){
2258eda3803bSmrg	pMga->MinClock = 18750;
2259eda3803bSmrg    }
2260fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
2261fe5e51b7Smrg	       pMga->MinClock / 1000);
2262fe5e51b7Smrg    /*
2263fe5e51b7Smrg     * If the user has specified ramdac speed in the XF86Config
2264fe5e51b7Smrg     * file, we respect that setting.
2265fe5e51b7Smrg     */
2266fe5e51b7Smrg    if (pMga->device->dacSpeeds[0]) {
2267fe5e51b7Smrg	int speed = 0;
2268fe5e51b7Smrg
2269fe5e51b7Smrg	switch (pScrn->bitsPerPixel) {
2270fe5e51b7Smrg	case 8:
2271fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP8];
2272fe5e51b7Smrg	   break;
2273fe5e51b7Smrg	case 16:
2274fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP16];
2275fe5e51b7Smrg	   break;
2276fe5e51b7Smrg	case 24:
2277fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP24];
2278fe5e51b7Smrg	   break;
2279fe5e51b7Smrg	case 32:
2280fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP32];
2281fe5e51b7Smrg	   break;
2282fe5e51b7Smrg	}
2283fe5e51b7Smrg	if (speed == 0)
2284fe5e51b7Smrg	    pMga->MaxClock = pMga->device->dacSpeeds[0];
2285fe5e51b7Smrg	else
2286fe5e51b7Smrg	    pMga->MaxClock = speed;
2287fe5e51b7Smrg	from = X_CONFIG;
2288fe5e51b7Smrg    } else {
2289fe5e51b7Smrg	pMga->MaxClock = pMga->Dac.maxPixelClock;
2290fe5e51b7Smrg	from = pMga->Dac.ClockFrom;
2291fe5e51b7Smrg    }
2292fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) {
2293fe5e51b7Smrg        /* Override on 2nd crtc */
2294fe5e51b7Smrg	if ((pMga->ChipRev >= 0x80) || (pMga->Chipset == PCI_CHIP_MGAG550)) {
2295fe5e51b7Smrg	    /* G450, G550 */
2296fe5e51b7Smrg	    pMga->MaxClock = 234000;
2297fe5e51b7Smrg	} else {
2298fe5e51b7Smrg	    pMga->MaxClock = 135000;
2299fe5e51b7Smrg	}
2300fe5e51b7Smrg    }
2301fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
2302fe5e51b7Smrg	       pMga->MaxClock / 1000);
2303fe5e51b7Smrg    /*
2304fe5e51b7Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
2305fe5e51b7Smrg     * and what sort of modes they can be used for.
2306fe5e51b7Smrg     */
2307fe5e51b7Smrg    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
2308fe5e51b7Smrg    clockRanges->next = NULL;
2309fe5e51b7Smrg    clockRanges->minClock = pMga->MinClock;
2310fe5e51b7Smrg    clockRanges->maxClock = pMga->MaxClock;
2311fe5e51b7Smrg    clockRanges->clockIndex = -1;		/* programmable */
2312fe5e51b7Smrg    clockRanges->interlaceAllowed = TRUE;
2313fe5e51b7Smrg    clockRanges->doubleScanAllowed = TRUE;
2314fe5e51b7Smrg    if (pMga->SecondCrtc == TRUE)
2315fe5e51b7Smrg	clockRanges->interlaceAllowed = FALSE;
2316fe5e51b7Smrg
2317fe5e51b7Smrg    clockRanges->ClockMulFactor = 1;
2318fe5e51b7Smrg    clockRanges->ClockDivFactor = 1;
2319fe5e51b7Smrg
2320fe5e51b7Smrg    /* Only set MemClk if appropriate for the ramdac */
2321fe5e51b7Smrg    if (pMga->Dac.SetMemClk) {
2322fe5e51b7Smrg	if (pMga->MemClk == 0) {
2323fe5e51b7Smrg	    pMga->MemClk = pMga->Dac.MemoryClock;
2324fe5e51b7Smrg	    from = pMga->Dac.MemClkFrom;
2325fe5e51b7Smrg	} else
2326fe5e51b7Smrg	    from = X_CONFIG;
2327fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "MCLK used is %.1f MHz\n",
2328fe5e51b7Smrg		   pMga->MemClk / 1000.0);
2329fe5e51b7Smrg    }
2330fe5e51b7Smrg
2331fe5e51b7Smrg    /*
2332fe5e51b7Smrg     * xf86ValidateModes will check that the mode HTotal and VTotal values
2333fe5e51b7Smrg     * don't exceed the chipset's limit if pScrn->maxHValue and
2334fe5e51b7Smrg     * pScrn->maxVValue are set.  Since our MGAValidMode() already takes
2335fe5e51b7Smrg     * care of this, we don't worry about setting them here.
2336fe5e51b7Smrg     */
2337fe5e51b7Smrg    {
2338fe5e51b7Smrg	int Pitches1[] =
2339fe5e51b7Smrg	  {640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
2340fe5e51b7Smrg	int Pitches2[] =
2341fe5e51b7Smrg	  {512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664,
2342fe5e51b7Smrg		1920, 2048, 0};
2343fe5e51b7Smrg	int *linePitches = NULL;
2344fe5e51b7Smrg	int minPitch = 256;
2345fe5e51b7Smrg	int maxPitch = 2048;
2346fe5e51b7Smrg
2347fe5e51b7Smrg        switch(pMga->Chipset) {
2348fe5e51b7Smrg	case PCI_CHIP_MGA2064:
2349fe5e51b7Smrg	   if (!pMga->NoAccel) {
23500bb88ba4Smrg		linePitches = malloc(sizeof(Pitches1));
2351fe5e51b7Smrg		memcpy(linePitches, Pitches1, sizeof(Pitches1));
2352fe5e51b7Smrg		minPitch = maxPitch = 0;
2353fe5e51b7Smrg	   }
2354fe5e51b7Smrg	   break;
2355fe5e51b7Smrg	case PCI_CHIP_MGA2164:
2356fe5e51b7Smrg	case PCI_CHIP_MGA2164_AGP:
2357fe5e51b7Smrg	case PCI_CHIP_MGA1064:
2358fe5e51b7Smrg	   if (!pMga->NoAccel) {
23590bb88ba4Smrg		linePitches = malloc(sizeof(Pitches2));
2360fe5e51b7Smrg		memcpy(linePitches, Pitches2, sizeof(Pitches2));
2361fe5e51b7Smrg		minPitch = maxPitch = 0;
2362fe5e51b7Smrg	   }
2363fe5e51b7Smrg	   break;
2364fe5e51b7Smrg	case PCI_CHIP_MGAG100:
2365fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
2366fe5e51b7Smrg	   maxPitch = 2048;
2367fe5e51b7Smrg	   break;
2368eda3803bSmrg	case PCI_CHIP_MGAG200_SE_A_PCI:
23690bb88ba4Smrg           if (pScrn->videoRam < 2048){
2370d7be9c72Smrg               maxPitch = 1280;
23710bb88ba4Smrg           }
23720bb88ba4Smrg           break;
2373fe5e51b7Smrg	case PCI_CHIP_MGAG200:
2374fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
2375fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
2376eda3803bSmrg        case PCI_CHIP_MGAG200_WINBOND_PCI:
23776f68ce78Smrg	case PCI_CHIP_MGAG200_EW3_PCI:
2378eda3803bSmrg	case PCI_CHIP_MGAG200_EV_PCI:
2379a31a186aSmrg    case PCI_CHIP_MGAG200_EH_PCI:
23800bb88ba4Smrg	case PCI_CHIP_MGAG200_ER_PCI:
2381fe5e51b7Smrg	case PCI_CHIP_MGAG400:
2382fe5e51b7Smrg	case PCI_CHIP_MGAG550:
2383fe5e51b7Smrg	   maxPitch = 4096;
2384fe5e51b7Smrg	   break;
2385fe5e51b7Smrg	}
2386fe5e51b7Smrg
2387fe5e51b7Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2388fe5e51b7Smrg			      pScrn->display->modes, clockRanges,
2389fe5e51b7Smrg			      linePitches, minPitch, maxPitch,
2390fe5e51b7Smrg			      pMga->Roundings[(pScrn->bitsPerPixel >> 3) - 1] *
2391fe5e51b7Smrg					pScrn->bitsPerPixel, 128, 2048,
2392fe5e51b7Smrg			      pScrn->display->virtualX,
2393fe5e51b7Smrg			      pScrn->display->virtualY,
2394fe5e51b7Smrg			      pMga->FbMapSize,
2395fe5e51b7Smrg			      LOOKUP_BEST_REFRESH);
2396fe5e51b7Smrg
23970bb88ba4Smrg	free(linePitches);
2398fe5e51b7Smrg    }
2399fe5e51b7Smrg
2400fe5e51b7Smrg    if (i < 1 && pMga->FBDev) {
2401fe5e51b7Smrg	fbdevHWUseBuildinMode(pScrn);
2402fe5e51b7Smrg	pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
2403fe5e51b7Smrg	i = 1;
2404fe5e51b7Smrg    }
2405fe5e51b7Smrg    if (i == -1) {
2406fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
2407fe5e51b7Smrg	MGAFreeRec(pScrn);
2408fe5e51b7Smrg	return FALSE;
2409fe5e51b7Smrg    }
2410fe5e51b7Smrg
2411fe5e51b7Smrg    /* Prune the modes marked as invalid */
2412fe5e51b7Smrg    xf86PruneDriverModes(pScrn);
2413fe5e51b7Smrg
2414fe5e51b7Smrg    if (i == 0 || pScrn->modes == NULL) {
2415fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2416fe5e51b7Smrg	MGAFreeRec(pScrn);
2417fe5e51b7Smrg	return FALSE;
2418fe5e51b7Smrg    }
2419fe5e51b7Smrg
2420fe5e51b7Smrg    /* If the Device section explicitly set HasSDRAM, don't bother checking.
2421fe5e51b7Smrg     */
2422fe5e51b7Smrg    if (!pMga->HasSDRAM) {
2423fe5e51b7Smrg	if ((pMga->softbooted || pMga->Primary)
2424fe5e51b7Smrg	     && pMga->chip_attribs->probe_for_sdram) {
2425fe5e51b7Smrg	    uint32_t option_reg;
2426fe5e51b7Smrg
2427fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2428fe5e51b7Smrg	    pci_device_cfg_read_u32(pMga->PciInfo, & option_reg,
2429fe5e51b7Smrg				    PCI_OPTION_REG);
2430fe5e51b7Smrg#else
2431fe5e51b7Smrg	    option_reg = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
2432fe5e51b7Smrg#endif
2433fe5e51b7Smrg	    pMga->HasSDRAM = ((option_reg & (1 << 14)) == 0);
2434fe5e51b7Smrg	}
2435fe5e51b7Smrg	else {
2436fe5e51b7Smrg	    pMga->HasSDRAM = pMga->chip_attribs->has_sdram;
2437fe5e51b7Smrg	}
2438fe5e51b7Smrg
2439fe5e51b7Smrg	if (pMga->HasSDRAM) {
2440fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Has SDRAM\n");
2441fe5e51b7Smrg	}
2442fe5e51b7Smrg    }
2443fe5e51b7Smrg
2444fe5e51b7Smrg    /*
2445fe5e51b7Smrg     * Set the CRTC parameters for all of the modes based on the type
2446fe5e51b7Smrg     * of mode, and the chipset's interlace requirements.
2447fe5e51b7Smrg     *
2448fe5e51b7Smrg     * Calling this is required if the mode->Crtc* values are used by the
2449fe5e51b7Smrg     * driver and if the driver doesn't provide code to set them.  They
2450fe5e51b7Smrg     * are not pre-initialised at all.
2451fe5e51b7Smrg     */
2452fe5e51b7Smrg    MGA_NOT_HAL(xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V));
2453fe5e51b7Smrg
2454fe5e51b7Smrg    /* Set the current mode to the first in the list */
2455fe5e51b7Smrg    pScrn->currentMode = pScrn->modes;
2456fe5e51b7Smrg
2457fe5e51b7Smrg    /* Print the list of modes being used */
2458fe5e51b7Smrg    xf86PrintModes(pScrn);
2459fe5e51b7Smrg
2460fe5e51b7Smrg    /* Set display resolution */
2461fe5e51b7Smrg    xf86SetDpi(pScrn, 0, 0);
2462fe5e51b7Smrg
2463fe5e51b7Smrg    /*
2464fe5e51b7Smrg     * Compute the byte offset into the linear frame buffer where the
2465fe5e51b7Smrg     * frame buffer data should actually begin.  According to DDK misc.c
2466fe5e51b7Smrg     * line 1023, if more than 4MB is to be displayed, YDSTORG must be set
2467fe5e51b7Smrg     * appropriately to align memory bank switching, and this requires a
2468fe5e51b7Smrg     * corresponding offset on linear frame buffer access.
2469fe5e51b7Smrg     * This is only needed for WRAM.
2470fe5e51b7Smrg     */
2471fe5e51b7Smrg
2472fe5e51b7Smrg    pMga->YDstOrg = 0;
2473fe5e51b7Smrg    if (pMga->chip_attribs->fb_4mb_quirk &&
2474fe5e51b7Smrg	(pScrn->virtualX * pScrn->virtualY * bytesPerPixel > 4*1024*1024)) {
2475fe5e51b7Smrg	int offset;
2476fe5e51b7Smrg	int offset_modulo = (pScrn->bitsPerPixel == 24) ? 12 : 4;
2477fe5e51b7Smrg	int ydstorg_modulo = 64;
2478fe5e51b7Smrg
2479fe5e51b7Smrg
2480fe5e51b7Smrg	if (pMga->Interleave) {
2481fe5e51b7Smrg	    offset_modulo <<= 1;
2482fe5e51b7Smrg	    ydstorg_modulo <<= 1;
2483fe5e51b7Smrg	}
2484fe5e51b7Smrg
2485fe5e51b7Smrg	offset = (4*1024*1024) % (pScrn->displayWidth * bytesPerPixel);
2486fe5e51b7Smrg	pMga->YDstOrg = offset / bytesPerPixel;
2487fe5e51b7Smrg
2488fe5e51b7Smrg	/*
2489fe5e51b7Smrg	 * When this was unconditional, it caused a line of horizontal garbage
2490fe5e51b7Smrg	 * at the middle right of the screen at the 4Meg boundary in 32bpp
2491fe5e51b7Smrg	 * (and presumably any other modes that use more than 4M). But it's
2492fe5e51b7Smrg	 * essential for 24bpp (it may not matter either way for 8bpp & 16bpp,
2493fe5e51b7Smrg	 * I'm not sure; I didn't notice problems when I checked with and
2494fe5e51b7Smrg	 * without.)
2495fe5e51b7Smrg	 * DRM Doug Merritt 12/97, submitted to XFree86 6/98 (oops)
2496fe5e51b7Smrg	 */
2497fe5e51b7Smrg	if (bytesPerPixel < 4) {
2498fe5e51b7Smrg	    while ((offset % offset_modulo) != 0 ||
2499fe5e51b7Smrg		   (pMga->YDstOrg % ydstorg_modulo) != 0) {
2500fe5e51b7Smrg		offset++;
2501fe5e51b7Smrg		pMga->YDstOrg = offset / bytesPerPixel;
2502fe5e51b7Smrg	    }
2503fe5e51b7Smrg	}
2504fe5e51b7Smrg    }
2505fe5e51b7Smrg
2506fe5e51b7Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "YDstOrg is set to %d\n",
2507fe5e51b7Smrg		   pMga->YDstOrg);
2508fe5e51b7Smrg    if(pMga->DualHeadEnabled) {
2509fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2510fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->masterFbMapSize;
2511fe5e51b7Smrg            /* Allocate HW cursor buffer at the end of video ram */
2512fe5e51b7Smrg	    if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2513fe5e51b7Smrg	        if( pScrn->virtualY * pScrn->displayWidth *
2514fe5e51b7Smrg		    pScrn->bitsPerPixel / 8 <=
2515fe5e51b7Smrg		    pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2516fe5e51b7Smrg		    pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2517fe5e51b7Smrg		    pMga->FbCursorOffset =
2518fe5e51b7Smrg		      pMgaEnt->masterFbMapSize -
2519fe5e51b7Smrg		      pMga->Dac.CursorOffscreenMemSize;
2520fe5e51b7Smrg		} else {
2521fe5e51b7Smrg		    pMga->HWCursor = FALSE;
2522fe5e51b7Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2523fe5e51b7Smrg			       "Too little offscreen memory for HW cursor; "
2524fe5e51b7Smrg			       "using SW cursor\n");
2525fe5e51b7Smrg		}
2526fe5e51b7Smrg	    }
2527fe5e51b7Smrg	} else { /* Second CRTC */
2528fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->slaveFbMapSize;
2529fe5e51b7Smrg	    pMga->HWCursor = FALSE;
2530fe5e51b7Smrg	}
2531fe5e51b7Smrg    } else {
2532fe5e51b7Smrg        pMga->FbUsableSize = pMga->FbMapSize - pMga->YDstOrg * bytesPerPixel;
2533fe5e51b7Smrg           /* Allocate HW cursor buffer at the end of video ram */
2534fe5e51b7Smrg        if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2535fe5e51b7Smrg	    if( pScrn->virtualY * pScrn->displayWidth *
2536fe5e51b7Smrg	        pScrn->bitsPerPixel / 8 <=
2537fe5e51b7Smrg        	pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2538fe5e51b7Smrg	        pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2539fe5e51b7Smrg	        pMga->FbCursorOffset =
2540fe5e51b7Smrg		  pMga->FbMapSize - pMga->Dac.CursorOffscreenMemSize;
2541fe5e51b7Smrg	    } else {
2542fe5e51b7Smrg	        pMga->HWCursor = FALSE;
2543fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2544fe5e51b7Smrg			   "Too little offscreen memory for HW cursor; "
2545fe5e51b7Smrg			   "using SW cursor\n");
2546fe5e51b7Smrg	    }
2547fe5e51b7Smrg	}
2548fe5e51b7Smrg    }
2549fe5e51b7Smrg    /*
2550fe5e51b7Smrg     * XXX This should be taken into account in some way in the mode valdation
2551fe5e51b7Smrg     * section.
2552fe5e51b7Smrg     */
2553fe5e51b7Smrg
2554fe5e51b7Smrg
2555fe5e51b7Smrg    /* Load the required framebuffer */
2556eda3803bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) {
2557eda3803bSmrg	MGAFreeRec(pScrn);
2558eda3803bSmrg	return FALSE;
2559fe5e51b7Smrg    }
2560fe5e51b7Smrg
2561fe5e51b7Smrg    /* Load ramdac if needed */
2562fe5e51b7Smrg    if (pMga->HWCursor) {
2563fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
2564fe5e51b7Smrg	    MGAFreeRec(pScrn);
2565fe5e51b7Smrg	    return FALSE;
2566fe5e51b7Smrg	}
2567fe5e51b7Smrg    }
2568fe5e51b7Smrg
2569fe5e51b7Smrg    /* Load shadowfb if needed */
2570fe5e51b7Smrg    if (pMga->ShadowFB) {
2571fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2572fe5e51b7Smrg	    MGAFreeRec(pScrn);
2573fe5e51b7Smrg	    return FALSE;
2574fe5e51b7Smrg	}
2575fe5e51b7Smrg    }
2576fe5e51b7Smrg
25770bb88ba4Smrg#ifdef MGADRI
2578fe5e51b7Smrg    /* Load the dri module if requested. */
2579fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_DRI, FALSE)) {
2580643b027fSmrg       xf86LoadSubModule(pScrn, "dri");
2581fe5e51b7Smrg    }
2582fe5e51b7Smrg#endif
2583fe5e51b7Smrg    pMga->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
2584fe5e51b7Smrg    pMga->CurrentLayout.depth = pScrn->depth;
2585fe5e51b7Smrg    pMga->CurrentLayout.displayWidth = pScrn->displayWidth;
2586fe5e51b7Smrg    pMga->CurrentLayout.weight.red = pScrn->weight.red;
2587fe5e51b7Smrg    pMga->CurrentLayout.weight.green = pScrn->weight.green;
2588fe5e51b7Smrg    pMga->CurrentLayout.weight.blue = pScrn->weight.blue;
2589fe5e51b7Smrg    pMga->CurrentLayout.mode = pScrn->currentMode;
2590fe5e51b7Smrg
2591fe5e51b7Smrg
2592fe5e51b7Smrg
2593fe5e51b7Smrg    if(pMga->MergedFB) {
2594fe5e51b7Smrg        MGAPreInitMergedFB(pScrn,flags);
2595fe5e51b7Smrg    };
2596fe5e51b7Smrg
2597fe5e51b7Smrg
2598fe5e51b7Smrg    xf86SetPrimInitDone(pScrn->entityList[0]);
2599fe5e51b7Smrg
2600fe5e51b7Smrg    return TRUE;
2601fe5e51b7Smrg}
2602fe5e51b7Smrg
2603fe5e51b7Smrg
2604fe5e51b7Smrg/*
2605fe5e51b7Smrg * Map the framebuffer and MMIO memory.
2606fe5e51b7Smrg */
2607fe5e51b7Smrg
2608fe5e51b7Smrgstatic Bool
2609fe5e51b7SmrgMGAMapMem(ScrnInfoPtr pScrn)
2610fe5e51b7Smrg{
2611fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2612fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2613fe5e51b7Smrg    struct pci_device *const dev = pMga->PciInfo;
2614fe5e51b7Smrg    struct pci_mem_region *region;
2615fe5e51b7Smrg    int i, err;
2616fe5e51b7Smrg#endif
2617fe5e51b7Smrg
2618fe5e51b7Smrg
2619fe5e51b7Smrg    if (!pMga->FBDev) {
2620fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2621acd6767fSmrg	pciaddr_t fbaddr = pMga->FbAddress;
2622acd6767fSmrg	pciaddr_t fbsize = pMga->FbMapSize;
2623acd6767fSmrg	err = pci_device_map_range(dev,
2624acd6767fSmrg				   fbaddr, fbsize,
26256f68ce78Smrg				   PCI_DEV_MAP_FLAG_WRITABLE |
26266f68ce78Smrg				   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
2627acd6767fSmrg				   (void **)&pMga->FbBase);
2628acd6767fSmrg
2629acd6767fSmrg	if (err) {
2630acd6767fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2631acd6767fSmrg		       "Unable to map Framebuffer %08llX %llx.  %s (%d)\n",
2632acd6767fSmrg		       (long long)fbaddr, (long long)fbsize,
2633acd6767fSmrg		       strerror(err), err);
2634acd6767fSmrg	    return FALSE;
2635acd6767fSmrg	}
2636acd6767fSmrg	else
2637acd6767fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2638acd6767fSmrg		       "MAPPED Framebuffer %08llX %llx to %08llX.\n",
2639acd6767fSmrg		       (long long)fbaddr, (long long)fbsize,
2640acd6767fSmrg		       (long long)pMga->FbBase);
2641acd6767fSmrg
2642acd6767fSmrg	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
2643acd6767fSmrg	    region = &dev->regions[pMga->io_bar];
2644acd6767fSmrg	    err = pci_device_map_range(dev,
2645acd6767fSmrg				       region->base_addr, region->size,
2646acd6767fSmrg				       PCI_DEV_MAP_FLAG_WRITABLE,
2647acd6767fSmrg				       &pMga->IOBase);
2648acd6767fSmrg
2649acd6767fSmrg	    if (err) {
2650acd6767fSmrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2651acd6767fSmrg			 "Unable to map IO Region %i.  %s (%d)\n",
2652acd6767fSmrg			 pMga->io_bar, strerror(err), err);
2653acd6767fSmrg	      return FALSE;
2654acd6767fSmrg	    }
2655fe5e51b7Smrg
2656acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2657acd6767fSmrg		pMga->entityPrivate->mappedIOBase = pMga->IOBase;
2658acd6767fSmrg	}
2659acd6767fSmrg	else
2660acd6767fSmrg		pMga->IOBase = pMga->entityPrivate->mappedIOBase;
2661acd6767fSmrg
2662acd6767fSmrg	if(pMga->entityPrivate != NULL)
2663acd6767fSmrg		pMga->entityPrivate->mappedIOUsage ++;
2664fe5e51b7Smrg
2665fe5e51b7Smrg#else
2666fe5e51b7Smrg	/*
2667fe5e51b7Smrg	 * For Alpha, we need to map SPARSE memory, since we need
2668fe5e51b7Smrg	 * byte/short access.  This is taken care of automatically by the
2669fe5e51b7Smrg	 * os-support layer.
2670fe5e51b7Smrg	 */
2671fe5e51b7Smrg	pMga->IOBase = xf86MapPciMem(pScrn->scrnIndex,
2672fe5e51b7Smrg				     VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
2673fe5e51b7Smrg				     pMga->PciTag, pMga->IOAddress, 0x4000);
2674fe5e51b7Smrg	if (pMga->IOBase == NULL)
2675fe5e51b7Smrg	    return FALSE;
2676fe5e51b7Smrg
26770bb88ba4Smrg    if (pMga->is_G200ER)
26780bb88ba4Smrg    {
26790bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
26800bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
26810bb88ba4Smrg                         pMga->FbMapSize);
26820bb88ba4Smrg    }
26830bb88ba4Smrg    else
26840bb88ba4Smrg    {
26850bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
26860bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
26870bb88ba4Smrg                         pMga->FbMapSize);
26880bb88ba4Smrg    }
2689fe5e51b7Smrg	if (pMga->FbBase == NULL)
2690fe5e51b7Smrg	    return FALSE;
2691fe5e51b7Smrg#endif
2692fe5e51b7Smrg    }
2693fe5e51b7Smrg    else {
2694fe5e51b7Smrg	pMga->FbBase = fbdevHWMapVidmem(pScrn);
2695fe5e51b7Smrg	if (pMga->FbBase == NULL) {
2696fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2697fe5e51b7Smrg		       "Unable to map framebuffer.\n");
2698fe5e51b7Smrg	    return FALSE;
2699fe5e51b7Smrg	}
2700fe5e51b7Smrg
2701fe5e51b7Smrg	pMga->IOBase = fbdevHWMapMMIO(pScrn);
2702fe5e51b7Smrg	if (pMga->IOBase == NULL) {
2703fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map MMIO.\n");
2704fe5e51b7Smrg	    return FALSE;
2705fe5e51b7Smrg	}
2706fe5e51b7Smrg    }
2707fe5e51b7Smrg
2708fe5e51b7Smrg
2709fe5e51b7Smrg    pMga->FbStart = pMga->FbBase + pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
2710fe5e51b7Smrg
2711fe5e51b7Smrg    pMga->ILOADBase = NULL;
2712fe5e51b7Smrg    if (pMga->iload_bar != -1) {
2713fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2714fe5e51b7Smrg        region = &dev->regions[pMga->iload_bar];
2715acd6767fSmrg
2716acd6767fSmrg	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) {
2717acd6767fSmrg	    err = pci_device_map_range(dev,
2718acd6767fSmrg				       region->base_addr, region->size,
2719acd6767fSmrg				       PCI_DEV_MAP_FLAG_WRITABLE,
2720acd6767fSmrg				       (void *) &pMga->ILOADBase);
2721acd6767fSmrg	    if (err) {
2722acd6767fSmrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2723acd6767fSmrg			 "Unable to map BAR 2 (ILOAD region).  %s (%d)\n",
2724acd6767fSmrg			 strerror(err), err);
2725acd6767fSmrg	      return FALSE;
2726acd6767fSmrg	    }
2727acd6767fSmrg
2728acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2729acd6767fSmrg		pMga->entityPrivate->mappedILOADBase = pMga->ILOADBase;
2730fe5e51b7Smrg	}
2731acd6767fSmrg	else
2732acd6767fSmrg		pMga->ILOADBase = pMga->entityPrivate->mappedILOADBase;
2733acd6767fSmrg
2734acd6767fSmrg	if(pMga->entityPrivate != NULL)
2735acd6767fSmrg		pMga->entityPrivate->mappedILOADUsage ++;
2736fe5e51b7Smrg#else
2737fe5e51b7Smrg	pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
2738fe5e51b7Smrg					VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
2739fe5e51b7Smrg					VIDMEM_READSIDEEFFECT,
2740fe5e51b7Smrg					pMga->PciTag, pMga->ILOADAddress,
2741fe5e51b7Smrg					0x800000);
2742fe5e51b7Smrg#endif
2743fe5e51b7Smrg    }
2744fe5e51b7Smrg
2745fe5e51b7Smrg
2746fe5e51b7Smrg    return TRUE;
2747fe5e51b7Smrg}
2748fe5e51b7Smrg
2749fe5e51b7Smrg
2750fe5e51b7Smrg/*
2751fe5e51b7Smrg * Unmap the framebuffer and MMIO memory.
2752fe5e51b7Smrg */
2753fe5e51b7Smrg
2754fe5e51b7Smrgstatic Bool
2755fe5e51b7SmrgMGAUnmapMem(ScrnInfoPtr pScrn)
2756fe5e51b7Smrg{
2757fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2758fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2759fe5e51b7Smrg    struct pci_device * const dev = pMga->PciInfo;
2760fe5e51b7Smrg#endif
2761fe5e51b7Smrg
2762fe5e51b7Smrg
2763fe5e51b7Smrg    if (!pMga->FBDev) {
2764fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2765acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2766acd6767fSmrg		pMga->entityPrivate->mappedIOUsage--;
2767acd6767fSmrg
2768acd6767fSmrg	    if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
2769acd6767fSmrg		pci_device_unmap_range(dev, pMga->IOBase,
2770acd6767fSmrg				       dev->regions[pMga->io_bar].size);
2771acd6767fSmrg
2772acd6767fSmrg		if(pMga->entityPrivate != NULL)
2773acd6767fSmrg			pMga->entityPrivate->mappedIOBase = NULL;
2774acd6767fSmrg	    }
2775acd6767fSmrg
2776acd6767fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UNMAPPING framebuffer 0x%08llX, 0x%llX.\n", (long long)pMga->FbBase, (long long)pMga->FbMapSize);
2777fe5e51b7Smrg        pci_device_unmap_range(dev, pMga->FbBase,
2778acd6767fSmrg			       pMga->FbMapSize);
2779fe5e51b7Smrg#else
2780fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
2781fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase, pMga->FbMapSize);
2782fe5e51b7Smrg#endif
2783fe5e51b7Smrg    }
2784fe5e51b7Smrg    else {
2785fe5e51b7Smrg	fbdevHWUnmapVidmem(pScrn);
2786fe5e51b7Smrg	fbdevHWUnmapMMIO(pScrn);
2787fe5e51b7Smrg    }
2788fe5e51b7Smrg
2789fe5e51b7Smrg    if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
2790fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2791acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2792acd6767fSmrg		pMga->entityPrivate->mappedILOADUsage--;
2793acd6767fSmrg
2794acd6767fSmrg	    if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) {
2795acd6767fSmrg		pci_device_unmap_range(dev, pMga->ILOADBase,
2796acd6767fSmrg				       dev->regions[pMga->iload_bar].size);
2797acd6767fSmrg
2798acd6767fSmrg		if(pMga->entityPrivate != NULL)
2799acd6767fSmrg		    pMga->entityPrivate->mappedILOADBase = NULL;
2800acd6767fSmrg	    }
2801acd6767fSmrg
2802fe5e51b7Smrg#else
2803fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
2804fe5e51b7Smrg#endif
2805fe5e51b7Smrg    }
2806fe5e51b7Smrg
2807fe5e51b7Smrg    pMga->IOBase = NULL;
2808fe5e51b7Smrg    pMga->FbBase = NULL;
2809fe5e51b7Smrg    pMga->FbStart = NULL;
2810fe5e51b7Smrg    pMga->ILOADBase = NULL;
2811fe5e51b7Smrg
2812fe5e51b7Smrg    return TRUE;
2813fe5e51b7Smrg}
2814fe5e51b7Smrg
2815fe5e51b7Smrg
2816fe5e51b7Smrg/*
2817fe5e51b7Smrg * This function saves the video state.
2818fe5e51b7Smrg */
2819fe5e51b7Smrgstatic void
2820fe5e51b7SmrgMGASave(ScrnInfoPtr pScrn)
2821fe5e51b7Smrg{
2822fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2823fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
2824fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2825fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
2826fe5e51b7Smrg
2827fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) return;
2828fe5e51b7Smrg
2829fe5e51b7Smrg    /* I need to save the registers for the second head also */
2830fe5e51b7Smrg    /* Save the register for 0x80 to 0xa0 */
2831fe5e51b7Smrg    /* Could call it dac2Saved */
2832fe5e51b7Smrg
2833fe5e51b7Smrg    /* Only save text mode fonts/text for the primary card */
2834fe5e51b7Smrg    (*pMga->Save)(pScrn, vgaReg, mgaReg, pMga->Primary);
2835fe5e51b7Smrg}
2836fe5e51b7Smrg
2837fe5e51b7Smrg/*
2838fe5e51b7Smrg * Initialise a new mode.  This is currently still using the old
2839fe5e51b7Smrg * "initialise struct, restore/write struct to HW" model.  That could
2840fe5e51b7Smrg * be changed.
2841fe5e51b7Smrg */
2842fe5e51b7Smrg
2843fe5e51b7Smrgstatic Bool
2844fe5e51b7SmrgMGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
2845fe5e51b7Smrg{
2846fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2847fe5e51b7Smrg    vgaRegPtr vgaReg;
2848fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2849fe5e51b7Smrg    MGARegPtr mgaReg;
2850fe5e51b7Smrg
2851fe5e51b7Smrg    vgaHWUnlock(hwp);
2852fe5e51b7Smrg
2853fe5e51b7Smrg/*    if(pMga->MergedFB && mode && mode->Private && (mode->PrivSize == 0)) {
2854fe5e51b7Smrg        mode = (DisplayModePtr)mode->Private;
2855fe5e51b7Smrg    }*/
2856fe5e51b7Smrg
2857fe5e51b7Smrg    /* Initialise the ModeReg values */
2858fe5e51b7Smrg    if (!vgaHWInit(pScrn, mode))
2859fe5e51b7Smrg	return FALSE;
2860fe5e51b7Smrg    pScrn->vtSema = TRUE;
2861fe5e51b7Smrg
2862fe5e51b7Smrg    if (!(*pMga->ModeInit)(pScrn, mode))
2863fe5e51b7Smrg	return FALSE;
2864fe5e51b7Smrg
2865fe5e51b7Smrg    /* Program the registers */
2866fe5e51b7Smrg    if (pMga->is_G200SE) {
2867fe5e51b7Smrg	MGAG200SEHWProtect(pScrn, TRUE);
2868fe5e51b7Smrg    } else {
2869fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
2870fe5e51b7Smrg    }
2871fe5e51b7Smrg    vgaReg = &hwp->ModeReg;
2872fe5e51b7Smrg    mgaReg = &pMga->ModeReg;
2873fe5e51b7Smrg
28740bb88ba4Smrg#ifdef MGADRI
2875fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
28760bb88ba4Smrg       DRILock(xf86ScrnToScreen(pScrn), 0);
2877fe5e51b7Smrg   }
2878fe5e51b7Smrg#endif
2879fe5e51b7Smrg
2880fe5e51b7Smrg    MGA_NOT_HAL((*pMga->Restore)(pScrn, vgaReg, mgaReg, FALSE));
2881fe5e51b7Smrg
2882fe5e51b7Smrg    MGAStormSync(pScrn);
2883fe5e51b7Smrg    MGAStormEngineInit(pScrn);
2884fe5e51b7Smrg
2885fe5e51b7Smrg    if (pMga->is_G200SE) {
2886fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
2887fe5e51b7Smrg    } else {
2888fe5e51b7Smrg	vgaHWProtect(pScrn, FALSE);
2889fe5e51b7Smrg    }
2890fe5e51b7Smrg
28910bb88ba4Smrg    /* Reset tagfifo*/
28920bb88ba4Smrg	if (pMga->is_G200ER)
28930bb88ba4Smrg    {
28940bb88ba4Smrg        CARD32 ulMemCtl = INREG(MGAREG_MEMCTL);
28950bb88ba4Smrg        CARD8  ucSeq1;
28960bb88ba4Smrg
28970bb88ba4Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reset tagfifo\n");
28980bb88ba4Smrg        /* Screen off */
28990bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
29000bb88ba4Smrg	    ucSeq1 = INREG8(MGAREG_SEQ_DATA) | 0x20;
29010bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1);
29020bb88ba4Smrg
29030bb88ba4Smrg        /* Reset tagfifo */
29040bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl | 0x002000000);
29050bb88ba4Smrg        usleep(1000); /* wait 1ms */
29060bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl & ~0x002000000);
29070bb88ba4Smrg
29080bb88ba4Smrg        /* Screen on */
29090bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1 & ~0x20);
29100bb88ba4Smrg
2911fe5e51b7Smrg    }
2912fe5e51b7Smrg
29130bb88ba4Smrg    /*
29140bb88ba4Smrg     This function optimize the Priority Request control
29150bb88ba4Smrg     Higher HiPriLvl will reduce drawing performance
29160bb88ba4Smrg     We need to give enough bandwith to crtc to avoid visual artifact
29170bb88ba4Smrg    */
29180bb88ba4Smrg	if (pMga->is_G200SE)
29190bb88ba4Smrg    {
29200bb88ba4Smrg        if (pMga->reg_1e24 >= 0x02)
29210bb88ba4Smrg        {
29220bb88ba4Smrg            /* Calulate CRTC Priority value */
29230bb88ba4Smrg            CARD8  ucHiPriLvl;
29240bb88ba4Smrg            CARD32 ulBitsPerPixel;
29250bb88ba4Smrg            CARD32 ulMemoryBandwidth;
29260bb88ba4Smrg
29270bb88ba4Smrg            /* uiBitsPerPixel can only be 8,16 or32 */
29280bb88ba4Smrg            if (pScrn->bitsPerPixel > 16)
29290bb88ba4Smrg            {
29300bb88ba4Smrg                ulBitsPerPixel = 32;
29310bb88ba4Smrg            }
29320bb88ba4Smrg            else if (pScrn->bitsPerPixel >  8)
29330bb88ba4Smrg            {
29340bb88ba4Smrg                ulBitsPerPixel = 16;
29350bb88ba4Smrg            }
29360bb88ba4Smrg            else
29370bb88ba4Smrg            {
29380bb88ba4Smrg                ulBitsPerPixel = 8;
29390bb88ba4Smrg            }
29400bb88ba4Smrg
29410bb88ba4Smrg
29420bb88ba4Smrg            ulMemoryBandwidth = (mode->Clock * ulBitsPerPixel) / 1000;
29430bb88ba4Smrg
29440bb88ba4Smrg            if      (ulMemoryBandwidth    > 3100)  ucHiPriLvl = 0;
29450bb88ba4Smrg            else if (ulMemoryBandwidth    > 2600)  ucHiPriLvl = 1;
29460bb88ba4Smrg            else if (ulMemoryBandwidth    > 1900)  ucHiPriLvl = 2;
29470bb88ba4Smrg            else if (ulMemoryBandwidth    > 1160)  ucHiPriLvl = 3;
29480bb88ba4Smrg            else if (ulMemoryBandwidth    > 440)   ucHiPriLvl = 4;
29490bb88ba4Smrg            else ucHiPriLvl = 5;
29500bb88ba4Smrg
2951fe5e51b7Smrg            OUTREG8(0x1FDE, 0x06);
29520bb88ba4Smrg		    OUTREG8(0x1FDF, ucHiPriLvl);
29530bb88ba4Smrg
29540bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %d\n",   mode->Clock);
29550bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %d\n",   pScrn->bitsPerPixel);
29560bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MemoryBandwidth == %d\n",   ulMemoryBandwidth);
29570bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == %02X\n", ucHiPriLvl);
2958fe5e51b7Smrg        }
29590bb88ba4Smrg        else
29600bb88ba4Smrg        {
29610bb88ba4Smrg            MGA_NOT_HAL(
29620bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %d\n",   mode->Clock);
29630bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %d\n",   pScrn->bitsPerPixel);
29640bb88ba4Smrg                OUTREG8(0x1FDE, 0x06);
29650bb88ba4Smrg	            if (pMga->reg_1e24 >= 0x01)
29660bb88ba4Smrg                {
29670bb88ba4Smrg		            OUTREG8(0x1FDF, 0x03);
29680bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 03\n");
29690bb88ba4Smrg                }
29700bb88ba4Smrg	            else
29710bb88ba4Smrg                {
29720bb88ba4Smrg		            OUTREG8(0x1FDF, 0x14);
29730bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 14h\n");
29740bb88ba4Smrg                }
29750bb88ba4Smrg            );
29760bb88ba4Smrg        }
29770bb88ba4Smrg    }
2978fe5e51b7Smrg
2979fe5e51b7Smrg    pMga->CurrentLayout.mode = mode;
2980fe5e51b7Smrg
2981fe5e51b7Smrg    if(pMga->MergedFB && mode->Private && (mode->PrivSize == 0)) {
2982fe5e51b7Smrg	pMga->M1currentMode = (DisplayModePtr)mode->Private;
2983fe5e51b7Smrg    }
2984fe5e51b7Smrg
29850bb88ba4Smrg#ifdef MGADRI
2986fe5e51b7Smrg   if (pMga->directRenderingEnabled)
29870bb88ba4Smrg     DRIUnlock(xf86ScrnToScreen(pScrn));
2988fe5e51b7Smrg#endif
2989fe5e51b7Smrg#ifdef DEBUG
2990fe5e51b7Smrg   MGAG450PrintPLL(pScrn);
2991fe5e51b7Smrg#endif
2992fe5e51b7Smrg    return TRUE;
2993fe5e51b7Smrg}
2994fe5e51b7Smrg
2995fe5e51b7Smrgstatic
2996fe5e51b7Smrgvoid MGARestoreSecondCrtc(ScrnInfoPtr pScrn)
2997fe5e51b7Smrg{
2998fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2999fe5e51b7Smrg
3000fe5e51b7Smrg    if (MGAISGx50(pMga)) {
3001fe5e51b7Smrg        /* Force to return in clone mode */
3002fe5e51b7Smrg        if (pMga->SecondOutput
3003fe5e51b7Smrg                && (xf86IsEntityShared(pScrn->entityList[0]) || pMga->SecondCrtc)
3004fe5e51b7Smrg                && !pMga->MergedFB) {
3005fe5e51b7Smrg            /* Do this branch if
3006fe5e51b7Smrg             * SecondOutput
3007fe5e51b7Smrg             * and not Unshared Primary
3008fe5e51b7Smrg             * and not Merged Mode (usualy means Unshared Primary)
3009fe5e51b7Smrg             */
3010fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3011fe5e51b7Smrg
3012fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3013fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3014fe5e51b7Smrg
3015fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3016fe5e51b7Smrg
3017fe5e51b7Smrg       } else {
3018fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3019fe5e51b7Smrg            CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3020fe5e51b7Smrg
3021fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3022fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC1OUTSEL_EN;
3023fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3024fe5e51b7Smrg
3025fe5e51b7Smrg            /* crtcdacsel -> crtc1 */
3026fe5e51b7Smrg            ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_CRTC2;
3027fe5e51b7Smrg            ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC1;
3028fe5e51b7Smrg
3029fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3030fe5e51b7Smrg            OUTREG(MGAREG_C2CTL, ulC2CTL);
3031fe5e51b7Smrg       }
3032fe5e51b7Smrg
3033fe5e51b7Smrg    } else {
3034fe5e51b7Smrg        /* Force to close second crtc */
3035fe5e51b7Smrg        CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3036fe5e51b7Smrg
3037fe5e51b7Smrg        ulC2CTL &= ~MGAREG_C2CTL_C2_EN;
3038fe5e51b7Smrg
3039fe5e51b7Smrg        OUTREG(MGAREG_C2CTL, ulC2CTL);
3040fe5e51b7Smrg    }
3041fe5e51b7Smrg}
3042fe5e51b7Smrg
3043fe5e51b7Smrg/*
3044fe5e51b7Smrg * Restore the initial (text) mode.
3045fe5e51b7Smrg */
3046fe5e51b7Smrgstatic void
3047fe5e51b7SmrgMGARestore(ScrnInfoPtr pScrn)
3048fe5e51b7Smrg{
3049fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3050fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
3051fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3052fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
3053fe5e51b7Smrg
3054fe5e51b7Smrg    if (pScrn->pScreen != NULL)
3055fe5e51b7Smrg	MGAStormSync(pScrn);
3056fe5e51b7Smrg
3057fe5e51b7Smrg    /*
3058fe5e51b7Smrg     * Restore the second crtc if:
3059fe5e51b7Smrg     * first and only driver entity
3060fe5e51b7Smrg     * second entity
3061fe5e51b7Smrg     * Merged Framebuffer mode (first and only driver entity)
3062fe5e51b7Smrg     */
3063fe5e51b7Smrg    if((!xf86IsEntityShared(pScrn->entityList[0]) && !pMga->SecondCrtc)
3064fe5e51b7Smrg       || pMga->SecondCrtc || pMga->MergedFB) {
3065fe5e51b7Smrg	/*       if(pMga->MergedFB) {
3066fe5e51b7Smrg		 if(pMga->pScrn2)
3067fe5e51b7Smrg                 MGARestoreSecondCrtc(pMga->pScrn2);
3068fe5e51b7Smrg		 } else*/
3069fe5e51b7Smrg	MGARestoreSecondCrtc(pScrn);
3070fe5e51b7Smrg	/* if we are second instance of driver, we've done our job, exit */
3071fe5e51b7Smrg	if(pMga->SecondCrtc) return;
3072fe5e51b7Smrg    }
3073fe5e51b7Smrg
3074fe5e51b7Smrg    /* Only restore text mode fonts/text for the primary card */
3075fe5e51b7Smrg    if (pMga->is_G200SE) {
3076fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,TRUE);
3077fe5e51b7Smrg    } else {
3078fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
3079fe5e51b7Smrg    }
3080fe5e51b7Smrg    if (pMga->Primary) {
3081fe5e51b7Smrg        (*pMga->Restore)(pScrn, vgaReg, mgaReg, TRUE);
3082fe5e51b7Smrg    } else {
3083fe5e51b7Smrg        vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
3084fe5e51b7Smrg    }
3085fe5e51b7Smrg
3086fe5e51b7Smrg    if (pMga->is_G200SE) {
3087fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
3088fe5e51b7Smrg    } else {
3089fe5e51b7Smrg	vgaHWProtect(pScrn,FALSE);
3090fe5e51b7Smrg    }
3091fe5e51b7Smrg}
3092fe5e51b7Smrg
3093fe5e51b7Smrg
3094fe5e51b7Smrg/* Workaround for a G400 CRTC2 display problem */
3095fe5e51b7Smrgstatic void
3096fe5e51b7SmrgMGACrtc2FillStrip(ScrnInfoPtr pScrn)
3097fe5e51b7Smrg{
3098fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3099fe5e51b7Smrg
3100fe5e51b7Smrg    if (pMga->NoAccel) {
3101fe5e51b7Smrg	/* Clears the whole screen, but ... */
3102fe5e51b7Smrg	bzero(pMga->FbStart,
3103fe5e51b7Smrg	    (pScrn->bitsPerPixel >> 3) * pScrn->displayWidth * pScrn->virtualY);
3104fe5e51b7Smrg    } else {
3105fe5e51b7Smrg	xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
3106acd6767fSmrg#ifdef HAVE_XAA_H
3107fe5e51b7Smrg	pMga->RestoreAccelState(pScrn);
3108fe5e51b7Smrg	pMga->SetupForSolidFill(pScrn, 0, GXcopy, 0xFFFFFFFF);
3109fe5e51b7Smrg	pMga->SubsequentSolidFillRect(pScrn, pScrn->virtualX, 0,
3110fe5e51b7Smrg				  pScrn->displayWidth - pScrn->virtualX,
3111fe5e51b7Smrg				  pScrn->virtualY);
3112acd6767fSmrg#endif
3113fe5e51b7Smrg	MGAStormSync(pScrn);
3114fe5e51b7Smrg    }
3115fe5e51b7Smrg}
3116fe5e51b7Smrg
3117fe5e51b7Smrg
3118fe5e51b7Smrg/* Mandatory */
3119fe5e51b7Smrg
3120fe5e51b7Smrg/* This gets called at the start of each server generation */
3121fe5e51b7Smrg
3122fe5e51b7Smrgstatic Bool
31230bb88ba4SmrgMGAScreenInit(SCREEN_INIT_ARGS_DECL)
3124fe5e51b7Smrg{
31250bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3126fe5e51b7Smrg    vgaHWPtr hwp;
3127fe5e51b7Smrg    MGAPtr pMga;
3128fe5e51b7Smrg    MGARamdacPtr MGAdac;
3129fe5e51b7Smrg    int ret;
3130fe5e51b7Smrg    VisualPtr visual;
3131fe5e51b7Smrg    unsigned char *FBStart;
3132fe5e51b7Smrg    int width, height, displayWidth;
3133fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
3134fe5e51b7Smrg    int f;
3135fe5e51b7Smrg    CARD32 VRTemp, FBTemp;
31360bb88ba4Smrg#ifdef MGADRI
3137fe5e51b7Smrg    MessageType driFrom = X_DEFAULT;
3138fe5e51b7Smrg#endif
3139fe5e51b7Smrg    DPMSSetProcPtr mga_dpms_set_proc = NULL;
3140fe5e51b7Smrg
3141fe5e51b7Smrg    hwp = VGAHWPTR(pScrn);
3142fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3143fe5e51b7Smrg    MGAdac = &pMga->Dac;
3144fe5e51b7Smrg
31450bb88ba4Smrg    if (pMga->is_G200SE)
31460bb88ba4Smrg    {
31470bb88ba4Smrg        VRTemp = pScrn->videoRam;
31480bb88ba4Smrg        FBTemp = pMga->FbMapSize;
31490bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
31500bb88ba4Smrg        {
31510bb88ba4Smrg            pScrn->videoRam = 16384;
31520bb88ba4Smrg        }
31530bb88ba4Smrg        else
31540bb88ba4Smrg        {
31550bb88ba4Smrg            pScrn->videoRam = 8192;
31560bb88ba4Smrg        }
31570bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
3158fe5e51b7Smrg    }
3159fe5e51b7Smrg
3160fe5e51b7Smrg
3161fe5e51b7Smrg    /* Map the MGA memory and MMIO areas */
3162fe5e51b7Smrg    if (!MGAMapMem(pScrn))
3163fe5e51b7Smrg	return FALSE;
3164fe5e51b7Smrg
3165fe5e51b7Smrg
3166fe5e51b7Smrg    /* Select functions that vary based on the CRTC configureation of the
3167fe5e51b7Smrg     * screen.
3168fe5e51b7Smrg     */
3169fe5e51b7Smrg    if (!pMga->MergedFB) {
3170fe5e51b7Smrg	if (pMga->SecondCrtc) {
3171fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSetCrtc2;
3172fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreenCrtc2;
3173fe5e51b7Smrg	}
3174fe5e51b7Smrg	else {
3175fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSet;
3176fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreen;
3177fe5e51b7Smrg	}
3178fe5e51b7Smrg    }
3179fe5e51b7Smrg    else {
3180fe5e51b7Smrg        pScreen->SaveScreen = MGASaveScreenMerged;
3181fe5e51b7Smrg	mga_dpms_set_proc = MGADisplayPowerManagementSetMerged;
3182fe5e51b7Smrg    }
3183fe5e51b7Smrg
3184fe5e51b7Smrg
3185fe5e51b7Smrg    if ((pMga->Chipset == PCI_CHIP_MGAG100)
3186fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
3187fe5e51b7Smrg        MGAG100BlackMagic(pScrn);
3188fe5e51b7Smrg
3189fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
3190fe5e51b7Smrg       DevUnion *pPriv;
3191fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3192fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3193fe5e51b7Smrg       pMgaEnt->refCount++;
3194fe5e51b7Smrg    } else {
3195fe5e51b7Smrg    }
3196fe5e51b7Smrg    if (pMga->is_G200SE) {
3197fe5e51b7Smrg	pScrn->videoRam = VRTemp;
3198fe5e51b7Smrg	pMga->FbMapSize = FBTemp;
3199fe5e51b7Smrg    }
3200fe5e51b7Smrg
3201fe5e51b7Smrg    /* Initialise the MMIO vgahw functions */
3202fe5e51b7Smrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
3203fe5e51b7Smrg    vgaHWGetIOBase(hwp);
3204fe5e51b7Smrg
3205fe5e51b7Smrg    /* Map the VGA memory when the primary video */
3206fe5e51b7Smrg    if (!pMga->FBDev) {
3207fe5e51b7Smrg	if (pMga->Primary) {
3208fe5e51b7Smrg	    hwp->MapSize = 0x10000;
3209fe5e51b7Smrg	    if (!vgaHWMapMem(pScrn))
3210fe5e51b7Smrg		return FALSE;
3211fe5e51b7Smrg	}
3212fe5e51b7Smrg
3213fe5e51b7Smrg	/* Save the current state */
3214fe5e51b7Smrg	MGASave(pScrn);
3215fe5e51b7Smrg	/* Initialise the first mode */
3216fe5e51b7Smrg	if (!MGAModeInit(pScrn, pScrn->currentMode))
3217fe5e51b7Smrg	    return FALSE;
3218fe5e51b7Smrg    }
3219fe5e51b7Smrg    else {
3220fe5e51b7Smrg	fbdevHWSave(pScrn);
3221fe5e51b7Smrg	/* Disable VGA core, and leave memory access on */
3222fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
3223fe5e51b7Smrg	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
3224fe5e51b7Smrg				  PCI_OPTION_REG);
3225fe5e51b7Smrg#else
3226fe5e51b7Smrg	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
3227fe5e51b7Smrg#endif
3228fe5e51b7Smrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode))
3229fe5e51b7Smrg	    return FALSE;
3230fe5e51b7Smrg
3231fe5e51b7Smrg        if (!pMga->SecondCrtc && pMga->HWCursor
3232fe5e51b7Smrg	    && pMga->chip_attribs->hwcursor_1064) {
3233fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_LOW, pMga->FbCursorOffset >> 10);
3234fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_HI, pMga->FbCursorOffset >> 18);
3235fe5e51b7Smrg	}
3236fe5e51b7Smrg
3237fe5e51b7Smrg	MGAStormEngineInit(pScrn);
3238fe5e51b7Smrg    }
3239fe5e51b7Smrg
3240fe5e51b7Smrg    /* Darken the screen for aesthetic reasons and set the viewport
3241fe5e51b7Smrg     */
3242fe5e51b7Smrg    (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
32430bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3244fe5e51b7Smrg
3245fe5e51b7Smrg
3246fe5e51b7Smrg    /*
3247fe5e51b7Smrg     * The next step is to setup the screen's visuals, and initialise the
3248fe5e51b7Smrg     * framebuffer code.  In cases where the framebuffer's default
3249fe5e51b7Smrg     * choices for things like visual layouts and bits per RGB are OK,
3250fe5e51b7Smrg     * this may be as simple as calling the framebuffer's ScreenInit()
3251fe5e51b7Smrg     * function.  If not, the visuals will need to be setup before calling
3252fe5e51b7Smrg     * a fb ScreenInit() function and fixed up after.
3253fe5e51b7Smrg     *
3254fe5e51b7Smrg     * For most PC hardware at depths >= 8, the defaults that cfb uses
3255fe5e51b7Smrg     * are not appropriate.  In this driver, we fixup the visuals after.
3256fe5e51b7Smrg     */
3257fe5e51b7Smrg
3258fe5e51b7Smrg    /*
3259fe5e51b7Smrg     * Reset the visual list.
3260fe5e51b7Smrg     */
3261fe5e51b7Smrg    miClearVisualTypes();
3262fe5e51b7Smrg
3263fe5e51b7Smrg    /* Setup the visuals we support. */
3264fe5e51b7Smrg
3265eda3803bSmrg    /* All MGA support DirectColor */
3266eda3803bSmrg    if (pMga->SecondCrtc) {
3267fe5e51b7Smrg	/* No DirectColor on the second head */
3268fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
3269fe5e51b7Smrg			      TrueColor))
3270fe5e51b7Smrg		return FALSE;
3271fe5e51b7Smrg	if (!miSetPixmapDepths ())
3272fe5e51b7Smrg	    return FALSE;
3273fe5e51b7Smrg    } else {
3274fe5e51b7Smrg	if (!xf86SetDefaultVisual(pScrn, -1))
3275fe5e51b7Smrg	    return FALSE;
3276fe5e51b7Smrg
3277fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth,
3278fe5e51b7Smrg			      miGetDefaultVisualMask(pScrn->depth),
3279fe5e51b7Smrg			      pScrn->rgbBits, pScrn->defaultVisual))
3280fe5e51b7Smrg	    return FALSE;
3281fe5e51b7Smrg	if (!miSetPixmapDepths ())
3282fe5e51b7Smrg	    return FALSE;
3283fe5e51b7Smrg    }
3284fe5e51b7Smrg
3285fe5e51b7Smrg    /*
3286fe5e51b7Smrg     * Call the framebuffer layer's ScreenInit function, and fill in other
3287fe5e51b7Smrg     * pScreen fields.
3288fe5e51b7Smrg     */
3289fe5e51b7Smrg
3290fe5e51b7Smrg    width = pScrn->virtualX;
3291fe5e51b7Smrg    height = pScrn->virtualY;
3292fe5e51b7Smrg    displayWidth = pScrn->displayWidth;
3293fe5e51b7Smrg
3294fe5e51b7Smrg
3295fe5e51b7Smrg    if(pMga->Rotate) {
3296fe5e51b7Smrg	height = pScrn->virtualX;
3297fe5e51b7Smrg	width = pScrn->virtualY;
3298fe5e51b7Smrg    }
3299fe5e51b7Smrg
3300fe5e51b7Smrg    if(pMga->ShadowFB) {
3301fe5e51b7Smrg 	pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
33020bb88ba4Smrg	pMga->ShadowPtr = malloc(pMga->ShadowPitch * height);
3303fe5e51b7Smrg	displayWidth = pMga->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3304fe5e51b7Smrg        FBStart = pMga->ShadowPtr;
3305fe5e51b7Smrg    } else {
3306fe5e51b7Smrg	pMga->ShadowPtr = NULL;
3307fe5e51b7Smrg	FBStart = pMga->FbStart;
3308fe5e51b7Smrg    }
3309fe5e51b7Smrg
33100bb88ba4Smrg#ifdef MGADRI
3311fe5e51b7Smrg     /*
3312eda3803bSmrg      * Setup DRI after visuals have been established.
3313eda3803bSmrg      *
3314fe5e51b7Smrg      * The DRI does not work when textured video is enabled at this time.
3315fe5e51b7Smrg      */
3316fe5e51b7Smrg    if (pMga->is_G200SE) {
3317fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3318fe5e51b7Smrg		   "Not supported by hardware, not initializing the DRI\n");
3319fe5e51b7Smrg	pMga->directRenderingEnabled = FALSE;
3320fe5e51b7Smrg	driFrom = X_PROBED;
3321fe5e51b7Smrg    } else if (!xf86ReturnOptValBool(pMga->Options, OPTION_DRI, TRUE)) {
3322fe5e51b7Smrg	driFrom = X_CONFIG;
3323fe5e51b7Smrg    } else if ( pMga->NoAccel ) {
3324fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3325fe5e51b7Smrg		   "Acceleration disabled, not initializing the DRI\n" );
3326fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3327fe5e51b7Smrg       driFrom = X_CONFIG;
3328fe5e51b7Smrg    }
3329fe5e51b7Smrg    else if ( pMga->TexturedVideo == TRUE ) {
3330fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3331fe5e51b7Smrg		   "Textured video enabled, not initializing the DRI\n" );
3332fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3333fe5e51b7Smrg       driFrom = X_CONFIG;
3334fe5e51b7Smrg    }
3335fe5e51b7Smrg    else if (pMga->SecondCrtc == TRUE) {
3336fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3337fe5e51b7Smrg		   "Not initializing the DRI on the second head\n" );
3338fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3339fe5e51b7Smrg    }
3340fe5e51b7Smrg    else if ((pMga->FbMapSize /
3341fe5e51b7Smrg	       (width * (pScrn->bitsPerPixel >> 3))) <= height * 3) {
3342fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3343fe5e51b7Smrg	  "Static buffer allocation failed, not initializing the DRI\n");
3344fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3345fe5e51b7Smrg	  "Need at least %d kB video memory at this resolution, bit depth\n",
3346fe5e51b7Smrg	  (3 * displayWidth * height * (pScrn->bitsPerPixel >> 3)) / 1024 );
3347fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3348fe5e51b7Smrg       driFrom = X_PROBED;
3349fe5e51b7Smrg    }
3350fe5e51b7Smrg    else {
3351fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIScreenInit(pScreen);
3352fe5e51b7Smrg    }
3353fe5e51b7Smrg#endif
3354fe5e51b7Smrg
3355fe5e51b7Smrg
3356eda3803bSmrg    if (!fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
3357eda3803bSmrg		      pScrn->yDpi, displayWidth, pScrn->bitsPerPixel)) {
3358fe5e51b7Smrg	return FALSE;
3359eda3803bSmrg    }
3360fe5e51b7Smrg
3361fe5e51b7Smrg
3362fe5e51b7Smrg    if (pScrn->bitsPerPixel > 8) {
3363fe5e51b7Smrg        /* Fixup RGB ordering */
3364fe5e51b7Smrg        visual = pScreen->visuals + pScreen->numVisuals;
3365fe5e51b7Smrg        while (--visual >= pScreen->visuals) {
3366fe5e51b7Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
3367fe5e51b7Smrg		visual->offsetRed = pScrn->offset.red;
3368fe5e51b7Smrg		visual->offsetGreen = pScrn->offset.green;
3369fe5e51b7Smrg		visual->offsetBlue = pScrn->offset.blue;
3370fe5e51b7Smrg		visual->redMask = pScrn->mask.red;
3371fe5e51b7Smrg		visual->greenMask = pScrn->mask.green;
3372fe5e51b7Smrg		visual->blueMask = pScrn->mask.blue;
3373fe5e51b7Smrg	    }
3374fe5e51b7Smrg	}
3375fe5e51b7Smrg    }
3376fe5e51b7Smrg
3377fe5e51b7Smrg    /* must be after RGB ordering fixed */
3378eda3803bSmrg    fbPictureInit (pScreen, 0, 0);
3379eda3803bSmrg
3380fe5e51b7Smrg    xf86SetBlackWhitePixels(pScreen);
3381fe5e51b7Smrg
3382fe5e51b7Smrg    pMga->BlockHandler = pScreen->BlockHandler;
3383fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
3384fe5e51b7Smrg
3385fe5e51b7Smrg    if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */
3386fe5e51b7Smrg	MGADGAInit(pScreen);
3387fe5e51b7Smrg
3388fe5e51b7Smrg    if (!pMga->NoAccel) {
3389fe5e51b7Smrg#ifdef USE_EXA
3390fe5e51b7Smrg	if (pMga->Exa)
3391fe5e51b7Smrg	    mgaExaInit(pScreen);
3392fe5e51b7Smrg	else
3393fe5e51b7Smrg#endif
3394fe5e51b7Smrg	    MGAStormAccelInit(pScreen);
3395fe5e51b7Smrg    }
3396fe5e51b7Smrg
3397fe5e51b7Smrg    xf86SetBackingStore(pScreen);
3398fe5e51b7Smrg    xf86SetSilkenMouse(pScreen);
3399fe5e51b7Smrg
3400fe5e51b7Smrg    /* Initialize software cursor.
3401fe5e51b7Smrg	Must precede creation of the default colormap */
3402fe5e51b7Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
3403fe5e51b7Smrg
3404fe5e51b7Smrg    /* Initialize HW cursor layer.
3405fe5e51b7Smrg	Must follow software cursor initialization*/
3406fe5e51b7Smrg    if (pMga->HWCursor) {
3407fe5e51b7Smrg	if(!MGAHWCursorInit(pScreen))
3408fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3409fe5e51b7Smrg		"Hardware cursor initialization failed\n");
3410fe5e51b7Smrg    }
3411fe5e51b7Smrg    if(pMga->MergedFB) {
3412fe5e51b7Smrg        /* Rotate and MergedFB are mutiualy exclusive, so we can use this
3413fe5e51b7Smrg         * variable.
3414fe5e51b7Smrg         */
3415fe5e51b7Smrg        if (!pMga->PointerMoved)
3416fe5e51b7Smrg            pMga->PointerMoved = pScrn->PointerMoved;
3417fe5e51b7Smrg        pScrn->PointerMoved = MGAMergePointerMoved;
3418fe5e51b7Smrg
3419fe5e51b7Smrg    }
3420fe5e51b7Smrg
3421fe5e51b7Smrg    /* Initialise default colourmap */
3422fe5e51b7Smrg    if (!miCreateDefColormap(pScreen))
3423fe5e51b7Smrg	return FALSE;
3424fe5e51b7Smrg
3425fe5e51b7Smrg    /* Initialize colormap layer.
3426fe5e51b7Smrg	Must follow initialization of the default colormap */
3427fe5e51b7Smrg    if (!pMga->SecondCrtc)
3428fe5e51b7Smrg	f = CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH;
3429fe5e51b7Smrg    else
3430fe5e51b7Smrg	f = CMAP_RELOAD_ON_MODE_SWITCH;
3431fe5e51b7Smrg    if(!xf86HandleColormaps(pScreen, 256, 8,
3432fe5e51b7Smrg	pMga->FBDev ? fbdevHWLoadPaletteWeak() : MGAdac->LoadPalette,
3433fe5e51b7Smrg	NULL, f))
3434fe5e51b7Smrg	return FALSE;
3435fe5e51b7Smrg
3436fe5e51b7Smrg    if(pMga->ShadowFB) {
3437fe5e51b7Smrg	RefreshAreaFuncPtr refreshArea = MGARefreshArea;
3438fe5e51b7Smrg
3439fe5e51b7Smrg	if(pMga->Rotate) {
3440fe5e51b7Smrg	    if (!pMga->PointerMoved) {
3441fe5e51b7Smrg	    pMga->PointerMoved = pScrn->PointerMoved;
3442fe5e51b7Smrg	    pScrn->PointerMoved = MGAPointerMoved;
3443fe5e51b7Smrg	    }
3444fe5e51b7Smrg
3445fe5e51b7Smrg	   switch(pScrn->bitsPerPixel) {
3446fe5e51b7Smrg	   case 8:	refreshArea = MGARefreshArea8;	break;
3447fe5e51b7Smrg	   case 16:	refreshArea = MGARefreshArea16;	break;
3448fe5e51b7Smrg	   case 24:	refreshArea = MGARefreshArea24;	break;
3449fe5e51b7Smrg	   case 32:	refreshArea = MGARefreshArea32;	break;
3450fe5e51b7Smrg	   }
3451fe5e51b7Smrg	}
3452fe5e51b7Smrg
3453fe5e51b7Smrg	ShadowFBInit(pScreen, refreshArea);
3454fe5e51b7Smrg    }
3455fe5e51b7Smrg
3456fe5e51b7Smrg    xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
3457fe5e51b7Smrg
3458fe5e51b7Smrg    pScrn->memPhysBase = pMga->FbAddress;
3459fe5e51b7Smrg    pScrn->fbOffset = pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
3460fe5e51b7Smrg
3461fe5e51b7Smrg    MGAInitVideo(pScreen);
3462fe5e51b7Smrg
34630bb88ba4Smrg#ifdef MGADRI
3464fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3465eda3803bSmrg       /* Now that mi, drm and others have done their thing,
3466fe5e51b7Smrg	* complete the DRI setup.
3467fe5e51b7Smrg	*/
3468fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIFinishScreenInit(pScreen);
3469fe5e51b7Smrg    }
3470fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3471fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
3472fe5e51b7Smrg    } else {
3473fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
3474fe5e51b7Smrg    }
3475fe5e51b7Smrg    if (pMga->DualHeadEnabled && pMga->SecondCrtc == FALSE)
3476fe5e51b7Smrg	pMgaEnt->directRenderingEnabled = pMga->directRenderingEnabled;
3477fe5e51b7Smrg    pMga->haveQuiescense = 1;
3478fe5e51b7Smrg#endif
3479fe5e51b7Smrg
3480fe5e51b7Smrg    /* Wrap the current CloseScreen function */
3481fe5e51b7Smrg    pMga->CloseScreen = pScreen->CloseScreen;
3482fe5e51b7Smrg    pScreen->CloseScreen = MGACloseScreen;
3483fe5e51b7Smrg
3484fe5e51b7Smrg    /* Report any unused options (only for the first generation) */
3485fe5e51b7Smrg    if (serverGeneration == 1) {
3486fe5e51b7Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3487fe5e51b7Smrg    }
3488fe5e51b7Smrg
3489fe5e51b7Smrg    /* For the second head, work around display problem. */
3490fe5e51b7Smrg    if (!pMga->MergedFB && pMga->SecondCrtc) {
3491fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3492fe5e51b7Smrg    }
3493fe5e51b7Smrg
3494fe5e51b7Smrg    /* Done */
3495fe5e51b7Smrg    return TRUE;
3496fe5e51b7Smrg}
3497fe5e51b7Smrg
3498fe5e51b7Smrg
3499fe5e51b7Smrg/* Usually mandatory */
3500fe5e51b7SmrgBool
35010bb88ba4SmrgMGASwitchMode(SWITCH_MODE_ARGS_DECL)
3502fe5e51b7Smrg{
35030bb88ba4Smrg    SCRN_INFO_PTR(arg);
3504fe5e51b7Smrg    if  (mode->Flags & 0x80000000) {
3505fe5e51b7Smrg 	return FALSE;
3506fe5e51b7Smrg    }   else
35070bb88ba4Smrg	return MGAModeInit(pScrn, mode);
3508fe5e51b7Smrg}
3509fe5e51b7Smrg
3510fe5e51b7Smrg /* Adjusts coordinates to match Panning granularity.
3511fe5e51b7Smrg  * does nothing if the HALlib is not loaded
3512fe5e51b7Smrg  */
3513fe5e51b7Smrgvoid
3514fe5e51b7SmrgMGAAdjustGranularity(ScrnInfoPtr pScrn, int* x, int* y)
3515fe5e51b7Smrg{
3516fe5e51b7Smrg}
3517fe5e51b7Smrg
3518fe5e51b7Smrg
3519fe5e51b7Smrg/*
3520fe5e51b7Smrg * This function is used to initialize the Start Address - the first
3521fe5e51b7Smrg * displayed location in the video memory.
3522fe5e51b7Smrg */
3523fe5e51b7Smrg/* Usually mandatory */
3524fe5e51b7Smrgvoid
35250bb88ba4SmrgMGAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
3526fe5e51b7Smrg{
35270bb88ba4Smrg    SCRN_INFO_PTR(arg);
3528493f84f4Smrg    int Base, tmp, count, last_vcount;
3529fe5e51b7Smrg
3530fe5e51b7Smrg    MGAFBLayout *pLayout;
3531fe5e51b7Smrg    MGAPtr pMga;
3532fe5e51b7Smrg
3533fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3534fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3535fe5e51b7Smrg
3536fe5e51b7Smrg        /* wanted to improve panning granularity problems without risking
3537fe5e51b7Smrg         * compatibility issues. Existing code looked hardware dependent.
3538fe5e51b7Smrg         */
3539fe5e51b7Smrg    MGA_NOT_HAL(
3540fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3541fe5e51b7Smrg            y += pScrn->virtualY - 1;
3542fe5e51b7Smrg
3543fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x + pMga->YDstOrg) >>
3544fe5e51b7Smrg                    (3 - pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]);
3545fe5e51b7Smrg
3546fe5e51b7Smrg        if (pLayout->bitsPerPixel == 24) {
3547fe5e51b7Smrg            if (pMga->Chipset == PCI_CHIP_MGAG400
3548fe5e51b7Smrg                || pMga->Chipset == PCI_CHIP_MGAG550)
3549fe5e51b7Smrg                Base &= ~1;  /*1 Not sure why */
3550fe5e51b7Smrg
3551fe5e51b7Smrg            Base *= 3;
3552fe5e51b7Smrg        }
3553fe5e51b7Smrg
3554fe5e51b7Smrg        /* find start of retrace */
3555fe5e51b7Smrg        while (INREG8(0x1FDA) & 0x08);
3556fe5e51b7Smrg        while (!(INREG8(0x1FDA) & 0x08));
3557fe5e51b7Smrg        /* wait until we're past the start (fixseg.c in the DDK) */
3558493f84f4Smrg        last_vcount = INREG(MGAREG_VCOUNT);
3559493f84f4Smrg        count = last_vcount + 2;
3560493f84f4Smrg        while (1) {
3561493f84f4Smrg           int vcount = INREG(MGAREG_VCOUNT);
3562493f84f4Smrg           if (vcount >= count) break;
3563493f84f4Smrg           if (vcount < last_vcount) break;
3564493f84f4Smrg           last_vcount = vcount;
3565493f84f4Smrg        }
3566fe5e51b7Smrg
3567fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, (Base & 0x00FF00) | 0x0C);
3568fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, ((Base & 0x0000FF) << 8) | 0x0D);
3569fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_INDEX, 0x00);
3570fe5e51b7Smrg        tmp = INREG8(MGAREG_CRTCEXT_DATA);
3571fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_DATA, (tmp & 0xF0) | ((Base & 0x0F0000) >> 16));
3572fe5e51b7Smrg    );
3573fe5e51b7Smrg
3574fe5e51b7Smrg}
3575fe5e51b7Smrg
3576fe5e51b7Smrgvoid
35770bb88ba4SmrgMGAAdjustFrameCrtc2(ADJUST_FRAME_ARGS_DECL)
3578fe5e51b7Smrg{
35790bb88ba4Smrg    SCRN_INFO_PTR(arg);
3580fe5e51b7Smrg    int Base;
3581fe5e51b7Smrg    MGAFBLayout *pLayout;
3582fe5e51b7Smrg    MGAPtr pMga;
3583fe5e51b7Smrg
3584fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3585fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3586fe5e51b7Smrg    MGA_NOT_HAL(
3587fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3588fe5e51b7Smrg            y += pScrn->virtualY - 1;
3589fe5e51b7Smrg
3590fe5e51b7Smrg        /* 3-85 c2offset
3591fe5e51b7Smrg            * 3-93 c2startadd0
3592fe5e51b7Smrg            * 3-96 c2vcount
3593fe5e51b7Smrg            */
3594fe5e51b7Smrg
3595fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x) * pLayout->bitsPerPixel >> 3;
3596fe5e51b7Smrg        Base += pMga->DstOrg;
3597fe5e51b7Smrg        Base &= 0x01ffffc0;
3598fe5e51b7Smrg        OUTREG(MGAREG_C2STARTADD0, Base);
3599fe5e51b7Smrg    );
3600fe5e51b7Smrg}
3601fe5e51b7Smrg
3602fe5e51b7Smrg/*
3603fe5e51b7Smrg * This is called when VT switching back to the X server.  Its job is
3604fe5e51b7Smrg * to reinitialise the video mode.
3605fe5e51b7Smrg *
3606fe5e51b7Smrg * We may wish to unmap video/MMIO memory too.
3607fe5e51b7Smrg */
3608fe5e51b7Smrg
3609fe5e51b7Smrg/* Mandatory */
3610fe5e51b7Smrgstatic Bool
36110bb88ba4SmrgMGAEnterVT(VT_FUNC_ARGS_DECL)
3612fe5e51b7Smrg{
36130bb88ba4Smrg    SCRN_INFO_PTR(arg);
3614fe5e51b7Smrg    MGAPtr pMga;
3615fe5e51b7Smrg
3616fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3617fe5e51b7Smrg
36180bb88ba4Smrg#ifdef MGADRI
3619fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3620fe5e51b7Smrg	if (pMga->irq) {
3621fe5e51b7Smrg	    /* Need to make sure interrupts are enabled */
3622fe5e51b7Smrg	    OUTREG(MGAREG_IEN, pMga->reg_ien);
3623fe5e51b7Smrg	}
36240bb88ba4Smrg        DRIUnlock(xf86ScrnToScreen(pScrn));
3625fe5e51b7Smrg    }
3626fe5e51b7Smrg#endif
3627fe5e51b7Smrg
3628fe5e51b7Smrg    if (!MGAModeInit(pScrn, pScrn->currentMode))
3629fe5e51b7Smrg	return FALSE;
36300bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3631fe5e51b7Smrg
3632fe5e51b7Smrg    /* For the second head, work around display problem. */
3633fe5e51b7Smrg   if (pMga->SecondCrtc) {
3634fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3635fe5e51b7Smrg    }
3636fe5e51b7Smrg
3637fe5e51b7Smrg    return TRUE;
3638fe5e51b7Smrg}
3639fe5e51b7Smrg
3640fe5e51b7Smrgstatic Bool
36410bb88ba4SmrgMGAEnterVTFBDev(VT_FUNC_ARGS_DECL)
3642fe5e51b7Smrg{
36430bb88ba4Smrg    SCRN_INFO_PTR(arg);
36440bb88ba4Smrg#ifdef MGADRI
3645fe5e51b7Smrg    ScreenPtr pScreen;
3646fe5e51b7Smrg    MGAPtr pMga;
3647fe5e51b7Smrg
3648fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3649fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
36500bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3651fe5e51b7Smrg        DRIUnlock(pScreen);
3652fe5e51b7Smrg    }
3653fe5e51b7Smrg#endif
3654fe5e51b7Smrg
36550bb88ba4Smrg    fbdevHWEnterVT(VT_FUNC_ARGS);
3656fe5e51b7Smrg    MGAStormEngineInit(pScrn);
3657fe5e51b7Smrg    return TRUE;
3658fe5e51b7Smrg}
3659fe5e51b7Smrg
3660fe5e51b7Smrg#define RESTORE_TEXTMODE_ON_DVI(x)                      \
3661fe5e51b7Smrg    if (MGAISGx50(x) &&                                 \
3662fe5e51b7Smrg       (ISDIGITAL1(x) || ISDIGITAL2(x))) {              \
3663fe5e51b7Smrg        /* Reset DUALDVI register */                    \
3664fe5e51b7Smrg        outMGAdac(MGA1064_DVI_PIPE_CTL, 0x0);           \
3665fe5e51b7Smrg        /* Set Panel mode between 20 and 54 MHz */      \
3666fe5e51b7Smrg        outMGAdac(MGA1064_PAN_CTL, 0x7);                \
3667fe5e51b7Smrg    }
3668fe5e51b7Smrg
3669fe5e51b7Smrg
3670fe5e51b7Smrg/*
3671fe5e51b7Smrg * This is called when VT switching away from the X server.  Its job is
3672fe5e51b7Smrg * to restore the previous (text) mode.
3673fe5e51b7Smrg *
3674fe5e51b7Smrg * We may wish to remap video/MMIO memory too.
3675fe5e51b7Smrg */
3676fe5e51b7Smrg
3677fe5e51b7Smrg/* Mandatory */
3678fe5e51b7Smrgstatic void
36790bb88ba4SmrgMGALeaveVT(VT_FUNC_ARGS_DECL)
3680fe5e51b7Smrg{
36810bb88ba4Smrg    SCRN_INFO_PTR(arg);
3682fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
36830bb88ba4Smrg#ifdef MGADRI
3684fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3685fe5e51b7Smrg    ScreenPtr pScreen;
3686fe5e51b7Smrg#endif
3687fe5e51b7Smrg
3688fe5e51b7Smrg    MGARestore(pScrn);
3689fe5e51b7Smrg    vgaHWLock(hwp);
3690fe5e51b7Smrg
36910bb88ba4Smrg#ifdef MGADRI
3692fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
36930bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3694fe5e51b7Smrg        DRILock(pScreen, 0);
3695fe5e51b7Smrg    }
3696fe5e51b7Smrg#endif
3697fe5e51b7Smrg}
3698fe5e51b7Smrg
3699fe5e51b7Smrg
3700fe5e51b7Smrg/*
3701fe5e51b7Smrg * This is called at the end of each server generation.  It restores the
3702fe5e51b7Smrg * original (text) mode.  It should also unmap the video memory, and free
3703fe5e51b7Smrg * any per-generation data allocated by the driver.  It should finish
3704fe5e51b7Smrg * by unwrapping and calling the saved CloseScreen function.
3705fe5e51b7Smrg */
3706fe5e51b7Smrg
3707fe5e51b7Smrg/* Mandatory */
3708fe5e51b7Smrgstatic Bool
37090bb88ba4SmrgMGACloseScreen(CLOSE_SCREEN_ARGS_DECL)
3710fe5e51b7Smrg{
37110bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3712fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3713fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3714fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
37150bb88ba4Smrg    CARD32 VRTemp, FBTemp;
3716fe5e51b7Smrg
3717fe5e51b7Smrg    if (pMga->MergedFB)
37180bb88ba4Smrg         MGACloseScreenMerged(pScreen);
37190bb88ba4Smrg
37200bb88ba4Smrg    if (pMga->is_G200SE)
37210bb88ba4Smrg    {
37220bb88ba4Smrg        VRTemp = pScrn->videoRam;
37230bb88ba4Smrg        FBTemp = pMga->FbMapSize;
37240bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
37250bb88ba4Smrg        {
37260bb88ba4Smrg            pScrn->videoRam = 16384;
37270bb88ba4Smrg        }
37280bb88ba4Smrg        else
37290bb88ba4Smrg        {
37300bb88ba4Smrg            pScrn->videoRam = 8192;
37310bb88ba4Smrg        }
37320bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
37330bb88ba4Smrg    }
3734fe5e51b7Smrg
3735fe5e51b7Smrg    if (pScrn->vtSema) {
3736fe5e51b7Smrg	if (pMga->FBDev) {
3737fe5e51b7Smrg	    fbdevHWRestore(pScrn);
3738fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3739fe5e51b7Smrg        } else {
3740fe5e51b7Smrg	    MGARestore(pScrn);
3741fe5e51b7Smrg	    vgaHWLock(hwp);
3742fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3743fe5e51b7Smrg	    vgaHWUnmapMem(pScrn);
3744fe5e51b7Smrg	}
3745fe5e51b7Smrg    }
37460bb88ba4Smrg
37470bb88ba4Smrg    if (pMga->is_G200SE)
37480bb88ba4Smrg    {
37490bb88ba4Smrg        pScrn->videoRam = VRTemp;
37500bb88ba4Smrg        pMga->FbMapSize = FBTemp;
37510bb88ba4Smrg    }
37520bb88ba4Smrg
37530bb88ba4Smrg#ifdef MGADRI
3754fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
3755fe5e51b7Smrg       MGADRICloseScreen(pScreen);
3756fe5e51b7Smrg       pMga->directRenderingEnabled=FALSE;
3757fe5e51b7Smrg   }
3758fe5e51b7Smrg#endif
3759fe5e51b7Smrg
3760fe5e51b7Smrg   if (pMga->DualHeadEnabled) {
3761fe5e51b7Smrg       DevUnion *pPriv;
3762fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3763fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3764fe5e51b7Smrg       pMgaEnt->refCount--;
3765fe5e51b7Smrg   }
3766fe5e51b7Smrg
3767acd6767fSmrg#ifdef USE_XAA
3768fe5e51b7Smrg    if (pMga->AccelInfoRec)
3769fe5e51b7Smrg	XAADestroyInfoRec(pMga->AccelInfoRec);
3770fe5e51b7Smrg#endif
3771fe5e51b7Smrg#ifdef USE_EXA
3772fe5e51b7Smrg    if (pMga->ExaDriver) {
3773fe5e51b7Smrg	exaDriverFini(pScreen);
37740bb88ba4Smrg	free(pMga->ExaDriver);
3775fe5e51b7Smrg    }
3776fe5e51b7Smrg#endif
3777fe5e51b7Smrg    if (pMga->CursorInfoRec)
3778fe5e51b7Smrg    	xf86DestroyCursorInfoRec(pMga->CursorInfoRec);
37790bb88ba4Smrg    free(pMga->ShadowPtr);
37800bb88ba4Smrg    free(pMga->DGAModes);
37810bb88ba4Smrg    free(pMga->adaptor);
37820bb88ba4Smrg    free(pMga->portPrivate);
37830bb88ba4Smrg    free(pMga->ScratchBuffer);
3784fe5e51b7Smrg
3785fe5e51b7Smrg    pScrn->vtSema = FALSE;
3786fe5e51b7Smrg
3787fe5e51b7Smrg    xf86ClearPrimInitDone(pScrn->entityList[0]);
3788fe5e51b7Smrg
3789fe5e51b7Smrg    if(pMga->BlockHandler)
3790fe5e51b7Smrg	pScreen->BlockHandler = pMga->BlockHandler;
3791fe5e51b7Smrg
3792fe5e51b7Smrg    pScreen->CloseScreen = pMga->CloseScreen;
3793fe5e51b7Smrg
37940bb88ba4Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3795fe5e51b7Smrg}
3796fe5e51b7Smrg
3797fe5e51b7Smrg
3798fe5e51b7Smrg/* Free up any persistent data structures */
3799fe5e51b7Smrg
3800fe5e51b7Smrg/* Optional */
3801fe5e51b7Smrgstatic void
38020bb88ba4SmrgMGAFreeScreen(FREE_SCREEN_ARGS_DECL)
3803fe5e51b7Smrg{
38040bb88ba4Smrg    SCRN_INFO_PTR(arg);
3805fe5e51b7Smrg    /*
3806fe5e51b7Smrg     * This only gets called when a screen is being deleted.  It does not
3807fe5e51b7Smrg     * get called routinely at the end of a server generation.
3808fe5e51b7Smrg     */
3809fe5e51b7Smrg    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
38100bb88ba4Smrg        vgaHWFreeHWRec(pScrn);
38110bb88ba4Smrg    MGAFreeRec(pScrn);
3812fe5e51b7Smrg
3813fe5e51b7Smrg}
3814fe5e51b7Smrg
3815eda3803bSmrg#ifndef HAVE_XF86MODEBANDWIDTH
3816eda3803bSmrg
3817eda3803bSmrg#define MODE_BANDWIDTH MODE_BAD
3818eda3803bSmrg
3819eda3803bSmrg/** Calculates the memory bandwidth (in MiB/sec) of a mode. */
3820eda3803bSmrgstatic unsigned int
3821eda3803bSmrgxf86ModeBandwidth(DisplayModePtr mode, int depth)
3822eda3803bSmrg{
3823eda3803bSmrg    float a_active, a_total, active_percent, pixels_per_second;
3824eda3803bSmrg    int bytes_per_pixel = (depth + 7) / 8;
3825eda3803bSmrg
3826eda3803bSmrg    if (!mode->HTotal || !mode->VTotal || !mode->Clock)
3827eda3803bSmrg	return 0;
3828eda3803bSmrg
3829eda3803bSmrg    a_active = mode->HDisplay * mode->VDisplay;
3830eda3803bSmrg    a_total = mode->HTotal * mode->VTotal;
3831eda3803bSmrg    active_percent = a_active / a_total;
3832eda3803bSmrg    pixels_per_second = active_percent * mode->Clock * 1000.0;
3833eda3803bSmrg
3834eda3803bSmrg    return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024));
3835eda3803bSmrg}
3836eda3803bSmrg#endif
3837fe5e51b7Smrg
3838fe5e51b7Smrg/* Checks if a mode is suitable for the selected chipset. */
3839fe5e51b7Smrg
3840fe5e51b7Smrg/* Optional */
3841fe5e51b7Smrgstatic ModeStatus
38420bb88ba4SmrgMGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
3843fe5e51b7Smrg{
38440bb88ba4Smrg    SCRN_INFO_PTR(arg);
3845fe5e51b7Smrg    int lace;
3846fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3847fe5e51b7Smrg
3848fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI) {
38490bb88ba4Smrg    	if (pMga->reg_1e24 == 0x01) {
38500bb88ba4Smrg	        if (mode->HDisplay > 1600)
38510bb88ba4Smrg	            return MODE_VIRTUAL_X;
38520bb88ba4Smrg	        if (mode->VDisplay > 1200)
38530bb88ba4Smrg	            return MODE_VIRTUAL_Y;
38540bb88ba4Smrg	        if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 244)
38550bb88ba4Smrg	            return MODE_BANDWIDTH;
38560bb88ba4Smrg        } else {
38576f68ce78Smrg            if (pMga->reg_1e24 == 0x02) {
38580bb88ba4Smrg	            if (mode->HDisplay > 1920)
38590bb88ba4Smrg	                return MODE_VIRTUAL_X;
38600bb88ba4Smrg	            if (mode->VDisplay > 1200)
38610bb88ba4Smrg	                return MODE_VIRTUAL_Y;
38620bb88ba4Smrg	            if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 301)
38630bb88ba4Smrg	                return MODE_BANDWIDTH;
38640bb88ba4Smrg            }
38650bb88ba4Smrg        }
3866eda3803bSmrg    } else if (pMga->is_G200WB){
3867eda3803bSmrg        if (mode->Flags & V_DBLSCAN)
3868eda3803bSmrg            return MODE_NO_DBLESCAN;
38696f68ce78Smrg        if (pMga->Chipset != PCI_CHIP_MGAG200_EW3_PCI)
38706f68ce78Smrg        {
38716f68ce78Smrg	    if (pMga->KVM && mode->HDisplay > 1280)
38726f68ce78Smrg	        return MODE_VIRTUAL_X;
38736f68ce78Smrg	    if (pMga->KVM && mode->VDisplay > 1024)
38746f68ce78Smrg	        return MODE_VIRTUAL_Y;
38756f68ce78Smrg	    if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 318.77)
38766f68ce78Smrg	        return MODE_BANDWIDTH;
38776f68ce78Smrg        }
3878eda3803bSmrg    } else if (pMga->is_G200EV
3879eda3803bSmrg	       && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 327)) {
38800bb88ba4Smrg	return MODE_BANDWIDTH;
3881a31a186aSmrg    } else if (pMga->is_G200EH
3882a31a186aSmrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 375)) {
3883a31a186aSmrg        return MODE_BANDWIDTH;
38840bb88ba4Smrg    } else if (pMga->is_G200ER
38850bb88ba4Smrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 550)) {
38860bb88ba4Smrg        return MODE_BANDWIDTH;
3887fe5e51b7Smrg    }
3888fe5e51b7Smrg
3889fe5e51b7Smrg    lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
3890fe5e51b7Smrg
3891fe5e51b7Smrg    if ((mode->CrtcHDisplay <= 2048) &&
3892fe5e51b7Smrg	(mode->CrtcHSyncStart <= 4096) &&
3893fe5e51b7Smrg	(mode->CrtcHSyncEnd <= 4096) &&
3894fe5e51b7Smrg	(mode->CrtcHTotal <= 4096) &&
3895fe5e51b7Smrg	(mode->CrtcVDisplay <= 2048 * lace) &&
3896fe5e51b7Smrg	(mode->CrtcVSyncStart <= 4096 * lace) &&
3897fe5e51b7Smrg	(mode->CrtcVSyncEnd <= 4096 * lace) &&
3898fe5e51b7Smrg	(mode->CrtcVTotal <= 4096 * lace)) {
3899fe5e51b7Smrg
3900fe5e51b7Smrg	/* Can't have horizontal panning for second head of G400 */
3901fe5e51b7Smrg	if (pMga->SecondCrtc) {
3902fe5e51b7Smrg	    if (flags == MODECHECK_FINAL) {
3903fe5e51b7Smrg		if (pMga->allowedWidth == 0)
3904fe5e51b7Smrg		    pMga->allowedWidth = pScrn->virtualX;
3905fe5e51b7Smrg		if (mode->HDisplay != pMga->allowedWidth)
3906fe5e51b7Smrg		    return(MODE_ONE_WIDTH);
3907fe5e51b7Smrg	    }
3908fe5e51b7Smrg	}
3909fe5e51b7Smrg
3910fe5e51b7Smrg	return(MODE_OK);
3911fe5e51b7Smrg    } else {
3912fe5e51b7Smrg	return(MODE_BAD);
3913fe5e51b7Smrg    }
3914fe5e51b7Smrg}
3915fe5e51b7Smrg
3916fe5e51b7Smrg
3917fe5e51b7Smrg/*
3918fe5e51b7Smrg * This routine is required but since we can't easily blank the
3919fe5e51b7Smrg * second display without risking powering off the monitor, return
3920fe5e51b7Smrg * FALSE and let the X server do something generic.
3921fe5e51b7Smrg */
3922fe5e51b7Smrgstatic Bool
3923fe5e51b7SmrgMGASaveScreenCrtc2(ScreenPtr pScreen, int mode)
3924fe5e51b7Smrg{
3925fe5e51b7Smrg    return FALSE;
3926fe5e51b7Smrg}
3927fe5e51b7Smrg
3928fe5e51b7Smrg/* Do screen blanking */
3929fe5e51b7Smrg
3930fe5e51b7Smrgstatic Bool
3931fe5e51b7SmrgMGASaveScreen(ScreenPtr pScreen, int mode)
3932fe5e51b7Smrg{
3933fe5e51b7Smrg    return vgaHWSaveScreen(pScreen, mode);
3934fe5e51b7Smrg}
3935fe5e51b7Smrg
3936fe5e51b7Smrg
3937fe5e51b7Smrg/*
3938fe5e51b7Smrg * MGADisplayPowerManagementSet --
3939fe5e51b7Smrg *
3940fe5e51b7Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode.
3941fe5e51b7Smrg *
3942fe5e51b7Smrg * XXX This needs fixing for sync-on-green!
3943fe5e51b7Smrg */
3944fe5e51b7Smrgvoid
3945fe5e51b7SmrgMGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
3946fe5e51b7Smrg			     int flags)
3947fe5e51b7Smrg{
3948fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
3949fe5e51b7Smrg	unsigned char seq1 = 0, crtcext1 = 0;
3950fe5e51b7Smrg
3951fe5e51b7Smrg	switch (PowerManagementMode)
3952fe5e51b7Smrg	{
3953fe5e51b7Smrg	case DPMSModeOn:
3954fe5e51b7Smrg	    /* Screen: On; HSync: On, VSync: On */
3955fe5e51b7Smrg	    seq1 = 0x00;
3956fe5e51b7Smrg	    crtcext1 = 0x00;
3957fe5e51b7Smrg	    break;
3958fe5e51b7Smrg	case DPMSModeStandby:
3959fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: On */
3960fe5e51b7Smrg	    seq1 = 0x20;
3961fe5e51b7Smrg	    crtcext1 = 0x10;
3962fe5e51b7Smrg	    break;
3963fe5e51b7Smrg	case DPMSModeSuspend:
3964fe5e51b7Smrg	    /* Screen: Off; HSync: On, VSync: Off */
3965fe5e51b7Smrg	    seq1 = 0x20;
3966fe5e51b7Smrg	    crtcext1 = 0x20;
3967fe5e51b7Smrg	    break;
3968fe5e51b7Smrg	case DPMSModeOff:
3969fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: Off */
3970fe5e51b7Smrg	    seq1 = 0x20;
3971fe5e51b7Smrg	    crtcext1 = 0x30;
3972fe5e51b7Smrg	    break;
3973fe5e51b7Smrg	}
3974fe5e51b7Smrg
3975fe5e51b7Smrg	/* XXX Prefer an implementation that doesn't depend on VGA specifics */
3976fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
3977fe5e51b7Smrg	seq1 |= INREG8(MGAREG_SEQ_DATA) & ~0x20;
3978fe5e51b7Smrg	MGAWAITVSYNC();
3979fe5e51b7Smrg	MGAWAITBUSY();
3980fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_DATA, seq1);
3981fe5e51b7Smrg	usleep(20000);
3982fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);	/* Select CRTCEXT1 */
3983fe5e51b7Smrg	crtcext1 |= INREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
3984fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1);
3985fe5e51b7Smrg}
3986fe5e51b7Smrg
3987fe5e51b7Smrg
3988fe5e51b7Smrgvoid
3989fe5e51b7SmrgMGADisplayPowerManagementSetCrtc2(ScrnInfoPtr pScrn, int PowerManagementMode,
3990fe5e51b7Smrg				  int flags)
3991fe5e51b7Smrg{
3992fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
3993fe5e51b7Smrg	CARD32 val = INREG(MGAREG_C2CTL);
3994fe5e51b7Smrg
3995fe5e51b7Smrg	if (PowerManagementMode==DPMSModeOn) {
3996fe5e51b7Smrg		/* Enable CRTC2 */
3997fe5e51b7Smrg		val |= MGAREG_C2CTL_C2_EN;
3998fe5e51b7Smrg		val &= ~MGAREG_C2CTL_PIXCLKDIS_DISABLE;
3999fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
4000fe5e51b7Smrg		/* Restore normal MAVEN values */
4001fe5e51b7Smrg		if (pMga->Maven) {
4002fe5e51b7Smrg			/* if TV MODE -- for later implementation
4003fe5e51b7Smrg				MAVW(MONEN, 0xb3);
4004fe5e51b7Smrg				MAVW(MONSET, 0x20);
4005fe5e51b7Smrg				MAVW(OUTMODE, 0x08);    output: SVideo/Composite
4006fe5e51b7Smrg			        MAVW(STABLE, 0x02);             makes picture stable?
4007fe5e51b7Smrg				fixme? linux uses 0x14...
4008fe5e51b7Smrg				MAVW(TEST, (MAVR(TEST) & 0x10));
4009fe5e51b7Smrg
4010fe5e51b7Smrg			 */
4011fe5e51b7Smrg			/* else monitor mode */
4012fe5e51b7Smrg
4013fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONEN, 0xb2);
4014fe5e51b7Smrg			/* must be set to this in monitor mode */
4015fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONSET, 0x20);
4016fe5e51b7Smrg			/* output: monitor mode */
4017fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x03);
4018fe5e51b7Smrg			/* makes picture stable? */
4019fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x22);
4020fe5e51b7Smrg			/* turn off test signal */
4021fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x00);
4022fe5e51b7Smrg		}
4023fe5e51b7Smrg	}
4024fe5e51b7Smrg	else {
4025fe5e51b7Smrg		/* Disable CRTC2 video */
4026fe5e51b7Smrg		val |= MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4027fe5e51b7Smrg		val &= ~MGAREG_C2CTL_C2_EN;
4028fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
4029fe5e51b7Smrg
4030fe5e51b7Smrg		/* Disable MAVEN display */
4031fe5e51b7Smrg		if (pMga->Maven) {
4032fe5e51b7Smrg		/* In order to blank the 2nd display, we must set some MAVEN registers.
4033fe5e51b7Smrg		 * It seems that not always the same values work on different hardware so
4034fe5e51b7Smrg		 * we try a few different (possibly redundant) ones. */
4035fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x6a); */
4036fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x03); */
4037fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x10); */
4038fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x80);
4039fe5e51b7Smrg		}
4040fe5e51b7Smrg
4041fe5e51b7Smrg	}
4042fe5e51b7Smrg}
4043fe5e51b7Smrg
4044fe5e51b7Smrg
4045fe5e51b7Smrgstatic void
40460bb88ba4SmrgMGABlockHandler (BLOCKHANDLER_ARGS_DECL)
40470bb88ba4Smrg{
40480bb88ba4Smrg    SCREEN_PTR(arg);
40490bb88ba4Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
4050fe5e51b7Smrg    MGAPtr         pMga = MGAPTR(pScrn);
4051fe5e51b7Smrg
4052fe5e51b7Smrg    if(pMga->PaletteLoadCallback)
4053fe5e51b7Smrg	(*pMga->PaletteLoadCallback)(pScrn);
4054fe5e51b7Smrg
4055fe5e51b7Smrg    pScreen->BlockHandler = pMga->BlockHandler;
40560bb88ba4Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
4057fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
4058fe5e51b7Smrg
4059fe5e51b7Smrg    if(pMga->VideoTimerCallback) {
4060fe5e51b7Smrg	UpdateCurrentTime();
4061fe5e51b7Smrg	(*pMga->VideoTimerCallback)(pScrn, currentTime.milliseconds);
4062fe5e51b7Smrg    }
4063fe5e51b7Smrg
4064fe5e51b7Smrg    if(pMga->RenderCallback)
4065fe5e51b7Smrg	(*pMga->RenderCallback)(pScrn);
4066fe5e51b7Smrg}
4067fe5e51b7Smrg
4068fe5e51b7Smrg#if defined (EXTRADEBUG)
4069fe5e51b7Smrg/*
4070fe5e51b7Smrg * some functions to track input/output in the server
4071fe5e51b7Smrg */
4072fe5e51b7Smrg
4073fe5e51b7SmrgCARD8
4074fe5e51b7SmrgMGAdbg_inreg8(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4075fe5e51b7Smrg{
4076fe5e51b7Smrg    CARD8 ret;
4077fe5e51b7Smrg
4078fe5e51b7Smrg    ret = MMIO_IN8(MGAPTR(pScrn)->IOBase,addr);
4079fe5e51b7Smrg    if(verbose)
4080fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4081fe5e51b7Smrg			"inreg8 : %s: 0x%8x = 0x%x\n",func, addr,ret);
4082fe5e51b7Smrg    return ret;
4083fe5e51b7Smrg}
4084fe5e51b7Smrg
4085fe5e51b7SmrgCARD16
4086fe5e51b7SmrgMGAdbg_inreg16(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4087fe5e51b7Smrg{
4088fe5e51b7Smrg    CARD16 ret;
4089fe5e51b7Smrg
4090fe5e51b7Smrg    ret = MMIO_IN16(MGAPTR(pScrn)->IOBase,addr);
4091fe5e51b7Smrg    if(verbose)
4092fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4093fe5e51b7Smrg			"inreg16: %s: 0x%8x = 0x%x\n",func, addr,ret);
4094fe5e51b7Smrg    return ret;
4095fe5e51b7Smrg}
4096fe5e51b7Smrg
4097fe5e51b7SmrgCARD32
4098fe5e51b7SmrgMGAdbg_inreg32(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4099fe5e51b7Smrg{
4100fe5e51b7Smrg    CARD32 ret;
4101fe5e51b7Smrg
4102fe5e51b7Smrg    ret = MMIO_IN32(MGAPTR(pScrn)->IOBase,addr);
4103fe5e51b7Smrg    if(verbose)
4104fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4105fe5e51b7Smrg			"inreg32: %s: 0x%8x = 0x%x\n",func, addr,ret);
4106fe5e51b7Smrg    return ret;
4107fe5e51b7Smrg}
4108fe5e51b7Smrg
4109fe5e51b7Smrgvoid
4110fe5e51b7SmrgMGAdbg_outreg8(ScrnInfoPtr pScrn,int addr,int val, char* func)
4111fe5e51b7Smrg{
4112fe5e51b7Smrg    CARD8 ret;
4113fe5e51b7Smrg
4114fe5e51b7Smrg#if 0
4115fe5e51b7Smrg    if( addr = MGAREG_CRTCEXT_DATA )
4116fe5e51b7Smrg    	return;
4117fe5e51b7Smrg#endif
4118fe5e51b7Smrg    if( addr != 0x3c00 ) {
4119fe5e51b7Smrg	ret = MGAdbg_inreg8(pScrn,addr,0,func);
4120fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4121fe5e51b7Smrg			"outreg8 : %s: 0x%8x = 0x%x was 0x%x\n",
4122fe5e51b7Smrg			func,addr,val,ret);
4123fe5e51b7Smrg    }
4124fe5e51b7Smrg    else {
4125fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "outreg8 : %s: index 0x%x\n",
4126fe5e51b7Smrg	func,val);
4127fe5e51b7Smrg    }
4128fe5e51b7Smrg    MMIO_OUT8(MGAPTR(pScrn)->IOBase,addr,val);
4129fe5e51b7Smrg}
4130fe5e51b7Smrg
4131fe5e51b7Smrgvoid
4132fe5e51b7SmrgMGAdbg_outreg16(ScrnInfoPtr pScrn,int addr,int val, char* func)
4133fe5e51b7Smrg{
4134fe5e51b7Smrg    CARD16 ret;
4135fe5e51b7Smrg
4136fe5e51b7Smrg#if 0
4137fe5e51b7Smrg    if (addr == MGAREG_CRTCEXT_INDEX)
4138fe5e51b7Smrg    	return;
4139fe5e51b7Smrg#endif
4140fe5e51b7Smrg    ret = MGAdbg_inreg16(pScrn,addr,0, func);
4141fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4142fe5e51b7Smrg			"outreg16: %s: 0x%8x = 0x%x was 0x%x\n",
4143fe5e51b7Smrg			func,addr,val,ret);
4144fe5e51b7Smrg    MMIO_OUT16(MGAPTR(pScrn)->IOBase,addr,val);
4145fe5e51b7Smrg}
4146fe5e51b7Smrg
4147fe5e51b7Smrgvoid
4148fe5e51b7SmrgMGAdbg_outreg32(ScrnInfoPtr pScrn,int addr,int val, char* func)
4149fe5e51b7Smrg{
4150fe5e51b7Smrg    CARD32 ret;
4151fe5e51b7Smrg
4152fe5e51b7Smrg    if (((addr & 0xff00) == 0x1c00)
4153fe5e51b7Smrg    	&& (addr != 0x1c04)
4154fe5e51b7Smrg/*    	&& (addr != 0x1c1c) */
4155fe5e51b7Smrg    	&& (addr != 0x1c20)
4156fe5e51b7Smrg    	&& (addr != 0x1c24)
4157fe5e51b7Smrg    	&& (addr != 0x1c80)
4158fe5e51b7Smrg    	&& (addr != 0x1c8c)
4159fe5e51b7Smrg    	&& (addr != 0x1c94)
4160fe5e51b7Smrg    	&& (addr != 0x1c98)
4161fe5e51b7Smrg    	&& (addr != 0x1c9c)
4162fe5e51b7Smrg	 ) {
4163fe5e51b7Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: refused address 0x%x\n",
4164fe5e51b7Smrg			func,addr);
4165fe5e51b7Smrg    	return;
4166fe5e51b7Smrg    }
4167fe5e51b7Smrg    ret = MGAdbg_inreg32(pScrn,addr,0, func);
4168fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4169fe5e51b7Smrg			"outreg32: %s: 0x%8x = 0x%x was 0x%x\n",
4170fe5e51b7Smrg			func,addr,val,ret);
4171fe5e51b7Smrg    MMIO_OUT32(MGAPTR(pScrn)->IOBase,addr,val);
4172fe5e51b7Smrg}
4173fe5e51b7Smrg#endif /* DEBUG */
4174fe5e51b7Smrg
4175fe5e51b7Smrgstatic void
4176fe5e51b7SmrgMGAG100BlackMagic(ScrnInfoPtr pScrn)
4177fe5e51b7Smrg{
4178fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
4179fe5e51b7Smrg
4180fe5e51b7Smrg    OUTREG(MGAREG_PLNWT, ~(CARD32)0x0);
4181fe5e51b7Smrg    /* reset memory */
4182fe5e51b7Smrg    OUTREG(MGAREG_MACCESS, 1<<15);
4183fe5e51b7Smrg    usleep(10);
4184fe5e51b7Smrg}
4185