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
42681f79626Smrg	16384, 0x4000,          /* Memory probe size & offset values */
42781f79626Smrg    },
42881f79626Smrg
42981f79626Smrg    [17] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
43081f79626Smrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
43181f79626Smrg	{
43281f79626Smrg	    { 50000, 230000 }, /* System VCO frequencies */
43381f79626Smrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
43481f79626Smrg	    { 0, 0 },          /* Video VCO frequencies */
43581f79626Smrg	    45000,            /* Memory clock */
43681f79626Smrg	    27050,             /* PLL reference frequency */
43781f79626Smrg	    0,                 /* Supports fast bitblt? */
43881f79626Smrg	    MGA_HOST_PCI       /* Host interface */
43981f79626Smrg	},
44081f79626Smrg
4410bb88ba4Smrg	16384, 0x4000,          /* Memory probe size & offset values */
4420bb88ba4Smrg    }
443fe5e51b7Smrg};
444fe5e51b7Smrg
445fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
446fe5e51b7Smrg#define MGA_DEVICE_MATCH(d, i) \
447fe5e51b7Smrg    { 0x102B, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
448fe5e51b7Smrg#define MGA_SUBDEVICE_MATCH(d, s, i) \
449fe5e51b7Smrg    { 0x102B, (d), 0x102B, (s), 0, 0, (i) }
450fe5e51b7Smrg
451fe5e51b7Smrgstatic const struct pci_id_match mga_device_match[] = {
452eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2064,     0),
453eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA1064,     1),
454eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164,     2),
455eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164_AGP, 3),
456eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100,     4),
457eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100_PCI, 5),
458eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200,     6),
459eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_PCI, 7),
460eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG400,     8),
461eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG550,     9),
462eda3803bSmrg
463eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_A_PCI, 10),
464eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_B_PCI, 11),
465eda3803bSmrg
466eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_EV_PCI, 12),
467eda3803bSmrg
468eda3803bSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_WINBOND_PCI, 13 ),
469fe5e51b7Smrg
470a31a186aSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EH_PCI, 14 ),
471a31a186aSmrg
4726f68ce78Smrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_ER_PCI, 15 ),
4736f68ce78Smrg
4746f68ce78Smrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EW3_PCI, 16 ),
4750bb88ba4Smrg
47681f79626Smrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EH3_PCI, 17 ),
47781f79626Smrg
478fe5e51b7Smrg    { 0, 0, 0 },
479fe5e51b7Smrg};
480fe5e51b7Smrg#endif
481fe5e51b7Smrg
482fe5e51b7Smrg/* Supported chipsets */
483fe5e51b7Smrgstatic SymTabRec MGAChipsets[] = {
484fe5e51b7Smrg    { PCI_CHIP_MGA2064,		"mga2064w" },
485fe5e51b7Smrg    { PCI_CHIP_MGA1064,		"mga1064sg" },
486fe5e51b7Smrg    { PCI_CHIP_MGA2164,		"mga2164w" },
487fe5e51b7Smrg    { PCI_CHIP_MGA2164_AGP,	"mga2164w AGP" },
488fe5e51b7Smrg    { PCI_CHIP_MGAG100,		"mgag100" },
489fe5e51b7Smrg    { PCI_CHIP_MGAG100_PCI,	"mgag100 PCI" },
490fe5e51b7Smrg    { PCI_CHIP_MGAG200,		"mgag200" },
491fe5e51b7Smrg    { PCI_CHIP_MGAG200_PCI,	"mgag200 PCI" },
492fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI,	"mgag200 SE A PCI" },
493fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI,	"mgag200 SE B PCI" },
494eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI,	"mgag200 EV Maxim" },
4950bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI,	"mgag200 ER SH7757" },
496eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI,	"mgag200 eW Nuvoton" },
4976f68ce78Smrg    { PCI_CHIP_MGAG200_EW3_PCI,	"mgag200 eW3 Nuvoton" },
498a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI,	"mgag200eH" },
49981f79626Smrg     { PCI_CHIP_MGAG200_EH3_PCI,	"mgag200eH3" },
500fe5e51b7Smrg    { PCI_CHIP_MGAG400,		"mgag400" },
501fe5e51b7Smrg    { PCI_CHIP_MGAG550,		"mgag550" },
502fe5e51b7Smrg    {-1,			NULL }
503fe5e51b7Smrg};
504fe5e51b7Smrg
505fe5e51b7Smrgstatic PciChipsets MGAPciChipsets[] = {
506643b027fSmrg    { PCI_CHIP_MGA2064,	    PCI_CHIP_MGA2064,	RES_SHARED_VGA },
507643b027fSmrg    { PCI_CHIP_MGA1064,	    PCI_CHIP_MGA1064,	RES_SHARED_VGA },
508643b027fSmrg    { PCI_CHIP_MGA2164,	    PCI_CHIP_MGA2164,	RES_SHARED_VGA },
509643b027fSmrg    { PCI_CHIP_MGA2164_AGP, PCI_CHIP_MGA2164_AGP,RES_SHARED_VGA },
510643b027fSmrg    { PCI_CHIP_MGAG100,	    PCI_CHIP_MGAG100,	RES_SHARED_VGA },
511643b027fSmrg    { PCI_CHIP_MGAG100_PCI, PCI_CHIP_MGAG100_PCI,RES_SHARED_VGA },
512643b027fSmrg    { PCI_CHIP_MGAG200,	    PCI_CHIP_MGAG200,	RES_SHARED_VGA },
513643b027fSmrg    { PCI_CHIP_MGAG200_PCI, PCI_CHIP_MGAG200_PCI,RES_SHARED_VGA },
514fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI, PCI_CHIP_MGAG200_SE_B_PCI,
515643b027fSmrg	RES_SHARED_VGA },
516fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI, PCI_CHIP_MGAG200_SE_A_PCI,
517643b027fSmrg	RES_SHARED_VGA },
518eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI, PCI_CHIP_MGAG200_EV_PCI,
519643b027fSmrg	RES_SHARED_VGA },
5200bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI, PCI_CHIP_MGAG200_ER_PCI,
5210bb88ba4Smrg	RES_SHARED_VGA },
522eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI, PCI_CHIP_MGAG200_WINBOND_PCI,
523643b027fSmrg	RES_SHARED_VGA },
5246f68ce78Smrg    { PCI_CHIP_MGAG200_EW3_PCI, PCI_CHIP_MGAG200_EW3_PCI,
5256f68ce78Smrg	RES_SHARED_VGA },
526a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI, PCI_CHIP_MGAG200_EH_PCI,
527a31a186aSmrg	RES_SHARED_VGA },
52881f79626Smrg    { PCI_CHIP_MGAG200_EH3_PCI, PCI_CHIP_MGAG200_EH3_PCI,
52981f79626Smrg	RES_SHARED_VGA },
530643b027fSmrg    { PCI_CHIP_MGAG400,	    PCI_CHIP_MGAG400,	RES_SHARED_VGA },
531643b027fSmrg    { PCI_CHIP_MGAG550,	    PCI_CHIP_MGAG550,	RES_SHARED_VGA },
532643b027fSmrg    { -1,			-1,		RES_UNDEFINED }
533fe5e51b7Smrg};
534fe5e51b7Smrg
535fe5e51b7Smrg/*
536fe5e51b7Smrg * This contains the functions needed by the server after loading the
537fe5e51b7Smrg * driver module.  It must be supplied, and gets added the driver list by
538d2b10af6Smrg * the Module Setup function in the dynamic case.  In the static case a
539fe5e51b7Smrg * reference to this is compiled in, and this requires that the name of
540fe5e51b7Smrg * this DriverRec be an upper-case version of the driver name.
541fe5e51b7Smrg */
542fe5e51b7Smrg
543fe5e51b7Smrg_X_EXPORT DriverRec MGA_C_NAME = {
544fe5e51b7Smrg    MGA_VERSION,
545fe5e51b7Smrg    MGA_DRIVER_NAME,
546fe5e51b7Smrg    MGAIdentify,
547fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
548fe5e51b7Smrg    NULL,
549fe5e51b7Smrg#else
550fe5e51b7Smrg    MGAProbe,
551fe5e51b7Smrg#endif
552fe5e51b7Smrg    MGAAvailableOptions,
553fe5e51b7Smrg    NULL,
554fe5e51b7Smrg    0,
555fe5e51b7Smrg    NULL,
556fe5e51b7Smrg
557fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
558fe5e51b7Smrg    mga_device_match,
559fe5e51b7Smrg    MGAPciProbe
560fe5e51b7Smrg#endif
561fe5e51b7Smrg};
562fe5e51b7Smrg
563fe5e51b7Smrg
564fe5e51b7Smrgstatic const OptionInfoRec MGAOptions[] = {
565fe5e51b7Smrg    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
566fe5e51b7Smrg    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
567fe5e51b7Smrg    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
568fe5e51b7Smrg    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
569fe5e51b7Smrg    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
570fe5e51b7Smrg    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
571fe5e51b7Smrg    { OPTION_MGA_SDRAM,		"MGASDRAM",	OPTV_BOOLEAN,	{0}, FALSE },
572fe5e51b7Smrg    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
573fe5e51b7Smrg    { OPTION_FBDEV,		"UseFBDev",	OPTV_BOOLEAN,	{0}, FALSE },
574fe5e51b7Smrg    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
575fe5e51b7Smrg    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,	{0}, FALSE },
576fe5e51b7Smrg    { OPTION_OVERCLOCK_MEM,	"OverclockMem",	OPTV_BOOLEAN,	{0}, FALSE },
577fe5e51b7Smrg    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
578fe5e51b7Smrg    { OPTION_ROTATE,		"Rotate",	OPTV_ANYSTR,	{0}, FALSE },
579fe5e51b7Smrg    { OPTION_TEXTURED_VIDEO,	"TexturedVideo",OPTV_BOOLEAN,	{0}, FALSE },
580fe5e51b7Smrg    { OPTION_CRTC2HALF,		"Crtc2Half",	OPTV_BOOLEAN,	{0}, FALSE },
581fe5e51b7Smrg    { OPTION_CRTC2RAM,		"Crtc2Ram",	OPTV_INTEGER,	{0}, FALSE },
582fe5e51b7Smrg    { OPTION_INT10,		"Int10",	OPTV_BOOLEAN,	{0}, FALSE },
583fe5e51b7Smrg    { OPTION_AGP_MODE,		"AGPMode",	OPTV_INTEGER,	{0}, FALSE },
584fe5e51b7Smrg    { OPTION_AGP_SIZE,		"AGPSize",      OPTV_INTEGER,   {0}, FALSE },
585fe5e51b7Smrg    { OPTION_DIGITAL1,		"DigitalScreen1",OPTV_BOOLEAN,	{0}, FALSE },
586fe5e51b7Smrg    { OPTION_DIGITAL2,		"DigitalScreen2",OPTV_BOOLEAN,	{0}, FALSE },
587fe5e51b7Smrg    { OPTION_TV,		"TV",		OPTV_BOOLEAN,	{0}, FALSE },
588fe5e51b7Smrg    { OPTION_TVSTANDARD,	"TVStandard",	OPTV_ANYSTR,	{0}, FALSE },
589fe5e51b7Smrg    { OPTION_CABLETYPE,		"CableType",	OPTV_ANYSTR,	{0}, FALSE },
590fe5e51b7Smrg    { OPTION_NOHAL,		"NoHal",	OPTV_BOOLEAN,	{0}, FALSE },
591fe5e51b7Smrg    { OPTION_SWAPPED_HEAD,	"SwappedHead",	OPTV_BOOLEAN,	{0}, FALSE },
592fe5e51b7Smrg    { OPTION_DRI,		"DRI",		OPTV_BOOLEAN,	{0}, FALSE },
593fe5e51b7Smrg    { OPTION_MERGEDFB,		"MergedFB",	OPTV_BOOLEAN,	{0}, FALSE },
594fe5e51b7Smrg    { OPTION_HSYNC2,	"Monitor2HSync",	OPTV_ANYSTR,	{0}, FALSE },
595fe5e51b7Smrg    { OPTION_VREFRESH2,	"Monitor2VRefresh",	OPTV_ANYSTR,	{0}, FALSE },
596fe5e51b7Smrg    { OPTION_MONITOR2POS,   "Monitor2Position",	OPTV_ANYSTR,	{0}, FALSE },
597fe5e51b7Smrg    { OPTION_METAMODES,   "MetaModes",  	OPTV_ANYSTR,	{0}, FALSE },
598fe5e51b7Smrg    { OPTION_OLDDMA,		"OldDmaInit",	OPTV_BOOLEAN,	{0}, FALSE },
599fe5e51b7Smrg    { OPTION_PCIDMA,		"ForcePciDma",	OPTV_BOOLEAN,	{0}, FALSE },
600fe5e51b7Smrg    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
601eda3803bSmrg    { OPTION_KVM,		"KVM",		OPTV_BOOLEAN,	{0}, FALSE },
602fe5e51b7Smrg    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
603fe5e51b7Smrg};
604fe5e51b7Smrg
605fe5e51b7Smrg#ifdef XFree86LOADER
606fe5e51b7Smrg
607fe5e51b7Smrgstatic MODULESETUPPROTO(mgaSetup);
608fe5e51b7Smrg
609fe5e51b7Smrgstatic XF86ModuleVersionInfo mgaVersRec =
610fe5e51b7Smrg{
611fe5e51b7Smrg	MGA_DRIVER_NAME,
612fe5e51b7Smrg	MODULEVENDORSTRING,
613fe5e51b7Smrg	MODINFOSTRING1,
614fe5e51b7Smrg	MODINFOSTRING2,
615fe5e51b7Smrg	XORG_VERSION_CURRENT,
616fe5e51b7Smrg    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
617fe5e51b7Smrg	ABI_CLASS_VIDEODRV,			/* This is a video driver */
618fe5e51b7Smrg	ABI_VIDEODRV_VERSION,
619fe5e51b7Smrg	MOD_CLASS_VIDEODRV,
620fe5e51b7Smrg	{0,0,0,0}
621fe5e51b7Smrg};
622fe5e51b7Smrg
623fe5e51b7Smrg_X_EXPORT XF86ModuleData MGA_MODULE_DATA = { &mgaVersRec, mgaSetup, NULL };
624fe5e51b7Smrg
625fe5e51b7Smrgstatic pointer
626fe5e51b7SmrgmgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
627fe5e51b7Smrg{
628fe5e51b7Smrg    static Bool setupDone = FALSE;
629fe5e51b7Smrg
630fe5e51b7Smrg    /* This module should be loaded only once, but check to be sure. */
631fe5e51b7Smrg
632fe5e51b7Smrg    if (!setupDone) {
633fe5e51b7Smrg	setupDone = TRUE;
634fe5e51b7Smrg	xf86AddDriver(&MGA_C_NAME, module, 1);
635fe5e51b7Smrg	/*
636fe5e51b7Smrg	 * The return value must be non-NULL on success even though there
637fe5e51b7Smrg	 * is no TearDownProc.
638fe5e51b7Smrg	 */
639fe5e51b7Smrg	return (pointer)1;
640fe5e51b7Smrg    } else {
641fe5e51b7Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
642fe5e51b7Smrg	return NULL;
643fe5e51b7Smrg    }
644fe5e51b7Smrg}
645fe5e51b7Smrg
646fe5e51b7Smrg
647fe5e51b7Smrg#endif /* XFree86LOADER */
648fe5e51b7Smrg
649fe5e51b7Smrg/*
650fe5e51b7Smrg * ramdac info structure initialization
651fe5e51b7Smrg */
652fe5e51b7Smrgstatic MGARamdacRec DacInit = {
653fe5e51b7Smrg	FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
654fe5e51b7Smrg	90000, /* maxPixelClock */
655fe5e51b7Smrg	0, X_DEFAULT, X_DEFAULT, FALSE
656fe5e51b7Smrg};
657fe5e51b7Smrg
658fe5e51b7SmrgBool
659fe5e51b7SmrgMGAGetRec(ScrnInfoPtr pScrn)
660fe5e51b7Smrg{
661fe5e51b7Smrg    /*
662fe5e51b7Smrg     * Allocate an MGARec, and hook it into pScrn->driverPrivate.
663fe5e51b7Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
664fe5e51b7Smrg     * the allocation has already been done.
665fe5e51b7Smrg     */
666fe5e51b7Smrg    if (pScrn->driverPrivate != NULL)
667fe5e51b7Smrg	return TRUE;
668fe5e51b7Smrg
669fe5e51b7Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(MGARec), 1);
670fe5e51b7Smrg    /* Initialise it */
671fe5e51b7Smrg
672fe5e51b7Smrg    MGAPTR(pScrn)->Dac = DacInit;
673fe5e51b7Smrg    return TRUE;
674fe5e51b7Smrg}
675fe5e51b7Smrg
676fe5e51b7Smrgvoid
677fe5e51b7SmrgMGAFreeRec(ScrnInfoPtr pScrn)
678fe5e51b7Smrg{
6790bb88ba4Smrg    free(pScrn->driverPrivate);
680fe5e51b7Smrg    pScrn->driverPrivate = NULL;
681fe5e51b7Smrg}
682fe5e51b7Smrg
683fe5e51b7Smrgstatic const OptionInfoRec *
684fe5e51b7SmrgMGAAvailableOptions(int chipid, int busid)
685fe5e51b7Smrg{
686fe5e51b7Smrg    return MGAOptions;
687fe5e51b7Smrg}
688fe5e51b7Smrg
689fe5e51b7Smrg/* Mandatory */
690fe5e51b7Smrgstatic void
691fe5e51b7SmrgMGAIdentify(int flags)
692fe5e51b7Smrg{
693fe5e51b7Smrg    xf86PrintChipsets(MGA_NAME, "driver for Matrox chipsets", MGAChipsets);
694fe5e51b7Smrg}
695fe5e51b7Smrg
696fe5e51b7Smrg
697fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
698fe5e51b7SmrgBool
699fe5e51b7SmrgMGAPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev,
700fe5e51b7Smrg	    intptr_t match_data)
701fe5e51b7Smrg{
702fe5e51b7Smrg    ScrnInfoPtr pScrn = NULL;
703fe5e51b7Smrg    MGAPtr pMga;
704fe5e51b7Smrg
7050bb88ba4Smrg    if (pci_device_has_kernel_driver(dev)) {
706acd6767fSmrg	/* If it's a G200 server chip, it's probably on KMS, so bail; if not,
707acd6767fSmrg	 * it might be using matroxfb, which is ok. */
708acd6767fSmrg	switch (dev->device_id) {
709acd6767fSmrg	    case PCI_CHIP_MGAG200_SE_A_PCI:
710acd6767fSmrg	    case PCI_CHIP_MGAG200_SE_B_PCI:
711acd6767fSmrg	    case PCI_CHIP_MGAG200_EV_PCI:
712acd6767fSmrg	    case PCI_CHIP_MGAG200_ER_PCI:
713acd6767fSmrg	    case PCI_CHIP_MGAG200_WINBOND_PCI:
714acd6767fSmrg	    case PCI_CHIP_MGAG200_EH_PCI:
71581f79626Smrg	    case PCI_CHIP_MGAG200_EH3_PCI:
716acd6767fSmrg		xf86DrvMsg(0, X_ERROR,
717acd6767fSmrg	                   "mga: The PCI device 0x%x at %2.2d@%2.2d:%2.2d:%1.1d has a kernel module claiming it.\n",
718acd6767fSmrg	                   dev->device_id, dev->bus, dev->domain, dev->dev, dev->func);
719acd6767fSmrg	        xf86DrvMsg(0, X_ERROR,
720acd6767fSmrg	                   "mga: This driver cannot operate until it has been unloaded.\n");
721acd6767fSmrg	        return FALSE;
722acd6767fSmrg	}
7230bb88ba4Smrg    }
7240bb88ba4Smrg
725fe5e51b7Smrg    /* Allocate a ScrnInfoRec and claim the slot */
726fe5e51b7Smrg    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, MGAPciChipsets,
727fe5e51b7Smrg				NULL,
728fe5e51b7Smrg				NULL, NULL, NULL, NULL
729fe5e51b7Smrg				);
730fe5e51b7Smrg    if (pScrn != NULL) {
731fe5e51b7Smrg	/* Fill in what we can of the ScrnInfoRec */
732fe5e51b7Smrg	pScrn->driverVersion	= MGA_VERSION;
733fe5e51b7Smrg	pScrn->driverName	= MGA_DRIVER_NAME;
734fe5e51b7Smrg	pScrn->name		= MGA_NAME;
735fe5e51b7Smrg	pScrn->Probe		= NULL;
736fe5e51b7Smrg	pScrn->PreInit		= MGAPreInit;
737fe5e51b7Smrg	pScrn->ScreenInit	= MGAScreenInit;
738fe5e51b7Smrg	pScrn->SwitchMode	= MGASwitchMode;
739fe5e51b7Smrg	pScrn->AdjustFrame	= MGAAdjustFrame;
740fe5e51b7Smrg	pScrn->EnterVT		= MGAEnterVT;
741fe5e51b7Smrg	pScrn->LeaveVT		= MGALeaveVT;
742fe5e51b7Smrg	pScrn->FreeScreen	= MGAFreeScreen;
743fe5e51b7Smrg	pScrn->ValidMode	= MGAValidMode;
744fe5e51b7Smrg
745fe5e51b7Smrg
746fe5e51b7Smrg	/* Allocate the MGARec driverPrivate */
747fe5e51b7Smrg	if (!MGAGetRec(pScrn)) {
748fe5e51b7Smrg	    return FALSE;
749fe5e51b7Smrg	}
750fe5e51b7Smrg
751fe5e51b7Smrg	pMga = MGAPTR(pScrn);
752fe5e51b7Smrg	pMga->chip_attribs = & attribs[ match_data ];
753fe5e51b7Smrg	pMga->PciInfo = dev;
754fe5e51b7Smrg
755fe5e51b7Smrg
756fe5e51b7Smrg	/*
757fe5e51b7Smrg	 * For cards that can do dual head per entity, mark the entity
758d2b10af6Smrg	 * as shareable.
759fe5e51b7Smrg	 */
760fe5e51b7Smrg	if (pMga->chip_attribs->dual_head_possible) {
761fe5e51b7Smrg	    MGAEntPtr pMgaEnt = NULL;
762fe5e51b7Smrg	    DevUnion *pPriv;
763fe5e51b7Smrg
764fe5e51b7Smrg	    xf86SetEntitySharable(entity_num);
765fe5e51b7Smrg	    /* Allocate an entity private if necessary */
766fe5e51b7Smrg	    if (MGAEntityIndex < 0)
767fe5e51b7Smrg	      MGAEntityIndex = xf86AllocateEntityPrivateIndex();
768fe5e51b7Smrg	    pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
769fe5e51b7Smrg	    if (!pPriv->ptr) {
770fe5e51b7Smrg		pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
771fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
772fe5e51b7Smrg		pMgaEnt->lastInstance = -1;
773fe5e51b7Smrg	    } else {
774fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
775fe5e51b7Smrg	    }
776fe5e51b7Smrg	    /*
777fe5e51b7Smrg	     * Set the entity instance for this instance of the driver.  For
778fe5e51b7Smrg	     * dual head per card, instance 0 is the "master" instance, driving
779fe5e51b7Smrg	     * the primary head, and instance 1 is the "slave".
780fe5e51b7Smrg	     */
781fe5e51b7Smrg	    pMgaEnt->lastInstance++;
782fe5e51b7Smrg	    xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
783fe5e51b7Smrg					   pMgaEnt->lastInstance);
784fe5e51b7Smrg	}
785fe5e51b7Smrg    }
786fe5e51b7Smrg
787fe5e51b7Smrg    return (pScrn != NULL);
788fe5e51b7Smrg}
789fe5e51b7Smrg
790fe5e51b7Smrg#else
791fe5e51b7Smrg
792fe5e51b7Smrg/* Mandatory */
793fe5e51b7Smrgstatic Bool
794fe5e51b7SmrgMGAProbe(DriverPtr drv, int flags)
795fe5e51b7Smrg{
796fe5e51b7Smrg    int i;
797fe5e51b7Smrg    GDevPtr *devSections;
798fe5e51b7Smrg    int *usedChips = NULL;
799fe5e51b7Smrg    int numDevSections;
800fe5e51b7Smrg    int numUsed;
801fe5e51b7Smrg    Bool foundScreen = FALSE;
802fe5e51b7Smrg
803fe5e51b7Smrg    /*
804fe5e51b7Smrg     * The aim here is to find all cards that this driver can handle,
805fe5e51b7Smrg     * and for the ones not already claimed by another driver, claim the
806fe5e51b7Smrg     * slot, and allocate a ScrnInfoRec.
807fe5e51b7Smrg     *
808fe5e51b7Smrg     * This should be a minimal probe, and it should under no circumstances
809fe5e51b7Smrg     * change the state of the hardware.  Because a device is found, don't
810fe5e51b7Smrg     * assume that it will be used.  Don't do any initialisations other than
811fe5e51b7Smrg     * the required ScrnInfoRec initialisations.  Don't allocate any new
812fe5e51b7Smrg     * data structures.
813fe5e51b7Smrg     */
814fe5e51b7Smrg
815fe5e51b7Smrg    /*
816fe5e51b7Smrg     * Check if there has been a chipset override in the config file.
817fe5e51b7Smrg     * For this we must find out if there is an active device section which
818fe5e51b7Smrg     * is relevant, i.e., which has no driver specified or has THIS driver
819fe5e51b7Smrg     * specified.
820fe5e51b7Smrg     */
821fe5e51b7Smrg
822fe5e51b7Smrg    if ((numDevSections = xf86MatchDevice(MGA_DRIVER_NAME,
823fe5e51b7Smrg					  &devSections)) <= 0) {
824fe5e51b7Smrg	/*
825fe5e51b7Smrg	 * There's no matching device section in the config file, so quit
826fe5e51b7Smrg	 * now.
827fe5e51b7Smrg	 */
828fe5e51b7Smrg	return FALSE;
829fe5e51b7Smrg    }
830fe5e51b7Smrg
831fe5e51b7Smrg    /*
832fe5e51b7Smrg     * We need to probe the hardware first.  We then need to see how this
833fe5e51b7Smrg     * fits in with what is given in the config file, and allow the config
834fe5e51b7Smrg     * file info to override any contradictions.
835fe5e51b7Smrg     */
836fe5e51b7Smrg
837fe5e51b7Smrg    /*
838fe5e51b7Smrg     * All of the cards this driver supports are PCI, so the "probing" just
839fe5e51b7Smrg     * amounts to checking the PCI data that the server has already collected.
840fe5e51b7Smrg     */
841fe5e51b7Smrg    if (xf86GetPciVideoInfo() == NULL) {
842fe5e51b7Smrg	/*
843fe5e51b7Smrg	 * We won't let anything in the config file override finding no
844fe5e51b7Smrg	 * PCI video cards at all.  This seems reasonable now, but we'll see.
845fe5e51b7Smrg	 */
846fe5e51b7Smrg	return FALSE;
847fe5e51b7Smrg    }
848fe5e51b7Smrg
849fe5e51b7Smrg    numUsed = xf86MatchPciInstances(MGA_NAME, PCI_VENDOR_MATROX,
850fe5e51b7Smrg			            MGAChipsets, MGAPciChipsets, devSections,
851fe5e51b7Smrg			            numDevSections, drv, &usedChips);
852fe5e51b7Smrg    /* Free it since we don't need that list after this */
8530bb88ba4Smrg    free(devSections);
854fe5e51b7Smrg    if (numUsed <= 0)
855fe5e51b7Smrg	return FALSE;
856fe5e51b7Smrg
857fe5e51b7Smrg
858fe5e51b7Smrg    if (flags & PROBE_DETECT)
859fe5e51b7Smrg	foundScreen = TRUE;
860fe5e51b7Smrg    else for (i = 0; i < numUsed; i++) {
861fe5e51b7Smrg	ScrnInfoPtr pScrn = NULL;
862fe5e51b7Smrg	EntityInfoPtr pEnt;
863fe5e51b7Smrg	int attrib_no;
864fe5e51b7Smrg
865fe5e51b7Smrg	/* Allocate a ScrnInfoRec and claim the slot */
866fe5e51b7Smrg	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
867fe5e51b7Smrg				    MGAPciChipsets, NULL, NULL,
868fe5e51b7Smrg				    NULL, NULL, NULL);
869fe5e51b7Smrg        if (pScrn != NULL) {
870fe5e51b7Smrg	    MGAPtr pMga;
871fe5e51b7Smrg
872fe5e51b7Smrg	    /* Fill in what we can of the ScrnInfoRec */
873fe5e51b7Smrg	    pScrn->driverVersion = MGA_VERSION;
874fe5e51b7Smrg	    pScrn->driverName	= MGA_DRIVER_NAME;
875fe5e51b7Smrg	    pScrn->name		= MGA_NAME;
876fe5e51b7Smrg	    pScrn->Probe	= MGAProbe;
877fe5e51b7Smrg	    pScrn->PreInit	= MGAPreInit;
878fe5e51b7Smrg	    pScrn->ScreenInit	= MGAScreenInit;
879fe5e51b7Smrg	    pScrn->SwitchMode	= MGASwitchMode;
880fe5e51b7Smrg	    pScrn->AdjustFrame	= MGAAdjustFrame;
881fe5e51b7Smrg	    pScrn->EnterVT	= MGAEnterVT;
882fe5e51b7Smrg	    pScrn->LeaveVT	= MGALeaveVT;
883fe5e51b7Smrg	    pScrn->FreeScreen	= MGAFreeScreen;
884fe5e51b7Smrg	    pScrn->ValidMode	= MGAValidMode;
885fe5e51b7Smrg
886fe5e51b7Smrg	    foundScreen = TRUE;
887fe5e51b7Smrg
888fe5e51b7Smrg	    /* Allocate the MGARec driverPrivate */
889fe5e51b7Smrg	    if (!MGAGetRec(pScrn)) {
890fe5e51b7Smrg		return FALSE;
891fe5e51b7Smrg	    }
892fe5e51b7Smrg
893fe5e51b7Smrg	    pMga = MGAPTR(pScrn);
894fe5e51b7Smrg
895fe5e51b7Smrg	    /*
896fe5e51b7Smrg	     * For cards that can do dual head per entity, mark the entity
897d2b10af6Smrg	     * as shareable.
898fe5e51b7Smrg	     */
899fe5e51b7Smrg	    pEnt = xf86GetEntityInfo(usedChips[i]);
900fe5e51b7Smrg
901fe5e51b7Smrg            switch (pEnt->chipset) {
902fe5e51b7Smrg            case PCI_CHIP_MGA2064:
903fe5e51b7Smrg                attrib_no = 0;
904fe5e51b7Smrg                break;
905fe5e51b7Smrg
906fe5e51b7Smrg            case PCI_CHIP_MGA1064:
907fe5e51b7Smrg                attrib_no = 1;
908fe5e51b7Smrg                break;
909fe5e51b7Smrg
910fe5e51b7Smrg            case PCI_CHIP_MGA2164:
911fe5e51b7Smrg                attrib_no = 2;
912fe5e51b7Smrg                break;
913eda3803bSmrg
914eda3803bSmrg            case PCI_CHIP_MGA2164_AGP:
915eda3803bSmrg                attrib_no = 3;
916eda3803bSmrg                break;
917fe5e51b7Smrg
918fe5e51b7Smrg            case PCI_CHIP_MGAG100:
919eda3803bSmrg                attrib_no = 4;
920eda3803bSmrg                break;
921eda3803bSmrg
922fe5e51b7Smrg            case PCI_CHIP_MGAG100_PCI:
923eda3803bSmrg                attrib_no = 5;
924fe5e51b7Smrg                break;
925fe5e51b7Smrg
926fe5e51b7Smrg            case PCI_CHIP_MGAG200:
927eda3803bSmrg                attrib_no = 6;
928eda3803bSmrg                break;
929eda3803bSmrg
930fe5e51b7Smrg            case PCI_CHIP_MGAG200_PCI:
931eda3803bSmrg                attrib_no = 7;
932fe5e51b7Smrg                break;
933fe5e51b7Smrg
934fe5e51b7Smrg            case PCI_CHIP_MGAG400:
935eda3803bSmrg                attrib_no = 8;
936fe5e51b7Smrg                break;
937fe5e51b7Smrg
938fe5e51b7Smrg            case PCI_CHIP_MGAG550:
939eda3803bSmrg                attrib_no = 9;
940fe5e51b7Smrg                break;
941fe5e51b7Smrg
942fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_A_PCI:
943eda3803bSmrg                attrib_no = 10;
944eda3803bSmrg                break;
945eda3803bSmrg
946fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_B_PCI:
947eda3803bSmrg                attrib_no = 11;
948eda3803bSmrg                break;
949eda3803bSmrg
950eda3803bSmrg            case PCI_CHIP_MGAG200_EV_PCI:
951eda3803bSmrg                attrib_no = 12;
952eda3803bSmrg                break;
953eda3803bSmrg
954eda3803bSmrg            case PCI_CHIP_MGAG200_WINBOND_PCI:
955eda3803bSmrg                attrib_no = 13;
956fe5e51b7Smrg                break;
957fe5e51b7Smrg
958a31a186aSmrg            case PCI_CHIP_MGAG200_EH_PCI:
959a31a186aSmrg                attrib_no = 14;
960a31a186aSmrg                break;
9610bb88ba4Smrg
9620bb88ba4Smrg            case PCI_CHIP_MGAG200_ER_PCI:
9630bb88ba4Smrg                attrib_no = 15;
9640bb88ba4Smrg                break;
9650bb88ba4Smrg
9666f68ce78Smrg            case PCI_CHIP_MGAG200_EW3_PCI:
9676f68ce78Smrg                attrib_no = 16;
9686f68ce78Smrg                break;
969a31a186aSmrg
97081f79626Smrg            case PCI_CHIP_MGAG200_EH3_PCI:
97181f79626Smrg                attrib_no = 17;
97281f79626Smrg                break;
97381f79626Smrg
974fe5e51b7Smrg	    default:
975fe5e51b7Smrg		return FALSE;
976fe5e51b7Smrg            }
977fe5e51b7Smrg
978fe5e51b7Smrg	    pMga->chip_attribs = & attribs[attrib_no];
979fe5e51b7Smrg
980fe5e51b7Smrg	    if (pMga->chip_attribs->dual_head_possible) {
981fe5e51b7Smrg		MGAEntPtr pMgaEnt = NULL;
982fe5e51b7Smrg		DevUnion *pPriv;
983fe5e51b7Smrg
984fe5e51b7Smrg		xf86SetEntitySharable(usedChips[i]);
985fe5e51b7Smrg		/* Allocate an entity private if necessary */
986fe5e51b7Smrg		if (MGAEntityIndex < 0)
987fe5e51b7Smrg		    MGAEntityIndex = xf86AllocateEntityPrivateIndex();
988fe5e51b7Smrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
989fe5e51b7Smrg		if (!pPriv->ptr) {
990fe5e51b7Smrg		    pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
991fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
992fe5e51b7Smrg		    pMgaEnt->lastInstance = -1;
993fe5e51b7Smrg		} else {
994fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
995fe5e51b7Smrg		}
996fe5e51b7Smrg		/*
997fe5e51b7Smrg		 * Set the entity instance for this instance of the driver.  For
998fe5e51b7Smrg		 * dual head per card, instance 0 is the "master" instance, driving
999fe5e51b7Smrg		 * the primary head, and instance 1 is the "slave".
1000fe5e51b7Smrg		 */
1001fe5e51b7Smrg		pMgaEnt->lastInstance++;
1002fe5e51b7Smrg		xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
1003fe5e51b7Smrg					       pMgaEnt->lastInstance);
1004fe5e51b7Smrg	    }
1005fe5e51b7Smrg        }
1006fe5e51b7Smrg    }
10070bb88ba4Smrg    free(usedChips);
1008fe5e51b7Smrg
1009fe5e51b7Smrg    return foundScreen;
1010fe5e51b7Smrg}
1011fe5e51b7Smrg#endif
1012fe5e51b7Smrg
1013fe5e51b7Smrg
1014fe5e51b7Smrg/*
1015fe5e51b7Smrg * MGASoftReset --
1016fe5e51b7Smrg *
1017fe5e51b7Smrg * Resets drawing engine
1018fe5e51b7Smrg */
1019fe5e51b7Smrgvoid
1020fe5e51b7SmrgMGASoftReset(ScrnInfoPtr pScrn)
1021fe5e51b7Smrg{
1022fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1023fe5e51b7Smrg
1024fe5e51b7Smrg	pMga->FbMapSize = 8192 * 1024;
102581f79626Smrg	if (!MGAMapMem(pScrn)) {
102681f79626Smrg	    return;
102781f79626Smrg	}
1028fe5e51b7Smrg
1029fe5e51b7Smrg	/* set soft reset bit */
1030fe5e51b7Smrg	OUTREG(MGAREG_Reset, 1);
1031fe5e51b7Smrg	usleep(200);
1032fe5e51b7Smrg	OUTREG(MGAREG_Reset, 0);
1033fe5e51b7Smrg
1034fe5e51b7Smrg	/* reset memory */
1035fe5e51b7Smrg	OUTREG(MGAREG_MACCESS, 1<<15);
1036fe5e51b7Smrg	usleep(10);
1037fe5e51b7Smrg
1038fe5e51b7Smrg#if 0
1039fe5e51b7Smrg	/* This will hang if the PLLs aren't on */
1040fe5e51b7Smrg
1041fe5e51b7Smrg	/* wait until drawing engine is ready */
1042fe5e51b7Smrg	while ( MGAISBUSY() )
1043fe5e51b7Smrg	    usleep(1000);
1044fe5e51b7Smrg
1045fe5e51b7Smrg	/* flush FIFO */
1046fe5e51b7Smrg	i = 32;
1047fe5e51b7Smrg	WAITFIFO(i);
1048fe5e51b7Smrg	while ( i-- )
1049fe5e51b7Smrg	    OUTREG(MGAREG_SHIFT, 0);
1050fe5e51b7Smrg#endif
1051fe5e51b7Smrg
1052fe5e51b7Smrg	MGAUnmapMem(pScrn);
1053fe5e51b7Smrg}
1054fe5e51b7Smrg
1055fe5e51b7Smrg/*
1056fe5e51b7Smrg * MGACountRAM --
1057fe5e51b7Smrg *
1058fe5e51b7Smrg * Counts amount of installed RAM
1059fe5e51b7Smrg */
1060fe5e51b7Smrgstatic int
1061fe5e51b7SmrgMGACountRam(ScrnInfoPtr pScrn)
1062fe5e51b7Smrg{
1063fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1064eda3803bSmrg    int ProbeSize = pMga->chip_attribs->probe_size;
1065eda3803bSmrg    int ProbeSizeOffset = pMga->chip_attribs->probe_offset;
1066fe5e51b7Smrg    int SizeFound = 2048;
1067fe5e51b7Smrg    CARD32 biosInfo = 0;
1068fe5e51b7Smrg    CARD8 seq1;
1069fe5e51b7Smrg
1070fe5e51b7Smrg#if 0
1071fe5e51b7Smrg    /* This isn't correct. It looks like this can have arbitrary
1072fe5e51b7Smrg	data for the memconfig even when the bios has initialized
1073fe5e51b7Smrg	it.  At least, my cards don't advertise the documented
1074fe5e51b7Smrg	values (my 8 and 16 Meg G200s have the same values) */
1075fe5e51b7Smrg    if (pMga->Primary) { /* can only trust this for primary cards */
1076fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1077fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & biosInfo,
1078fe5e51b7Smrg				PCI_OPTION_REG);
1079fe5e51b7Smrg#else
1080fe5e51b7Smrg	biosInfo = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1081fe5e51b7Smrg#endif
1082fe5e51b7Smrg    }
1083fe5e51b7Smrg#endif
1084fe5e51b7Smrg
1085fe5e51b7Smrg    switch(pMga->Chipset) {
1086fe5e51b7Smrg    case PCI_CHIP_MGA2164:
1087fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
1088fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1089fe5e51b7Smrg		"Unable to probe memory amount due to hardware bug.  "
1090fe5e51b7Smrg		"Assuming 4096 KB\n");
1091fe5e51b7Smrg	return 4096;
1092fe5e51b7Smrg    case PCI_CHIP_MGAG400:
1093fe5e51b7Smrg    case PCI_CHIP_MGAG550:
1094fe5e51b7Smrg	if(biosInfo) {
1095fe5e51b7Smrg	    switch((biosInfo >> 10) & 0x07) {
1096fe5e51b7Smrg	    case 0:
1097fe5e51b7Smrg		return (biosInfo & (1 << 14)) ? 32768 : 16384;
1098fe5e51b7Smrg	    case 1:
1099fe5e51b7Smrg	    case 2:
1100fe5e51b7Smrg		return 16384;
1101fe5e51b7Smrg	    case 3:
1102fe5e51b7Smrg	    case 5:
1103fe5e51b7Smrg		return 65536;
1104fe5e51b7Smrg	    case 4:
1105fe5e51b7Smrg		return 32768;
1106fe5e51b7Smrg	    }
1107fe5e51b7Smrg	}
1108fe5e51b7Smrg	break;
1109fe5e51b7Smrg    case PCI_CHIP_MGAG200:
1110fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
1111fe5e51b7Smrg	if(biosInfo) {
1112fe5e51b7Smrg	    switch((biosInfo >> 11) & 0x03) {
1113fe5e51b7Smrg	    case 0:
1114fe5e51b7Smrg		return 8192;
1115fe5e51b7Smrg	    default:
1116fe5e51b7Smrg		return 16384;
1117fe5e51b7Smrg	    }
1118fe5e51b7Smrg	}
1119fe5e51b7Smrg	break;
1120fe5e51b7Smrg    case PCI_CHIP_MGAG100:
1121fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
1122fe5e51b7Smrg	if(biosInfo) /* I'm not sure if the docs are correct */
1123fe5e51b7Smrg	    return (biosInfo & (1 << 12)) ? 16384 : 8192;
1124fe5e51b7Smrg        break;
1125fe5e51b7Smrg    default:
1126fe5e51b7Smrg        break;
1127fe5e51b7Smrg    }
1128fe5e51b7Smrg
1129fe5e51b7Smrg    if (pMga->FbAddress) {
1130fe5e51b7Smrg	volatile unsigned char* base;
1131fe5e51b7Smrg	unsigned char tmp;
1132fe5e51b7Smrg	int i;
1133fe5e51b7Smrg
1134fe5e51b7Smrg	pMga->FbMapSize = ProbeSize * 1024;
1135fe5e51b7Smrg	if (!MGAMapMem(pScrn)) {
1136fe5e51b7Smrg	    return 0;
1137fe5e51b7Smrg	}
1138fe5e51b7Smrg
1139fe5e51b7Smrg	base = pMga->FbBase;
1140fe5e51b7Smrg
1141eda3803bSmrg	if (pMga->is_G200SE)
1142eda3803bSmrg	    pMga->reg_1e24 = INREG(0x1e24); /* stash the model for later */
11430bb88ba4Smrg	if (pMga->reg_1e24 >= 0x01) {
1144eda3803bSmrg	    MGAUnmapMem(pScrn);
1145eda3803bSmrg	    ProbeSize = 16384;
1146eda3803bSmrg	    ProbeSizeOffset = 0x10000;
1147eda3803bSmrg	    pMga->FbMapSize = ProbeSize * 1024;
114881f79626Smrg	    if (!MGAMapMem(pScrn)) {
114981f79626Smrg		return 0;
115081f79626Smrg	    }
1151eda3803bSmrg	    base = pMga->FbBase;
1152eda3803bSmrg	}
1153eda3803bSmrg
1154fe5e51b7Smrg	if (pMga->is_G200SE) {
1155fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1156fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1157fe5e51b7Smrg	    seq1 |= 0x20;
1158fe5e51b7Smrg	    MGAWAITVSYNC();
1159fe5e51b7Smrg	    MGAWAITBUSY();
1160fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1161fe5e51b7Smrg	    usleep(20000);
1162fe5e51b7Smrg	}
1163fe5e51b7Smrg
1164eda3803bSmrg        if (pMga->is_G200WB) {
116581f79626Smrg            uint32_t Option, MaxMapSize;
1166eda3803bSmrg
1167eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1168eda3803bSmrg            pci_device_cfg_read_u32(pMga->PciInfo, &Option,
1169eda3803bSmrg                                    PCI_OPTION_REG);
1170eda3803bSmrg            MaxMapSize = pMga->PciInfo->regions[0].size;
1171eda3803bSmrg#else
1172eda3803bSmrg            Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1173eda3803bSmrg            MaxMapSize = 1UL << pMga->PciInfo->size[0];
1174eda3803bSmrg#endif
1175eda3803bSmrg            Option = (Option & 0x3000000) >> 24 ;
1176eda3803bSmrg
1177eda3803bSmrg            if (Option == 2)
1178eda3803bSmrg                ProbeSize = 4*1024;
1179eda3803bSmrg            else if(Option == 1)
1180eda3803bSmrg                ProbeSize = 8*1024;
1181eda3803bSmrg            else if(Option == 0)
1182eda3803bSmrg                ProbeSize = 16*1024;
1183eda3803bSmrg
1184eda3803bSmrg            if (ProbeSize * 1024 > MaxMapSize)
1185eda3803bSmrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1186eda3803bSmrg                        "Fb size from config space doesn't fit option register\n");
1187eda3803bSmrg            else {
1188eda3803bSmrg                MGAUnmapMem(pScrn);
1189eda3803bSmrg                pMga->FbMapSize = ProbeSize * 1024;
119081f79626Smrg                if (!MGAMapMem(pScrn)) {
119181f79626Smrg		    return 0;
119281f79626Smrg		}
1193eda3803bSmrg                base = pMga->FbBase;
1194eda3803bSmrg            }
1195eda3803bSmrg        }
1196eda3803bSmrg
1197fe5e51b7Smrg	/* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */
1198fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1199fe5e51b7Smrg	tmp = INREG8(MGAREG_CRTCEXT_DATA);
1200fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp | 0x80);
1201fe5e51b7Smrg
1202eda3803bSmrg	/* apparently the G200 IP don't have a BIOS to read */
1203a31a186aSmrg	if (pMga->is_G200SE || pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) {
1204fe5e51b7Smrg	    CARD32 MemoryAt0, MemoryAt1, Offset;
1205fe5e51b7Smrg	    CARD32 FirstMemoryVal1, FirstMemoryVal2;
1206fe5e51b7Smrg	    CARD32 SecondMemoryVal1, SecondMemoryVal2;
1207fe5e51b7Smrg	    CARD32 TestMemoryLocA, TestMemoryLocB;
1208fe5e51b7Smrg	    CARD32 TestMemoryLoc0, TestMemoryLoc1;
1209fe5e51b7Smrg	    CARD32 TestA, TestB;
1210fe5e51b7Smrg
1211fe5e51b7Smrg	    MemoryAt0 = base[0];
1212fe5e51b7Smrg	    MemoryAt1 = base[1];
1213fe5e51b7Smrg	    base[0] = 0;
1214fe5e51b7Smrg	    base[1] = 0;
1215fe5e51b7Smrg
1216fe5e51b7Smrg	    for (Offset = 0x100000; Offset < (ProbeSize * 1024);
1217eda3803bSmrg		    Offset += ProbeSizeOffset) {
1218fe5e51b7Smrg		FirstMemoryVal1 = base[Offset];
1219fe5e51b7Smrg		FirstMemoryVal2 = base[Offset+1];
1220fe5e51b7Smrg		SecondMemoryVal1 = base[Offset+0x100];
1221fe5e51b7Smrg		SecondMemoryVal2 = base[Offset+0x101];
1222fe5e51b7Smrg
1223fe5e51b7Smrg		base[Offset] = 0x55;
1224fe5e51b7Smrg		base[Offset+1] = 0xaa;
1225fe5e51b7Smrg		base[Offset+0x100] = 0x55;
1226fe5e51b7Smrg		base[Offset+0x101] = 0xaa;
1227fe5e51b7Smrg
1228eda3803bSmrg		OUTREG8(MGAREG_CRTC_INDEX, 0);
1229fe5e51b7Smrg		usleep(8);
1230fe5e51b7Smrg
1231fe5e51b7Smrg		TestMemoryLocA = base[Offset];
1232fe5e51b7Smrg		TestMemoryLocB = base[Offset+1];
1233fe5e51b7Smrg		TestMemoryLoc0 = base[0];
1234fe5e51b7Smrg		TestMemoryLoc1 = base[1];
1235fe5e51b7Smrg
1236fe5e51b7Smrg		base[Offset] = FirstMemoryVal1;
1237fe5e51b7Smrg		base[Offset+1] = FirstMemoryVal2;
1238fe5e51b7Smrg		base[Offset+0x100] = SecondMemoryVal1;
1239fe5e51b7Smrg		base[Offset+0x101] = SecondMemoryVal2;
1240fe5e51b7Smrg
1241fe5e51b7Smrg		TestA = ((TestMemoryLocB << 8) + TestMemoryLocA);
1242fe5e51b7Smrg		TestB = ((TestMemoryLoc1 << 8) + TestMemoryLoc0);
1243fe5e51b7Smrg		if ((TestA != 0xAA55) || (TestB)) {
1244fe5e51b7Smrg		    break;
1245fe5e51b7Smrg		}
1246fe5e51b7Smrg	    }
1247fe5e51b7Smrg
1248fe5e51b7Smrg	    base[0] = MemoryAt0;
1249fe5e51b7Smrg	    base[1] = MemoryAt1;
1250fe5e51b7Smrg
1251fe5e51b7Smrg	    SizeFound = (Offset / 1024) - 64;
1252fe5e51b7Smrg	} else {
1253fe5e51b7Smrg	    /* write, read and compare method
1254fe5e51b7Smrg	       split into two loops to make it more reliable on RS/6k -ReneR */
1255fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1256fe5e51b7Smrg		base[(i * 1024) - 1] = 0xAA;
1257fe5e51b7Smrg	    }
1258fe5e51b7Smrg	    OUTREG8(MGAREG_CRTC_INDEX, 0);  /* flush the cache */
1259fe5e51b7Smrg	    usleep(4);  /* twart write combination */
1260fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1261fe5e51b7Smrg		if(base[(i * 1024) - 1] == 0xAA) {
1262fe5e51b7Smrg		    SizeFound = i;
1263fe5e51b7Smrg		    break;
1264fe5e51b7Smrg		}
1265fe5e51b7Smrg	    }
1266fe5e51b7Smrg	}
1267fe5e51b7Smrg
1268fe5e51b7Smrg	/* restore CRTCEXT3 state */
1269fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1270fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp);
1271fe5e51b7Smrg
1272fe5e51b7Smrg	if (pMga->is_G200SE) {
1273fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1274fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1275fe5e51b7Smrg	    seq1 &= ~0x20;
1276fe5e51b7Smrg	    MGAWAITVSYNC();
1277fe5e51b7Smrg	    MGAWAITBUSY();
1278fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1279fe5e51b7Smrg	    usleep(20000);
1280fe5e51b7Smrg	}
1281fe5e51b7Smrg	MGAUnmapMem(pScrn);
1282fe5e51b7Smrg    }
1283fe5e51b7Smrg   return SizeFound;
1284fe5e51b7Smrg}
1285fe5e51b7Smrg
1286643b027fSmrg#ifdef  EDID_COMPLETE_RAWDATA
1287643b027fSmrg#undef  xf86DoEDID_DDC2
1288643b027fSmrg#define xf86DoEDID_DDC2(a, b) xf86DoEEDID(a, b, TRUE)
1289643b027fSmrg#endif
1290643b027fSmrg
1291fe5e51b7Smrgstatic xf86MonPtr
1292fe5e51b7SmrgMGAdoDDC(ScrnInfoPtr pScrn)
1293fe5e51b7Smrg{
1294643b027fSmrg    vgaHWPtr hwp;
1295643b027fSmrg    MGAPtr pMga;
1296643b027fSmrg    xf86MonPtr MonInfo = NULL;
12970bb88ba4Smrg    const char *from = NULL;
1298643b027fSmrg
1299643b027fSmrg    hwp = VGAHWPTR(pScrn);
1300643b027fSmrg    pMga = MGAPTR(pScrn);
1301643b027fSmrg
1302643b027fSmrg    /* Load DDC if we have the code to use it */
1303643b027fSmrg    /* This gives us DDC1 */
1304643b027fSmrg    if (pMga->ddc1Read || pMga->i2cInit) {
1305643b027fSmrg	if (!xf86LoadSubModule(pScrn, "ddc")) {
1306643b027fSmrg	    /* ddc module not found, we can do without it */
1307643b027fSmrg	    pMga->ddc1Read = NULL;
1308643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1309643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1310643b027fSmrg	    return NULL;
1311fe5e51b7Smrg	}
1312fe5e51b7Smrg    } else
1313643b027fSmrg	return NULL;
1314fe5e51b7Smrg
1315fe5e51b7Smrg    /* - DDC can use I2C bus */
1316fe5e51b7Smrg    /* Load I2C if we have the code to use it */
1317fe5e51b7Smrg    if (pMga->i2cInit) {
1318643b027fSmrg	if (!xf86LoadSubModule(pScrn, "i2c")) {
1319643b027fSmrg	    /* i2c module not found, we can do without it */
1320643b027fSmrg	    pMga->i2cInit = NULL;
1321643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1322643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1323643b027fSmrg	}
1324643b027fSmrg    }
1325643b027fSmrg
1326643b027fSmrg    /* Map the MGA memory and MMIO areas */
1327643b027fSmrg    if (!MGAMapMem(pScrn))
1328643b027fSmrg	return NULL;
1329643b027fSmrg
1330643b027fSmrg    /* Initialise the MMIO vgahw functions */
1331643b027fSmrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
1332643b027fSmrg    vgaHWGetIOBase(hwp);
1333643b027fSmrg
1334643b027fSmrg    /* Map the VGA memory when the primary video */
1335643b027fSmrg    if (pMga->Primary) {
1336643b027fSmrg	hwp->MapSize = 0x10000;
1337643b027fSmrg	if (!vgaHWMapMem(pScrn))
1338643b027fSmrg	    return NULL;
1339643b027fSmrg    } else {
1340643b027fSmrg	/* XXX Need to write an MGA mode ddc1SetSpeed */
1341643b027fSmrg	if (pMga->DDC1SetSpeed == vgaHWddc1SetSpeedWeak()) {
1342643b027fSmrg	    pMga->DDC1SetSpeed = NULL;
1343643b027fSmrg	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
1344643b027fSmrg			   "DDC1 disabled - chip not in VGA mode\n");
1345643b027fSmrg	}
1346643b027fSmrg    }
1347fe5e51b7Smrg
1348643b027fSmrg    /* Save the current state */
1349643b027fSmrg    MGASave(pScrn);
1350643b027fSmrg
1351643b027fSmrg    /* It is now safe to talk to the card */
13520bb88ba4Smrg    /* Allow access to DDC */
13530bb88ba4Smrg    if (pMga->is_G200ER) {
13540bb88ba4Smrg	 CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
13550bb88ba4Smrg     outMGAdac(MGA1064_GEN_IO_CTL2, ucData | 1);
13560bb88ba4Smrg    }
1357643b027fSmrg
1358643b027fSmrg    /* Initialize I2C buses - used by DDC if available */
1359643b027fSmrg    if (pMga->i2cInit) {
1360643b027fSmrg	pMga->i2cInit(pScrn);
1361643b027fSmrg    }
1362643b027fSmrg
1363643b027fSmrg    /* DDC for second head... */
1364643b027fSmrg    if (pMga->SecondCrtc && pMga->DDC_Bus2) {
13650bb88ba4Smrg	MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus2);
1366643b027fSmrg	from = "I2C";
1367643b027fSmrg    } else {
1368fe5e51b7Smrg	/* Its the first head... */
1369643b027fSmrg	if (pMga->DDC_Bus1) {
13700bb88ba4Smrg	    MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus1);
1371643b027fSmrg	    from = "I2C";
1372643b027fSmrg	}
1373643b027fSmrg	if (!MonInfo)
1374643b027fSmrg	    /* Read and output monitor info using DDC1 */
1375643b027fSmrg	    if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
13760bb88ba4Smrg		MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),
1377643b027fSmrg					  pMga->DDC1SetSpeed,
1378643b027fSmrg					  pMga->ddc1Read ) ;
1379643b027fSmrg		from = "DDC1";
1380643b027fSmrg	    }
1381643b027fSmrg	if (!MonInfo){
1382fe5e51b7Smrg	    vbeInfoPtr pVbe;
1383fe5e51b7Smrg	    if (xf86LoadSubModule(pScrn, "vbe")) {
1384643b027fSmrg		pVbe = VBEInit(NULL, pMga->pEnt->index);
1385643b027fSmrg		MonInfo = vbeDoEDID(pVbe, NULL);
1386643b027fSmrg		vbeFree(pVbe);
1387643b027fSmrg		from = "VBE";
1388fe5e51b7Smrg	    }
1389643b027fSmrg	}
1390643b027fSmrg    }
1391fe5e51b7Smrg
1392643b027fSmrg    if (MonInfo) {
1393643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s monitor info\n", from);
1394643b027fSmrg	xf86PrintEDID(MonInfo);
1395643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of monitor info\n");
1396643b027fSmrg    }
1397fe5e51b7Smrg
13980bb88ba4Smrg    /* Remove access to DDC */
13990bb88ba4Smrg    if (pMga->is_G200ER) {
14000bb88ba4Smrg	  CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
14010bb88ba4Smrg      outMGAdac(MGA1064_GEN_IO_CTL2, ucData & ~1);
14020bb88ba4Smrg    }
14030bb88ba4Smrg
1404643b027fSmrg    /* Restore previous state and unmap MGA memory and MMIO areas */
1405643b027fSmrg    MGARestore(pScrn);
1406643b027fSmrg    MGAUnmapMem(pScrn);
1407643b027fSmrg    /* Unmap vga memory if we mapped it */
1408643b027fSmrg    if (xf86IsPrimaryPci(pMga->PciInfo) && !pMga->FBDev) {
1409643b027fSmrg	vgaHWUnmapMem(pScrn);
1410643b027fSmrg    }
1411643b027fSmrg
1412643b027fSmrg    xf86SetDDCproperties(pScrn, MonInfo);
1413643b027fSmrg
1414643b027fSmrg    return MonInfo;
1415fe5e51b7Smrg}
1416fe5e51b7Smrg
1417fe5e51b7Smrg
1418fe5e51b7Smrgvoid
1419fe5e51b7SmrgMGAProbeDDC(ScrnInfoPtr pScrn, int index)
1420fe5e51b7Smrg{
1421fe5e51b7Smrg    vbeInfoPtr pVbe;
1422fe5e51b7Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1423fe5e51b7Smrg	pVbe = VBEInit(NULL,index);
1424fe5e51b7Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1425fe5e51b7Smrg	vbeFree(pVbe);
1426fe5e51b7Smrg    }
1427fe5e51b7Smrg}
1428fe5e51b7Smrg
1429fe5e51b7SmrgBool
1430fe5e51b7SmrgMGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
1431fe5e51b7Smrg{
1432fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1433fe5e51b7Smrg
1434fe5e51b7Smrg	if (!pMga->Maven) return FALSE;
1435fe5e51b7Smrg
1436fe5e51b7Smrg	/* FIXME: Using private interfaces for the moment until a more
1437fe5e51b7Smrg	 * flexible xf86I2CWriteRead() variant shows up for us
1438fe5e51b7Smrg	 *
1439fe5e51b7Smrg	 * MAVEN does _not_ like a start bit in the middle of its transaction
1440fe5e51b7Smrg	 * MAVEN does _not_ like ACK at the end of the transaction
1441fe5e51b7Smrg	 */
1442fe5e51b7Smrg
1443fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CStart(pMga->Maven_Bus, pMga->Maven->ByteTimeout)) return FALSE;
1444fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, MAVEN_READ)) return FALSE;
1445fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, reg)) return FALSE;
1446fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1447fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CGetByte(pMga->Maven, val, 0)) return FALSE;
1448fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1449fe5e51b7Smrg
1450fe5e51b7Smrg	return TRUE;
1451fe5e51b7Smrg}
1452fe5e51b7Smrg
1453fe5e51b7Smrg/* Mandatory */
1454fe5e51b7Smrgstatic Bool
1455fe5e51b7SmrgMGAPreInit(ScrnInfoPtr pScrn, int flags)
1456fe5e51b7Smrg{
1457fe5e51b7Smrg    MGAPtr pMga;
1458fe5e51b7Smrg    MessageType from;
1459fe5e51b7Smrg    int i;
1460fe5e51b7Smrg    double real;
1461fe5e51b7Smrg    int bytesPerPixel;
1462fe5e51b7Smrg    ClockRangePtr clockRanges;
1463fe5e51b7Smrg    const char *s;
1464fe5e51b7Smrg    int flags24;
1465fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
1466fe5e51b7Smrg    Bool Default;
1467fe5e51b7Smrg
1468fe5e51b7Smrg    /*
1469fe5e51b7Smrg     * Note: This function is only called once at server startup, and
1470fe5e51b7Smrg     * not at the start of each server generation.  This means that
1471fe5e51b7Smrg     * only things that are persistent across server generations can
1472fe5e51b7Smrg     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
1473fe5e51b7Smrg     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
1474fe5e51b7Smrg     * are too, and should be used for data that must persist across
1475fe5e51b7Smrg     * server generations.
1476fe5e51b7Smrg     *
1477fe5e51b7Smrg     * Per-generation data should be allocated with
1478fe5e51b7Smrg     * AllocateScreenPrivateIndex() from the ScreenInit() function.
1479fe5e51b7Smrg     */
1480fe5e51b7Smrg
1481fe5e51b7Smrg    /* Check the number of entities, and fail if it isn't one. */
1482fe5e51b7Smrg    if (pScrn->numEntities != 1)
1483fe5e51b7Smrg	return FALSE;
1484fe5e51b7Smrg
1485fe5e51b7Smrg
1486fe5e51b7Smrg    pMga = MGAPTR(pScrn);
1487fe5e51b7Smrg    /* Set here until dri is enabled */
14880bb88ba4Smrg#ifdef MGADRI
1489fe5e51b7Smrg    pMga->haveQuiescense = 1;
1490fe5e51b7Smrg#endif
1491fe5e51b7Smrg    /* Get the entity, and make sure it is PCI. */
1492fe5e51b7Smrg    pMga->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1493fe5e51b7Smrg    if (pMga->pEnt->location.type != BUS_PCI)
1494fe5e51b7Smrg	return FALSE;
1495fe5e51b7Smrg
1496fe5e51b7Smrg    /* Allocate an entity private if necessary */
1497fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {
1498fe5e51b7Smrg	pMgaEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1499fe5e51b7Smrg					MGAEntityIndex)->ptr;
1500fe5e51b7Smrg        pMga->entityPrivate = pMgaEnt;
1501fe5e51b7Smrg    }
1502fe5e51b7Smrg
1503fe5e51b7Smrg    /* Set pMga->device to the relevant Device section */
1504fe5e51b7Smrg    pMga->device = xf86GetDevFromEntity(pScrn->entityList[0],
1505fe5e51b7Smrg					pScrn->entityInstanceList[0]);
1506fe5e51b7Smrg
1507fe5e51b7Smrg    if (flags & PROBE_DETECT) {
1508fe5e51b7Smrg	MGAProbeDDC(pScrn, pMga->pEnt->index);
1509fe5e51b7Smrg	return TRUE;
1510fe5e51b7Smrg    }
1511fe5e51b7Smrg
1512fe5e51b7Smrg    /* The vgahw module should be loaded here when needed */
1513fe5e51b7Smrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
1514fe5e51b7Smrg	return FALSE;
1515fe5e51b7Smrg
1516fe5e51b7Smrg    /*
1517fe5e51b7Smrg     * Allocate a vgaHWRec
1518fe5e51b7Smrg     */
1519fe5e51b7Smrg    if (!vgaHWGetHWRec(pScrn))
1520fe5e51b7Smrg	return FALSE;
1521fe5e51b7Smrg
1522fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
1523fe5e51b7Smrg    /* Find the PCI info for this screen */
1524fe5e51b7Smrg    pMga->PciInfo = xf86GetPciInfoForEntity(pMga->pEnt->index);
1525fe5e51b7Smrg    pMga->PciTag = pciTag(pMga->PciInfo->bus, pMga->PciInfo->device,
1526fe5e51b7Smrg			  pMga->PciInfo->func);
1527fe5e51b7Smrg#endif
1528fe5e51b7Smrg
1529fe5e51b7Smrg    pMga->Primary = xf86IsPrimaryPci(pMga->PciInfo);
1530fe5e51b7Smrg
1531643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1532fe5e51b7Smrg    xf86SetOperatingState(resVgaIo, pMga->pEnt->index, ResUnusedOpr);
1533fe5e51b7Smrg    xf86SetOperatingState(resVgaMem, pMga->pEnt->index, ResDisableOpr);
1534643b027fSmrg#endif
1535fe5e51b7Smrg
1536fe5e51b7Smrg    /* Set pScrn->monitor */
1537fe5e51b7Smrg    pScrn->monitor = pScrn->confScreen->monitor;
1538fe5e51b7Smrg
1539fe5e51b7Smrg    /*
1540fe5e51b7Smrg     * Set the Chipset and ChipRev, allowing config file entries to
1541fe5e51b7Smrg     * override.
1542fe5e51b7Smrg     */
1543fe5e51b7Smrg    if (pMga->device->chipset && *pMga->device->chipset) {
1544fe5e51b7Smrg	pScrn->chipset = pMga->device->chipset;
1545fe5e51b7Smrg        pMga->Chipset = xf86StringToToken(MGAChipsets, pScrn->chipset);
1546fe5e51b7Smrg        from = X_CONFIG;
1547fe5e51b7Smrg    } else if (pMga->device->chipID >= 0) {
1548fe5e51b7Smrg	pMga->Chipset = pMga->device->chipID;
1549fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1550fe5e51b7Smrg	from = X_CONFIG;
1551fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
1552fe5e51b7Smrg		   pMga->Chipset);
1553fe5e51b7Smrg    } else {
1554fe5e51b7Smrg	from = X_PROBED;
1555fe5e51b7Smrg	pMga->Chipset = DEVICE_ID(pMga->PciInfo);
1556fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1557fe5e51b7Smrg    }
1558fe5e51b7Smrg
1559fe5e51b7Smrg    if (pMga->device->chipRev >= 0) {
1560fe5e51b7Smrg	pMga->ChipRev = pMga->device->chipRev;
1561fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
1562fe5e51b7Smrg		   pMga->ChipRev);
1563fe5e51b7Smrg    } else {
1564fe5e51b7Smrg	pMga->ChipRev = CHIP_REVISION(pMga->PciInfo);
1565fe5e51b7Smrg    }
1566fe5e51b7Smrg
1567fe5e51b7Smrg    /*
1568fe5e51b7Smrg     * This shouldn't happen because such problems should be caught in
1569fe5e51b7Smrg     * MGAProbe(), but check it just in case.
1570fe5e51b7Smrg     */
1571fe5e51b7Smrg    if (pScrn->chipset == NULL) {
1572fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1573fe5e51b7Smrg		   "ChipID 0x%04X is not recognised\n", pMga->Chipset);
1574fe5e51b7Smrg	return FALSE;
1575fe5e51b7Smrg    }
1576fe5e51b7Smrg    if (pMga->Chipset < 0) {
1577fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1578fe5e51b7Smrg		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
1579fe5e51b7Smrg	return FALSE;
1580fe5e51b7Smrg    }
1581fe5e51b7Smrg
1582fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"", pScrn->chipset);
1583fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG400) {
1584fe5e51b7Smrg	if (pMga->ChipRev >= 0x80)
1585fe5e51b7Smrg	    xf86ErrorF(" (G450)\n");
1586fe5e51b7Smrg	else
1587fe5e51b7Smrg	    xf86ErrorF(" (G400)\n");
1588fe5e51b7Smrg    } else {
1589fe5e51b7Smrg	xf86ErrorF("\n");
1590fe5e51b7Smrg    }
1591fe5e51b7Smrg
1592fe5e51b7Smrg    pMga->is_Gx50 = ((pMga->Chipset == PCI_CHIP_MGAG400) && (pMga->ChipRev >= 0x80))
1593fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG550);
1594fe5e51b7Smrg    pMga->is_G200SE = (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI)
1595fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG200_SE_B_PCI);
1596eda3803bSmrg    pMga->is_G200EV = (pMga->Chipset == PCI_CHIP_MGAG200_EV_PCI);
15976f68ce78Smrg    pMga->is_G200WB = (pMga->Chipset == PCI_CHIP_MGAG200_WINBOND_PCI)
15986f68ce78Smrg	|| (pMga->Chipset ==  PCI_CHIP_MGAG200_EW3_PCI);
159981f79626Smrg    pMga->is_G200EH = (pMga->Chipset == PCI_CHIP_MGAG200_EH_PCI)
160081f79626Smrg        ||  (pMga->Chipset ==  PCI_CHIP_MGAG200_EH3_PCI);
16010bb88ba4Smrg    pMga->is_G200ER = (pMga->Chipset == PCI_CHIP_MGAG200_ER_PCI);
1602fe5e51b7Smrg
1603fe5e51b7Smrg    pMga->DualHeadEnabled = FALSE;
1604fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {/* dual-head mode requested*/
1605fe5e51b7Smrg	if (
1606fe5e51b7Smrg	    !MGA_DH_NEEDS_HAL(pMga)) {
1607fe5e51b7Smrg	    pMga->DualHeadEnabled = TRUE;
1608fe5e51b7Smrg	} else if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1609fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1610fe5e51b7Smrg	 "This card requires the \"mga_hal\" module for dual-head operation\n"
1611fe5e51b7Smrg	 "\tIt can be found at the Matrox web site <http://www.matrox.com>\n");
1612fe5e51b7Smrg	}
1613fe5e51b7Smrg    }
1614fe5e51b7Smrg
1615acd6767fSmrg    /*
1616acd6767fSmrg     * Disable HW cursor by default on G200 server chips as these
1617acd6767fSmrg     * chips are often used with a remote graphics link which cannot
1618acd6767fSmrg     * display the HW cursor.
1619acd6767fSmrg     */
1620acd6767fSmrg    switch (pMga->Chipset) {
1621acd6767fSmrg    case PCI_CHIP_MGAG200_SE_A_PCI:
1622acd6767fSmrg    case PCI_CHIP_MGAG200_SE_B_PCI:
1623acd6767fSmrg    case PCI_CHIP_MGAG200_EV_PCI:
1624acd6767fSmrg    case PCI_CHIP_MGAG200_ER_PCI:
1625acd6767fSmrg    case PCI_CHIP_MGAG200_WINBOND_PCI:
1626acd6767fSmrg    case PCI_CHIP_MGAG200_EH_PCI:
162781f79626Smrg    case PCI_CHIP_MGAG200_EH3_PCI:
1628acd6767fSmrg	pMga->HWCursor = FALSE;
1629acd6767fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1630acd6767fSmrg		   "HW cursor is not supported with video redirection on"
1631acd6767fSmrg		   "G200 server chips.\n If you don't intend to use video "
1632acd6767fSmrg		   "redirection enable with Option \"HWCursor\" \"On\"\n");
1633acd6767fSmrg	break;
1634acd6767fSmrg    default:
1635acd6767fSmrg	pMga->HWCursor = TRUE;
1636acd6767fSmrg    }
1637acd6767fSmrg    from = X_DEFAULT;
1638acd6767fSmrg
1639acd6767fSmrg    /*
1640acd6767fSmrg     * The preferred method is to use the "hw cursor" option as a tri-state
1641acd6767fSmrg     * option, with the default set above.
1642acd6767fSmrg     */
1643acd6767fSmrg    if (xf86GetOptValBool(pMga->Options, OPTION_HW_CURSOR, &pMga->HWCursor))
1644acd6767fSmrg	from = X_CONFIG;
1645acd6767fSmrg
1646acd6767fSmrg    /* For compatibility, accept this too (as an override) */
1647acd6767fSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SW_CURSOR, FALSE)) {
1648acd6767fSmrg	from = X_CONFIG;
1649acd6767fSmrg	pMga->HWCursor = FALSE;
1650acd6767fSmrg    }
1651acd6767fSmrg
1652acd6767fSmrg    pMga->SecondCrtc = FALSE;
1653fe5e51b7Smrg    /*
1654fe5e51b7Smrg     * In case of DualHead, we need to determine if we are the 'master' head
1655fe5e51b7Smrg     * or the 'slave' head. In order to do that, at the end of the first
1656fe5e51b7Smrg     * initialisation, PrimInit is set as DONE to the shared entity. So that
1657fe5e51b7Smrg     * the second initialisation knows that something has been done before it.
1658fe5e51b7Smrg     * This always assume that the first device initialised is the master
1659fe5e51b7Smrg     * head, and the second the slave.
1660fe5e51b7Smrg     *
1661fe5e51b7Smrg     */
1662fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {      /* dual-head mode */
1663fe5e51b7Smrg        if (!xf86IsPrimInitDone(pScrn->entityList[0])) { /* Is it the first initialisation? */
1664fe5e51b7Smrg            /* First CRTC  */
1665fe5e51b7Smrg            pMgaEnt->pScrn_1 = pScrn;
1666fe5e51b7Smrg        } else if (pMga->DualHeadEnabled) {
1667fe5e51b7Smrg            /* Second CRTC */
1668fe5e51b7Smrg            pMga->SecondCrtc = TRUE;
1669fe5e51b7Smrg            pMga->HWCursor = FALSE;
1670acd6767fSmrg	    from = X_DEFAULT;
1671fe5e51b7Smrg            pMgaEnt->pScrn_2 = pScrn;
1672fe5e51b7Smrg            pScrn->AdjustFrame = MGAAdjustFrameCrtc2;
1673fe5e51b7Smrg	    /*
1674fe5e51b7Smrg	     * Fail initialization of second head if we are in MergeFB mode,
1675d2b10af6Smrg	     * since we do it ourselves.
1676fe5e51b7Smrg             */
1677fe5e51b7Smrg            if(pMgaEnt->pScrn_1 && MGAPTR(pMgaEnt->pScrn_1)->MergedFB) {
1678fe5e51b7Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1679fe5e51b7Smrg			   "Primary head in Merged framebuffer mode. \n"
1680fe5e51b7Smrg			   "Don't let Xfree try to manage the second head.\n"
1681fe5e51b7Smrg			   "Remove the second screen in the \"ServerLayout\"\n"
1682fe5e51b7Smrg			   "Section of the config file.");
1683fe5e51b7Smrg		return FALSE;
1684fe5e51b7Smrg	    }
1685fe5e51b7Smrg        } else {
1686fe5e51b7Smrg	    return FALSE;
1687fe5e51b7Smrg	}
1688fe5e51b7Smrg    }
1689acd6767fSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1690acd6767fSmrg	       pMga->HWCursor ? "HW" : "SW");
1691acd6767fSmrg
1692fe5e51b7Smrg
1693fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
16940bb88ba4Smrg#ifdef MGADRI
1695fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescenceShared;
1696fe5e51b7Smrg#endif
1697fe5e51b7Smrg    } else {                                              /* single-head mode */
16980bb88ba4Smrg#ifdef MGADRI
1699fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescence;
1700fe5e51b7Smrg#endif
1701fe5e51b7Smrg    }
1702fe5e51b7Smrg
17030bb88ba4Smrg    if (!(pMga->Options = malloc(sizeof(MGAOptions))))
1704eda3803bSmrg	return FALSE;
1705eda3803bSmrg    memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions));
1706eda3803bSmrg
1707eda3803bSmrg    /* ajv changes to reflect actual values. see sdk pp 3-2. */
1708eda3803bSmrg    /* these masks just get rid of the crap in the lower bits */
1709eda3803bSmrg
1710eda3803bSmrg    /* For the 2064 and older rev 1064, base0 is the MMIO and base1 is
1711eda3803bSmrg     * the framebuffer.
1712eda3803bSmrg     */
1713eda3803bSmrg
1714eda3803bSmrg    switch (pMga->chip_attribs->BARs) {
1715eda3803bSmrg    case old_BARs:
1716eda3803bSmrg	pMga->framebuffer_bar = 1;
1717eda3803bSmrg	pMga->io_bar = 0;
1718eda3803bSmrg	pMga->iload_bar = -1;
1719eda3803bSmrg	break;
1720eda3803bSmrg    case probe_BARs:
1721eda3803bSmrg	if (pMga->ChipRev < 3) {
1722eda3803bSmrg	    pMga->framebuffer_bar = 1;
1723eda3803bSmrg	    pMga->io_bar = 0;
1724eda3803bSmrg	    pMga->iload_bar = 2;
1725eda3803bSmrg	    break;
1726eda3803bSmrg	}
1727eda3803bSmrg	/* FALLTHROUGH */
1728eda3803bSmrg    case new_BARs:
1729eda3803bSmrg	pMga->framebuffer_bar = 0;
1730eda3803bSmrg	pMga->io_bar = 1;
1731eda3803bSmrg	pMga->iload_bar = 2;
1732eda3803bSmrg	break;
1733eda3803bSmrg    }
1734eda3803bSmrg
1735eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1736eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->regions[pMga->framebuffer_bar].base_addr;
1737eda3803bSmrg#else
1738eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->memBase[pMga->framebuffer_bar] & 0xff800000;
1739eda3803bSmrg#endif
1740eda3803bSmrg
1741eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n",
1742eda3803bSmrg	       (unsigned long)pMga->FbAddress);
1743eda3803bSmrg
1744eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1745eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lX\n",
1746eda3803bSmrg	       (unsigned long) pMga->PciInfo->regions[pMga->io_bar].base_addr);
1747eda3803bSmrg#else
1748eda3803bSmrg    pMga->IOAddress = pMga->PciInfo->memBase[pMga->io_bar] & 0xffffc000;
1749eda3803bSmrg
1750eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
1751eda3803bSmrg	       (unsigned long)pMga->IOAddress);
1752eda3803bSmrg#endif
1753eda3803bSmrg
1754eda3803bSmrg    if (pMga->iload_bar != -1) {
1755eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1756eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1757eda3803bSmrg		   "Pseudo-DMA transfer window at 0x%lX\n",
1758eda3803bSmrg		   (unsigned long) pMga->PciInfo->regions[pMga->iload_bar].base_addr);
1759eda3803bSmrg#else
1760eda3803bSmrg	if (pMga->PciInfo->memBase[2] != 0) {
1761eda3803bSmrg	    pMga->ILOADAddress = pMga->PciInfo->memBase[2] & 0xffffc000;
1762eda3803bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1763eda3803bSmrg		       "Pseudo-DMA transfer window at 0x%lX\n",
1764eda3803bSmrg		       (unsigned long)pMga->ILOADAddress);
1765eda3803bSmrg	}
1766eda3803bSmrg#endif
1767eda3803bSmrg    }
1768eda3803bSmrg
1769eda3803bSmrg#ifndef XSERVER_LIBPCIACCESS
1770eda3803bSmrg    /*
1771eda3803bSmrg     * Find the BIOS base.  Get it from the PCI config if possible.  Otherwise
17720bb88ba4Smrg     * use the VGA default.
1773eda3803bSmrg     */
1774eda3803bSmrg
1775eda3803bSmrg	/* details: rombase sdk pp 4-15 */
1776eda3803bSmrg	if (pMga->PciInfo->biosBase != 0) {
1777eda3803bSmrg	    pMga->BiosAddress = pMga->PciInfo->biosBase & 0xffff0000;
1778eda3803bSmrg	    pMga->BiosFrom = X_PROBED;
1779eda3803bSmrg	} else if (pMga->Primary) {
1780eda3803bSmrg	    pMga->BiosAddress = 0xc0000;
1781eda3803bSmrg	    pMga->BiosFrom = X_DEFAULT;
1782eda3803bSmrg	}
1783eda3803bSmrg    if (pMga->BiosAddress) {
1784eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom, "BIOS at 0x%lX\n",
1785eda3803bSmrg		   (unsigned long)pMga->BiosAddress);
1786eda3803bSmrg    }
1787eda3803bSmrg#endif
1788eda3803bSmrg
1789643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1790eda3803bSmrg    if (xf86RegisterResources(pMga->pEnt->index, NULL, ResExclusive)) {
1791eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1792eda3803bSmrg		"xf86RegisterResources() found resource conflicts\n");
1793eda3803bSmrg	MGAFreeRec(pScrn);
1794eda3803bSmrg	return FALSE;
1795eda3803bSmrg    }
1796643b027fSmrg#endif
1797eda3803bSmrg
1798fe5e51b7Smrg    /*
1799fe5e51b7Smrg     * The first thing we should figure out is the depth, bpp, etc.
1800fe5e51b7Smrg     * Our default depth is 8, so pass it to the helper function.
1801fe5e51b7Smrg     * We support both 24bpp and 32bpp layouts, so indicate that.
1802fe5e51b7Smrg     */
1803fe5e51b7Smrg
1804eda3803bSmrg    /* Prefer 32bpp */
1805eda3803bSmrg    flags24 = Support24bppFb | Support32bppFb | PreferConvert24to32;
1806fe5e51b7Smrg
1807fe5e51b7Smrg    if (pMga->SecondCrtc)
1808fe5e51b7Smrg	flags24 = Support32bppFb;
1809fe5e51b7Smrg
1810eda3803bSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_FBDEV, FALSE)) {
1811eda3803bSmrg	pMga->FBDev = TRUE;
1812eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1813eda3803bSmrg		"Using framebuffer device\n");
1814eda3803bSmrg	/* check for linux framebuffer device */
1815eda3803bSmrg	if (!xf86LoadSubModule(pScrn, "fbdevhw"))
1816eda3803bSmrg	    return FALSE;
1817eda3803bSmrg	if (!fbdevHWInit(pScrn, pMga->PciInfo, NULL))
1818eda3803bSmrg	    return FALSE;
1819eda3803bSmrg    }
1820eda3803bSmrg
1821eda3803bSmrg    /*
1822eda3803bSmrg     * If the user has specified the amount of memory in the XF86Config
1823eda3803bSmrg     * file, we respect that setting.
1824eda3803bSmrg     */
1825eda3803bSmrg    from = X_PROBED;
1826eda3803bSmrg    if (pMga->device->videoRam != 0) {
1827eda3803bSmrg	pScrn->videoRam = pMga->device->videoRam;
1828eda3803bSmrg	from = X_CONFIG;
1829eda3803bSmrg    } else if (pMga->FBDev) {
1830eda3803bSmrg	pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024;
1831eda3803bSmrg    } else {
1832eda3803bSmrg	pScrn->videoRam = MGACountRam(pScrn);
1833eda3803bSmrg    }
1834eda3803bSmrg
1835eda3803bSmrg    if (pMga->is_G200SE && pScrn->videoRam < 2048)
1836fe5e51b7Smrg	pScrn->confScreen->defaultdepth = 16;
1837fe5e51b7Smrg
1838fe5e51b7Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
1839fe5e51b7Smrg	return FALSE;
1840fe5e51b7Smrg    } else {
1841fe5e51b7Smrg	/* Check that the returned depth is one we support */
1842fe5e51b7Smrg	switch (pScrn->depth) {
1843fe5e51b7Smrg	case 8:
1844fe5e51b7Smrg	case 16:
1845fe5e51b7Smrg	case 24:
1846fe5e51b7Smrg	    /* OK */
1847fe5e51b7Smrg	    break;
1848eda3803bSmrg	case 15:
1849eda3803bSmrg	    if (pMga->Chipset != PCI_CHIP_MGAG200_SE_A_PCI)
1850eda3803bSmrg		break;
1851fe5e51b7Smrg	default:
1852fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1853fe5e51b7Smrg		       "Given depth (%d) is not supported by this driver\n",
1854fe5e51b7Smrg		       pScrn->depth);
1855fe5e51b7Smrg	    return FALSE;
1856fe5e51b7Smrg	}
1857fe5e51b7Smrg    }
1858fe5e51b7Smrg    xf86PrintDepthBpp(pScrn);
1859fe5e51b7Smrg
1860fe5e51b7Smrg    /*
1861fe5e51b7Smrg     * This must happen after pScrn->display has been set because
1862fe5e51b7Smrg     * xf86SetWeight references it.
1863fe5e51b7Smrg     */
1864fe5e51b7Smrg    if (pScrn->depth > 8) {
1865fe5e51b7Smrg	/* The defaults are OK for us */
1866fe5e51b7Smrg	rgb zeros = {0, 0, 0};
1867fe5e51b7Smrg
1868fe5e51b7Smrg	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1869fe5e51b7Smrg	    return FALSE;
1870fe5e51b7Smrg	} else {
1871fe5e51b7Smrg	    /* XXX check that weight returned is supported */
1872fe5e51b7Smrg            ;
1873fe5e51b7Smrg        }
1874fe5e51b7Smrg    }
1875fe5e51b7Smrg
1876fe5e51b7Smrg    bytesPerPixel = pScrn->bitsPerPixel / 8;
1877fe5e51b7Smrg
1878fe5e51b7Smrg    /* We use a programmable clock */
1879fe5e51b7Smrg    pScrn->progClock = TRUE;
1880fe5e51b7Smrg
1881fe5e51b7Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
1882fe5e51b7Smrg    xf86CollectOptions(pScrn, NULL);
1883fe5e51b7Smrg
1884fe5e51b7Smrg    /* Process the options */
1885fe5e51b7Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options);
1886fe5e51b7Smrg
1887fe5e51b7Smrg    if (pMga->is_G200SE) {
1888fe5e51b7Smrg        /* Disable MTRR support on PCIe systems */
1889fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1890fe5e51b7Smrg	uint32_t temp;
1891fe5e51b7Smrg
1892fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & temp, 0xDC);
1893fe5e51b7Smrg#else
1894fe5e51b7Smrg        CARD32 temp = pciReadLong(pMga->PciTag, 0xDC);
1895fe5e51b7Smrg#endif
1896fe5e51b7Smrg
1897fe5e51b7Smrg        if ((temp & 0x0000FF00) != 0x0) {
1898fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling MTRR support.\n");
1899fe5e51b7Smrg            pScrn->options = xf86ReplaceBoolOption(pScrn->options, "MTRR", FALSE);
1900fe5e51b7Smrg        }
1901fe5e51b7Smrg    }
1902eda3803bSmrg
1903eda3803bSmrg    if (pMga->is_G200WB && xf86ReturnOptValBool(pMga->Options, OPTION_KVM, TRUE)) {
1904eda3803bSmrg        pMga->KVM = TRUE;
1905eda3803bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling KVM\n");
1906eda3803bSmrg    }
1907fe5e51b7Smrg
1908fe5e51b7Smrg#if !defined(__powerpc__)
1909fe5e51b7Smrg    pMga->softbooted = FALSE;
1910fe5e51b7Smrg    Default = (pMga->chip_attribs->dual_head_possible
1911fe5e51b7Smrg	       && !pMga->Primary && !pMga->SecondCrtc);
1912fe5e51b7Smrg
1913fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_INT10, Default) &&
1914fe5e51b7Smrg        xf86LoadSubModule(pScrn, "int10")) {
1915fe5e51b7Smrg        xf86Int10InfoPtr pInt;
1916fe5e51b7Smrg
1917fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
1918fe5e51b7Smrg        pInt = xf86InitInt10(pMga->pEnt->index);
1919fe5e51b7Smrg	if (pInt) pMga->softbooted = TRUE;
1920fe5e51b7Smrg        xf86FreeInt10(pInt);
1921fe5e51b7Smrg    }
1922fe5e51b7Smrg#endif
1923fe5e51b7Smrg
1924fe5e51b7Smrg    /* Set the bits per RGB for 8bpp mode */
1925fe5e51b7Smrg    if (pScrn->depth == 8)
1926fe5e51b7Smrg	pScrn->rgbBits = 8;
1927fe5e51b7Smrg
19280bb88ba4Smrg#ifdef MGADRI
1929fe5e51b7Smrg    from = X_DEFAULT;
1930fe5e51b7Smrg    pMga->agpMode = MGA_DEFAULT_AGP_MODE;
1931fe5e51b7Smrg
1932fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1933fe5e51b7Smrg			     OPTION_AGP_MODE, &(pMga->agpMode))) {
1934fe5e51b7Smrg       if (pMga->agpMode < 1) {
1935fe5e51b7Smrg	  pMga->agpMode = 1;
1936fe5e51b7Smrg       }
1937fe5e51b7Smrg       if (pMga->agpMode > MGA_MAX_AGP_MODE) {
1938fe5e51b7Smrg	  pMga->agpMode = MGA_MAX_AGP_MODE;
1939fe5e51b7Smrg       }
1940fe5e51b7Smrg       from = X_CONFIG;
1941fe5e51b7Smrg    }
1942fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1943fe5e51b7Smrg                             OPTION_AGP_SIZE, &(pMga->agpSize))) {
1944fe5e51b7Smrg                             /* check later */
1945fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, from, "Using %d MB of AGP memory\n",
1946fe5e51b7Smrg	          pMga->agpSize);
1947fe5e51b7Smrg    }
1948fe5e51b7Smrg
1949fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n",
1950fe5e51b7Smrg	       pMga->agpMode);
1951fe5e51b7Smrg
1952fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OLDDMA, FALSE)) {
1953fe5e51b7Smrg	pMga->useOldDmaInit = TRUE;
1954fe5e51b7Smrg    }
1955fe5e51b7Smrg
1956fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCIDMA, FALSE)) {
1957fe5e51b7Smrg	pMga->forcePciDma = TRUE;
1958fe5e51b7Smrg    }
1959fe5e51b7Smrg#endif
1960fe5e51b7Smrg
1961fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) {
1962fe5e51b7Smrg	pMga->NoAccel = TRUE;
1963fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1964fe5e51b7Smrg    } else {
1965fe5e51b7Smrg	int from = X_DEFAULT;
1966fe5e51b7Smrg#ifdef USE_EXA
196781f79626Smrg	const char *s = xf86GetOptValString(pMga->Options, OPTION_ACCELMETHOD);
1968fe5e51b7Smrg#endif
1969fe5e51b7Smrg	pMga->NoAccel = FALSE;
1970fe5e51b7Smrg	pMga->Exa = FALSE;
1971fe5e51b7Smrg#ifdef USE_EXA
197281f79626Smrg#ifndef USE_XAA
197381f79626Smrg	pMga->Exa = TRUE;
197481f79626Smrg#endif
1975fe5e51b7Smrg	if (!xf86NameCmp(s, "EXA")) {
1976fe5e51b7Smrg	    pMga->Exa = TRUE;
1977fe5e51b7Smrg	    from = X_CONFIG;
1978fe5e51b7Smrg	}
1979fe5e51b7Smrg#endif
1980fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
1981fe5e51b7Smrg		   pMga->Exa ? "EXA" : "XAA");
1982fe5e51b7Smrg    }
1983fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) {
1984fe5e51b7Smrg	pMga->UsePCIRetry = TRUE;
1985fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
1986fe5e51b7Smrg    }
1987fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
1988fe5e51b7Smrg	pMga->SyncOnGreen = TRUE;
1989fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
1990fe5e51b7Smrg    }
1991fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHOWCACHE, FALSE)) {
1992fe5e51b7Smrg	pMga->ShowCache = TRUE;
1993fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
1994fe5e51b7Smrg    }
1995fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MGA_SDRAM, FALSE)) {
1996fe5e51b7Smrg	pMga->HasSDRAM = TRUE;
1997fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Has SDRAM\n");
1998fe5e51b7Smrg    }
1999fe5e51b7Smrg    if (xf86GetOptValFreq(pMga->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
2000fe5e51b7Smrg	pMga->MemClk = (int)(real * 1000.0);
2001fe5e51b7Smrg    }
2002fe5e51b7Smrg
2003fe5e51b7Smrg    if(xf86GetOptValInteger(pMga->Options, OPTION_VIDEO_KEY, &(pMga->videoKey))) {
2004fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
2005fe5e51b7Smrg				pMga->videoKey);
2006fe5e51b7Smrg    } else {
2007fe5e51b7Smrg	pMga->videoKey =  (1 << pScrn->offset.red) |
2008fe5e51b7Smrg			  (1 << pScrn->offset.green) |
2009fe5e51b7Smrg        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
2010fe5e51b7Smrg    }
2011fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHADOW_FB, FALSE)) {
2012fe5e51b7Smrg	pMga->ShadowFB = TRUE;
2013fe5e51b7Smrg	pMga->NoAccel = TRUE;
2014fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2015fe5e51b7Smrg		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
2016fe5e51b7Smrg    }
2017fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OVERCLOCK_MEM, FALSE)) {
2018fe5e51b7Smrg	pMga->OverclockMem = TRUE;
2019fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overclocking memory\n");
2020fe5e51b7Smrg    }
2021fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_TEXTURED_VIDEO, FALSE)) {
2022fe5e51b7Smrg	pMga->TexturedVideo = TRUE;
2023fe5e51b7Smrg    }
2024fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MERGEDFB, FALSE)) {
2025fe5e51b7Smrg        if(!MGAISGx50(pMga)) {
2026fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2027fe5e51b7Smrg                "\"Merged Framebuffer\" mode only supported on G450 and G550 boards.\n");
2028fe5e51b7Smrg        } else {
2029fe5e51b7Smrg            {
2030fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2031fe5e51b7Smrg                    "HALLib not loaded! NOT using \"Merged Framebuffer\" mode.\n");
2032fe5e51b7Smrg            } /* MGA_NOT_HAL */
2033fe5e51b7Smrg        } /* ISMGAGx50() */
2034fe5e51b7Smrg    }
2035fe5e51b7Smrg    if (pMga->FBDev) {
2036fe5e51b7Smrg	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
2037fe5e51b7Smrg	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
2038fe5e51b7Smrg	pScrn->EnterVT       = MGAEnterVTFBDev;
2039fe5e51b7Smrg	pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
2040fe5e51b7Smrg	pScrn->ValidMode     = fbdevHWValidModeWeak();
2041fe5e51b7Smrg    }
2042fe5e51b7Smrg    pMga->Rotate = 0;
2043fe5e51b7Smrg    if ((s = xf86GetOptValString(pMga->Options, OPTION_ROTATE))) {
2044fe5e51b7Smrg        if(!pMga->MergedFB) {
2045fe5e51b7Smrg            if(!xf86NameCmp(s, "CW")) {
2046fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2047fe5e51b7Smrg                pMga->NoAccel = TRUE;
2048fe5e51b7Smrg                pMga->HWCursor = FALSE;
2049fe5e51b7Smrg                pMga->Rotate = 1;
2050fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2051fe5e51b7Smrg                        "Rotating screen clockwise - acceleration disabled\n");
2052fe5e51b7Smrg            } else
2053fe5e51b7Smrg            if(!xf86NameCmp(s, "CCW")) {
2054fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2055fe5e51b7Smrg                pMga->NoAccel = TRUE;
2056fe5e51b7Smrg                pMga->HWCursor = FALSE;
2057fe5e51b7Smrg                pMga->Rotate = -1;
2058fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2059fe5e51b7Smrg                        "Rotating screen counter clockwise - acceleration disabled\n");
2060fe5e51b7Smrg            } else {
2061fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2062fe5e51b7Smrg                        "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
2063fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2064fe5e51b7Smrg                        "Valid options are \"CW\" or \"CCW\"\n");
2065fe5e51b7Smrg            }
2066fe5e51b7Smrg        } else {
2067fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2068fe5e51b7Smrg                " -- Rotation disabled.\n");
2069fe5e51b7Smrg        }
2070fe5e51b7Smrg    }
2071fe5e51b7Smrg
20720bb88ba4Smrg    /* Load XAA if needed */
20730bb88ba4Smrg    if (!pMga->NoAccel) {
20740bb88ba4Smrg#ifdef USE_EXA
20750bb88ba4Smrg	if (pMga->Exa) {
20760bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "exa")) {
20770bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
20780bb88ba4Smrg		           "Falling back to shadowfb\n");
20790bb88ba4Smrg		pMga->ShadowFB = TRUE;
20800bb88ba4Smrg		pMga->NoAccel = TRUE;
20810bb88ba4Smrg	    }
20820bb88ba4Smrg	} else {
20830bb88ba4Smrg#endif
2084acd6767fSmrg#ifdef USE_XAA
20850bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
20860bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
20870bb88ba4Smrg		           "Falling back to shadowfb\n");
20880bb88ba4Smrg		pMga->ShadowFB = TRUE;
20890bb88ba4Smrg		pMga->NoAccel = TRUE;
20900bb88ba4Smrg	    }
20910bb88ba4Smrg#endif
20920bb88ba4Smrg#ifdef USE_EXA
20930bb88ba4Smrg	}
20940bb88ba4Smrg#endif
20950bb88ba4Smrg    }
20960bb88ba4Smrg
2097fe5e51b7Smrg    switch (pMga->Chipset) {
2098fe5e51b7Smrg    case PCI_CHIP_MGA2064:
2099fe5e51b7Smrg    case PCI_CHIP_MGA2164:
2100fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
2101fe5e51b7Smrg	MGA2064SetupFuncs(pScrn);
2102fe5e51b7Smrg	break;
2103fe5e51b7Smrg    case PCI_CHIP_MGA1064:
2104fe5e51b7Smrg    case PCI_CHIP_MGAG100:
2105fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
2106fe5e51b7Smrg    case PCI_CHIP_MGAG200:
2107fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
2108fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_A_PCI:
2109fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_B_PCI:
2110eda3803bSmrg    case PCI_CHIP_MGAG200_WINBOND_PCI:
21116f68ce78Smrg    case PCI_CHIP_MGAG200_EW3_PCI:
2112eda3803bSmrg    case PCI_CHIP_MGAG200_EV_PCI:
2113a31a186aSmrg    case PCI_CHIP_MGAG200_EH_PCI:
21140bb88ba4Smrg    case PCI_CHIP_MGAG200_ER_PCI:
211581f79626Smrg    case PCI_CHIP_MGAG200_EH3_PCI:
2116fe5e51b7Smrg    case PCI_CHIP_MGAG400:
2117fe5e51b7Smrg    case PCI_CHIP_MGAG550:
2118fe5e51b7Smrg	MGAGSetupFuncs(pScrn);
2119fe5e51b7Smrg	break;
2120fe5e51b7Smrg    }
2121fe5e51b7Smrg
2122fe5e51b7Smrg    /*
2123fe5e51b7Smrg     * Read the BIOS data struct
2124fe5e51b7Smrg     */
2125fe5e51b7Smrg
2126fe5e51b7Smrg#if defined(__alpha__) && !defined(XSERVER_LIBPCIACCESS)
2127fe5e51b7Smrg    /*
2128fe5e51b7Smrg     * Some old Digital-OEMed Matrox Millennium I cards have a VGA
2129fe5e51b7Smrg     * disable switch.  If the disable is on, we can't read the BIOS,
2130fe5e51b7Smrg     * and pMga->BiosAddress = 0x0. The disable switch is needed to
2131fe5e51b7Smrg     * allow multi-head operation with brain-dead console code... ;-}
2132fe5e51b7Smrg     */
2133fe5e51b7Smrg
2134fe5e51b7Smrg    if ((pMga->BiosAddress == 0) && !xf86IsPrimaryPci(pMga->PciInfo))
2135fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom,
2136fe5e51b7Smrg                   "BIOS not found, skipping read\n");
2137fe5e51b7Smrg    else
2138fe5e51b7Smrg#endif
2139fe5e51b7Smrg    mga_read_and_process_bios( pScrn );
2140fe5e51b7Smrg
2141fe5e51b7Smrg
2142fe5e51b7Smrg    /* Since the BIOS can swap DACs during the initialisation of G550, we need to
2143fe5e51b7Smrg     * store which DAC this instance of the driver is taking care of. This is done
2144fe5e51b7Smrg     * by checking a flag stored in the ROM by the BIOS at a fixed address. */
2145fe5e51b7Smrg
2146fe5e51b7Smrg    if (!pMga->SecondCrtc)
2147fe5e51b7Smrg        pMga->SecondOutput = FALSE;
2148fe5e51b7Smrg    else
2149fe5e51b7Smrg        pMga->SecondOutput = TRUE;
2150fe5e51b7Smrg
2151fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG550) {
2152fe5e51b7Smrg        if (!pMga->SecondCrtc) {
2153fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? TRUE : FALSE;
2154fe5e51b7Smrg        } else {
2155fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? FALSE : TRUE;
2156fe5e51b7Smrg        }
2157fe5e51b7Smrg    }
2158fe5e51b7Smrg
2159fe5e51b7Smrg
2160fe5e51b7Smrg    /* HW bpp matches reported bpp */
2161fe5e51b7Smrg    pMga->HwBpp = pScrn->bitsPerPixel;
2162fe5e51b7Smrg
2163fe5e51b7Smrg    /*
2164fe5e51b7Smrg     * Reset card if it isn't primary one
2165fe5e51b7Smrg     */
21660bb88ba4Smrg    if ( (!pMga->Primary && !pMga->FBDev) )
2167fe5e51b7Smrg        MGASoftReset(pScrn);
2168fe5e51b7Smrg
2169fe5e51b7Smrg    if (pScrn->videoRam == 0) {
2170fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2171fe5e51b7Smrg		   "Unable to detect video RAM.\n");
2172fe5e51b7Smrg	return FALSE;
2173fe5e51b7Smrg    }
2174fe5e51b7Smrg
2175fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
2176fe5e51b7Smrg       /* This takes gives either half or 8 meg to the second head
2177fe5e51b7Smrg	* whichever is less. */
2178fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2179fe5e51b7Smrg	    Bool UseHalf = FALSE;
2180fe5e51b7Smrg	    int adjust;
2181fe5e51b7Smrg
2182fe5e51b7Smrg	    xf86GetOptValBool(pMga->Options, OPTION_CRTC2HALF, &UseHalf);
2183fe5e51b7Smrg	    adjust = pScrn->videoRam / 2;
2184fe5e51b7Smrg
2185fe5e51b7Smrg	    if (UseHalf == TRUE ||
2186fe5e51b7Smrg		  xf86GetOptValInteger(pMga->Options, OPTION_CRTC2RAM, &adjust)) {
2187fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2188fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2189fe5e51b7Smrg			   adjust);
2190fe5e51b7Smrg	    } else {
2191fe5e51b7Smrg	        adjust = min(adjust, 8192);
2192fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2193fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2194fe5e51b7Smrg			   adjust);
2195fe5e51b7Smrg	    }
2196fe5e51b7Smrg	    pMgaEnt->mastervideoRam = pScrn->videoRam - adjust;
2197fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->mastervideoRam;
2198fe5e51b7Smrg	    pMgaEnt->slavevideoRam = adjust;
2199fe5e51b7Smrg	    pMgaEnt->masterFbAddress = pMga->FbAddress;
2200fe5e51b7Smrg	    pMga->FbMapSize =
2201fe5e51b7Smrg	       pMgaEnt->masterFbMapSize = pScrn->videoRam * 1024;
2202fe5e51b7Smrg	    pMgaEnt->slaveFbAddress = pMga->FbAddress +
2203fe5e51b7Smrg	       pMgaEnt->masterFbMapSize;
2204fe5e51b7Smrg	    pMgaEnt->slaveFbMapSize = pMgaEnt->slavevideoRam * 1024;
2205fe5e51b7Smrg	    pMga->realSrcOrg = pMga->SrcOrg = 0;
2206fe5e51b7Smrg	    pMga->DstOrg = 0;
2207fe5e51b7Smrg	} else {
2208fe5e51b7Smrg	    pMga->FbAddress = pMgaEnt->slaveFbAddress;
2209fe5e51b7Smrg	    pMga->FbMapSize = pMgaEnt->slaveFbMapSize;
2210fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->slavevideoRam;
2211fe5e51b7Smrg	    pMga->DstOrg = pMga->realSrcOrg =
2212fe5e51b7Smrg	      pMgaEnt->slaveFbAddress - pMgaEnt->masterFbAddress;
2213fe5e51b7Smrg	    pMga->SrcOrg = 0; /* This is not stored in hw format!! */
2214fe5e51b7Smrg	}
2215fe5e51b7Smrg        pMgaEnt->refCount++;
2216fe5e51b7Smrg    } else {
2217fe5e51b7Smrg        /* Normal Handling of video ram etc */
2218fe5e51b7Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
2219fe5e51b7Smrg        switch(pMga->Chipset) {
2220fe5e51b7Smrg	  case PCI_CHIP_MGAG550:
2221fe5e51b7Smrg	  case PCI_CHIP_MGAG400:
2222fe5e51b7Smrg	  case PCI_CHIP_MGAG200:
2223fe5e51b7Smrg	  case PCI_CHIP_MGAG200_PCI:
2224fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_A_PCI:
2225fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_B_PCI:
2226eda3803bSmrg          case PCI_CHIP_MGAG200_WINBOND_PCI:
22276f68ce78Smrg	  case PCI_CHIP_MGAG200_EW3_PCI:
2228eda3803bSmrg	  case PCI_CHIP_MGAG200_EV_PCI:
22296f68ce78Smrg	  case PCI_CHIP_MGAG200_EH_PCI:
223081f79626Smrg	  case PCI_CHIP_MGAG200_EH3_PCI:
22310bb88ba4Smrg	  case PCI_CHIP_MGAG200_ER_PCI:
2232fe5e51b7Smrg	    pMga->SrcOrg = 0;
2233fe5e51b7Smrg	    pMga->DstOrg = 0;
2234fe5e51b7Smrg	    break;
2235fe5e51b7Smrg	  default:
2236fe5e51b7Smrg	    break;
2237fe5e51b7Smrg	}
2238fe5e51b7Smrg    }
2239fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
2240fe5e51b7Smrg               pScrn->videoRam);
2241fe5e51b7Smrg
2242fe5e51b7Smrg   /* Set the bpp shift value */
2243fe5e51b7Smrg    pMga->BppShifts[0] = 0;
2244fe5e51b7Smrg    pMga->BppShifts[1] = 1;
2245fe5e51b7Smrg    pMga->BppShifts[2] = 0;
2246fe5e51b7Smrg    pMga->BppShifts[3] = 2;
2247fe5e51b7Smrg
2248fe5e51b7Smrg    /*
2249fe5e51b7Smrg     * fill MGAdac struct
2250fe5e51b7Smrg     * Warning: currently, it should be after RAM counting
2251fe5e51b7Smrg     */
2252fe5e51b7Smrg    (*pMga->PreInit)(pScrn);
2253fe5e51b7Smrg
2254fe5e51b7Smrg#if !defined(__powerpc__)
2255fe5e51b7Smrg
2256fe5e51b7Smrg    /* Read and print the Monitor DDC info */
2257fe5e51b7Smrg    pScrn->monitor->DDC = MGAdoDDC(pScrn);
2258fe5e51b7Smrg#endif /* !__powerpc__ */
2259fe5e51b7Smrg
2260fe5e51b7Smrg    if (!pScrn->monitor->DDC && pMga->is_G200SE) {
2261fe5e51b7Smrg	/* Jam in ranges big enough for 1024x768 */
2262fe5e51b7Smrg	if (!pScrn->monitor->nHsync) {
2263fe5e51b7Smrg	    pScrn->monitor->nHsync = 1;
2264fe5e51b7Smrg	    pScrn->monitor->hsync[0].lo = 31.5;
2265fe5e51b7Smrg	    pScrn->monitor->hsync[0].hi = 48.0;
2266fe5e51b7Smrg	}
2267fe5e51b7Smrg	if (!pScrn->monitor->nVrefresh) {
2268fe5e51b7Smrg	    pScrn->monitor->nVrefresh = 1;
2269fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].lo = 56.0;
2270fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].hi = 75.0;
2271fe5e51b7Smrg	}
2272fe5e51b7Smrg    }
2273fe5e51b7Smrg
2274fe5e51b7Smrg
2275fe5e51b7Smrg    /*
2276fe5e51b7Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
2277fe5e51b7Smrg     * here.
2278fe5e51b7Smrg     */
2279fe5e51b7Smrg
2280fe5e51b7Smrg    {
2281fe5e51b7Smrg	Gamma zeros = {0.0, 0.0, 0.0};
2282fe5e51b7Smrg
2283fe5e51b7Smrg	if (!xf86SetGamma(pScrn, zeros)) {
2284fe5e51b7Smrg	    return FALSE;
2285fe5e51b7Smrg	}
2286fe5e51b7Smrg    }
2287fe5e51b7Smrg
2288fe5e51b7Smrg
2289fe5e51b7Smrg    /* XXX Set HW cursor use */
2290fe5e51b7Smrg
2291fe5e51b7Smrg    /* Set the min pixel clock */
2292fe5e51b7Smrg    pMga->MinClock = 17750;
2293eda3803bSmrg    if (pMga->is_G200WB){
2294eda3803bSmrg	pMga->MinClock = 18750;
2295eda3803bSmrg    }
2296fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
2297fe5e51b7Smrg	       pMga->MinClock / 1000);
2298fe5e51b7Smrg    /*
2299fe5e51b7Smrg     * If the user has specified ramdac speed in the XF86Config
2300fe5e51b7Smrg     * file, we respect that setting.
2301fe5e51b7Smrg     */
2302fe5e51b7Smrg    if (pMga->device->dacSpeeds[0]) {
2303fe5e51b7Smrg	int speed = 0;
2304fe5e51b7Smrg
2305fe5e51b7Smrg	switch (pScrn->bitsPerPixel) {
2306fe5e51b7Smrg	case 8:
2307fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP8];
2308fe5e51b7Smrg	   break;
2309fe5e51b7Smrg	case 16:
2310fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP16];
2311fe5e51b7Smrg	   break;
2312fe5e51b7Smrg	case 24:
2313fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP24];
2314fe5e51b7Smrg	   break;
2315fe5e51b7Smrg	case 32:
2316fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP32];
2317fe5e51b7Smrg	   break;
2318fe5e51b7Smrg	}
2319fe5e51b7Smrg	if (speed == 0)
2320fe5e51b7Smrg	    pMga->MaxClock = pMga->device->dacSpeeds[0];
2321fe5e51b7Smrg	else
2322fe5e51b7Smrg	    pMga->MaxClock = speed;
2323fe5e51b7Smrg	from = X_CONFIG;
2324fe5e51b7Smrg    } else {
2325fe5e51b7Smrg	pMga->MaxClock = pMga->Dac.maxPixelClock;
2326fe5e51b7Smrg	from = pMga->Dac.ClockFrom;
2327fe5e51b7Smrg    }
2328fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) {
2329fe5e51b7Smrg        /* Override on 2nd crtc */
2330fe5e51b7Smrg	if ((pMga->ChipRev >= 0x80) || (pMga->Chipset == PCI_CHIP_MGAG550)) {
2331fe5e51b7Smrg	    /* G450, G550 */
2332fe5e51b7Smrg	    pMga->MaxClock = 234000;
2333fe5e51b7Smrg	} else {
2334fe5e51b7Smrg	    pMga->MaxClock = 135000;
2335fe5e51b7Smrg	}
2336fe5e51b7Smrg    }
2337fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
2338fe5e51b7Smrg	       pMga->MaxClock / 1000);
2339fe5e51b7Smrg    /*
2340fe5e51b7Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
2341fe5e51b7Smrg     * and what sort of modes they can be used for.
2342fe5e51b7Smrg     */
2343fe5e51b7Smrg    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
2344fe5e51b7Smrg    clockRanges->next = NULL;
2345fe5e51b7Smrg    clockRanges->minClock = pMga->MinClock;
2346fe5e51b7Smrg    clockRanges->maxClock = pMga->MaxClock;
2347fe5e51b7Smrg    clockRanges->clockIndex = -1;		/* programmable */
2348fe5e51b7Smrg    clockRanges->interlaceAllowed = TRUE;
2349fe5e51b7Smrg    clockRanges->doubleScanAllowed = TRUE;
2350fe5e51b7Smrg    if (pMga->SecondCrtc == TRUE)
2351fe5e51b7Smrg	clockRanges->interlaceAllowed = FALSE;
2352fe5e51b7Smrg
2353fe5e51b7Smrg    clockRanges->ClockMulFactor = 1;
2354fe5e51b7Smrg    clockRanges->ClockDivFactor = 1;
2355fe5e51b7Smrg
2356fe5e51b7Smrg    /* Only set MemClk if appropriate for the ramdac */
2357fe5e51b7Smrg    if (pMga->Dac.SetMemClk) {
2358fe5e51b7Smrg	if (pMga->MemClk == 0) {
2359fe5e51b7Smrg	    pMga->MemClk = pMga->Dac.MemoryClock;
2360fe5e51b7Smrg	    from = pMga->Dac.MemClkFrom;
2361fe5e51b7Smrg	} else
2362fe5e51b7Smrg	    from = X_CONFIG;
2363fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "MCLK used is %.1f MHz\n",
2364fe5e51b7Smrg		   pMga->MemClk / 1000.0);
2365fe5e51b7Smrg    }
2366fe5e51b7Smrg
2367fe5e51b7Smrg    /*
2368fe5e51b7Smrg     * xf86ValidateModes will check that the mode HTotal and VTotal values
2369fe5e51b7Smrg     * don't exceed the chipset's limit if pScrn->maxHValue and
2370fe5e51b7Smrg     * pScrn->maxVValue are set.  Since our MGAValidMode() already takes
2371fe5e51b7Smrg     * care of this, we don't worry about setting them here.
2372fe5e51b7Smrg     */
2373fe5e51b7Smrg    {
2374fe5e51b7Smrg	int Pitches1[] =
2375fe5e51b7Smrg	  {640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
2376fe5e51b7Smrg	int Pitches2[] =
2377fe5e51b7Smrg	  {512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664,
2378fe5e51b7Smrg		1920, 2048, 0};
2379fe5e51b7Smrg	int *linePitches = NULL;
2380fe5e51b7Smrg	int minPitch = 256;
2381fe5e51b7Smrg	int maxPitch = 2048;
2382fe5e51b7Smrg
2383fe5e51b7Smrg        switch(pMga->Chipset) {
2384fe5e51b7Smrg	case PCI_CHIP_MGA2064:
2385fe5e51b7Smrg	   if (!pMga->NoAccel) {
23860bb88ba4Smrg		linePitches = malloc(sizeof(Pitches1));
2387fe5e51b7Smrg		memcpy(linePitches, Pitches1, sizeof(Pitches1));
2388fe5e51b7Smrg		minPitch = maxPitch = 0;
2389fe5e51b7Smrg	   }
2390fe5e51b7Smrg	   break;
2391fe5e51b7Smrg	case PCI_CHIP_MGA2164:
2392fe5e51b7Smrg	case PCI_CHIP_MGA2164_AGP:
2393fe5e51b7Smrg	case PCI_CHIP_MGA1064:
2394fe5e51b7Smrg	   if (!pMga->NoAccel) {
23950bb88ba4Smrg		linePitches = malloc(sizeof(Pitches2));
2396fe5e51b7Smrg		memcpy(linePitches, Pitches2, sizeof(Pitches2));
2397fe5e51b7Smrg		minPitch = maxPitch = 0;
2398fe5e51b7Smrg	   }
2399fe5e51b7Smrg	   break;
2400fe5e51b7Smrg	case PCI_CHIP_MGAG100:
2401fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
2402fe5e51b7Smrg	   maxPitch = 2048;
2403fe5e51b7Smrg	   break;
2404eda3803bSmrg	case PCI_CHIP_MGAG200_SE_A_PCI:
24050bb88ba4Smrg           if (pScrn->videoRam < 2048){
2406d7be9c72Smrg               maxPitch = 1280;
24070bb88ba4Smrg           }
24080bb88ba4Smrg           break;
2409fe5e51b7Smrg	case PCI_CHIP_MGAG200:
2410fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
2411fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
2412eda3803bSmrg        case PCI_CHIP_MGAG200_WINBOND_PCI:
24136f68ce78Smrg	case PCI_CHIP_MGAG200_EW3_PCI:
2414eda3803bSmrg	case PCI_CHIP_MGAG200_EV_PCI:
241581f79626Smrg        case PCI_CHIP_MGAG200_EH_PCI:
241681f79626Smrg        case PCI_CHIP_MGAG200_EH3_PCI:
24170bb88ba4Smrg	case PCI_CHIP_MGAG200_ER_PCI:
2418fe5e51b7Smrg	case PCI_CHIP_MGAG400:
2419fe5e51b7Smrg	case PCI_CHIP_MGAG550:
2420fe5e51b7Smrg	   maxPitch = 4096;
2421fe5e51b7Smrg	   break;
2422fe5e51b7Smrg	}
2423fe5e51b7Smrg
2424fe5e51b7Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2425fe5e51b7Smrg			      pScrn->display->modes, clockRanges,
2426fe5e51b7Smrg			      linePitches, minPitch, maxPitch,
2427fe5e51b7Smrg			      pMga->Roundings[(pScrn->bitsPerPixel >> 3) - 1] *
2428fe5e51b7Smrg					pScrn->bitsPerPixel, 128, 2048,
2429fe5e51b7Smrg			      pScrn->display->virtualX,
2430fe5e51b7Smrg			      pScrn->display->virtualY,
2431fe5e51b7Smrg			      pMga->FbMapSize,
2432fe5e51b7Smrg			      LOOKUP_BEST_REFRESH);
2433fe5e51b7Smrg
24340bb88ba4Smrg	free(linePitches);
2435fe5e51b7Smrg    }
2436fe5e51b7Smrg
2437fe5e51b7Smrg    if (i < 1 && pMga->FBDev) {
2438fe5e51b7Smrg	fbdevHWUseBuildinMode(pScrn);
2439fe5e51b7Smrg	pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
2440fe5e51b7Smrg	i = 1;
2441fe5e51b7Smrg    }
2442fe5e51b7Smrg    if (i == -1) {
2443fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
2444fe5e51b7Smrg	MGAFreeRec(pScrn);
2445fe5e51b7Smrg	return FALSE;
2446fe5e51b7Smrg    }
2447fe5e51b7Smrg
2448fe5e51b7Smrg    /* Prune the modes marked as invalid */
2449fe5e51b7Smrg    xf86PruneDriverModes(pScrn);
2450fe5e51b7Smrg
2451fe5e51b7Smrg    if (i == 0 || pScrn->modes == NULL) {
2452fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2453fe5e51b7Smrg	MGAFreeRec(pScrn);
2454fe5e51b7Smrg	return FALSE;
2455fe5e51b7Smrg    }
2456fe5e51b7Smrg
2457fe5e51b7Smrg    /* If the Device section explicitly set HasSDRAM, don't bother checking.
2458fe5e51b7Smrg     */
2459fe5e51b7Smrg    if (!pMga->HasSDRAM) {
2460fe5e51b7Smrg	if ((pMga->softbooted || pMga->Primary)
2461fe5e51b7Smrg	     && pMga->chip_attribs->probe_for_sdram) {
2462fe5e51b7Smrg	    uint32_t option_reg;
2463fe5e51b7Smrg
2464fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2465fe5e51b7Smrg	    pci_device_cfg_read_u32(pMga->PciInfo, & option_reg,
2466fe5e51b7Smrg				    PCI_OPTION_REG);
2467fe5e51b7Smrg#else
2468fe5e51b7Smrg	    option_reg = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
2469fe5e51b7Smrg#endif
2470fe5e51b7Smrg	    pMga->HasSDRAM = ((option_reg & (1 << 14)) == 0);
2471fe5e51b7Smrg	}
2472fe5e51b7Smrg	else {
2473fe5e51b7Smrg	    pMga->HasSDRAM = pMga->chip_attribs->has_sdram;
2474fe5e51b7Smrg	}
2475fe5e51b7Smrg
2476fe5e51b7Smrg	if (pMga->HasSDRAM) {
2477fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Has SDRAM\n");
2478fe5e51b7Smrg	}
2479fe5e51b7Smrg    }
2480fe5e51b7Smrg
2481fe5e51b7Smrg    /*
2482fe5e51b7Smrg     * Set the CRTC parameters for all of the modes based on the type
2483fe5e51b7Smrg     * of mode, and the chipset's interlace requirements.
2484fe5e51b7Smrg     *
2485fe5e51b7Smrg     * Calling this is required if the mode->Crtc* values are used by the
2486fe5e51b7Smrg     * driver and if the driver doesn't provide code to set them.  They
2487fe5e51b7Smrg     * are not pre-initialised at all.
2488fe5e51b7Smrg     */
2489fe5e51b7Smrg    MGA_NOT_HAL(xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V));
2490fe5e51b7Smrg
2491fe5e51b7Smrg    /* Set the current mode to the first in the list */
2492fe5e51b7Smrg    pScrn->currentMode = pScrn->modes;
2493fe5e51b7Smrg
2494fe5e51b7Smrg    /* Print the list of modes being used */
2495fe5e51b7Smrg    xf86PrintModes(pScrn);
2496fe5e51b7Smrg
2497fe5e51b7Smrg    /* Set display resolution */
2498fe5e51b7Smrg    xf86SetDpi(pScrn, 0, 0);
2499fe5e51b7Smrg
2500fe5e51b7Smrg    /*
2501fe5e51b7Smrg     * Compute the byte offset into the linear frame buffer where the
2502fe5e51b7Smrg     * frame buffer data should actually begin.  According to DDK misc.c
2503fe5e51b7Smrg     * line 1023, if more than 4MB is to be displayed, YDSTORG must be set
2504fe5e51b7Smrg     * appropriately to align memory bank switching, and this requires a
2505fe5e51b7Smrg     * corresponding offset on linear frame buffer access.
2506fe5e51b7Smrg     * This is only needed for WRAM.
2507fe5e51b7Smrg     */
2508fe5e51b7Smrg
2509fe5e51b7Smrg    pMga->YDstOrg = 0;
2510fe5e51b7Smrg    if (pMga->chip_attribs->fb_4mb_quirk &&
2511fe5e51b7Smrg	(pScrn->virtualX * pScrn->virtualY * bytesPerPixel > 4*1024*1024)) {
2512fe5e51b7Smrg	int offset;
2513fe5e51b7Smrg	int offset_modulo = (pScrn->bitsPerPixel == 24) ? 12 : 4;
2514fe5e51b7Smrg	int ydstorg_modulo = 64;
2515fe5e51b7Smrg
2516fe5e51b7Smrg
2517fe5e51b7Smrg	if (pMga->Interleave) {
2518fe5e51b7Smrg	    offset_modulo <<= 1;
2519fe5e51b7Smrg	    ydstorg_modulo <<= 1;
2520fe5e51b7Smrg	}
2521fe5e51b7Smrg
2522fe5e51b7Smrg	offset = (4*1024*1024) % (pScrn->displayWidth * bytesPerPixel);
2523fe5e51b7Smrg	pMga->YDstOrg = offset / bytesPerPixel;
2524fe5e51b7Smrg
2525fe5e51b7Smrg	/*
2526fe5e51b7Smrg	 * When this was unconditional, it caused a line of horizontal garbage
2527fe5e51b7Smrg	 * at the middle right of the screen at the 4Meg boundary in 32bpp
2528fe5e51b7Smrg	 * (and presumably any other modes that use more than 4M). But it's
2529fe5e51b7Smrg	 * essential for 24bpp (it may not matter either way for 8bpp & 16bpp,
2530fe5e51b7Smrg	 * I'm not sure; I didn't notice problems when I checked with and
2531fe5e51b7Smrg	 * without.)
2532fe5e51b7Smrg	 * DRM Doug Merritt 12/97, submitted to XFree86 6/98 (oops)
2533fe5e51b7Smrg	 */
2534fe5e51b7Smrg	if (bytesPerPixel < 4) {
2535fe5e51b7Smrg	    while ((offset % offset_modulo) != 0 ||
2536fe5e51b7Smrg		   (pMga->YDstOrg % ydstorg_modulo) != 0) {
2537fe5e51b7Smrg		offset++;
2538fe5e51b7Smrg		pMga->YDstOrg = offset / bytesPerPixel;
2539fe5e51b7Smrg	    }
2540fe5e51b7Smrg	}
2541fe5e51b7Smrg    }
2542fe5e51b7Smrg
2543fe5e51b7Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "YDstOrg is set to %d\n",
2544fe5e51b7Smrg		   pMga->YDstOrg);
2545fe5e51b7Smrg    if(pMga->DualHeadEnabled) {
2546fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2547fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->masterFbMapSize;
2548fe5e51b7Smrg            /* Allocate HW cursor buffer at the end of video ram */
2549fe5e51b7Smrg	    if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2550fe5e51b7Smrg	        if( pScrn->virtualY * pScrn->displayWidth *
2551fe5e51b7Smrg		    pScrn->bitsPerPixel / 8 <=
2552fe5e51b7Smrg		    pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2553fe5e51b7Smrg		    pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2554fe5e51b7Smrg		    pMga->FbCursorOffset =
2555fe5e51b7Smrg		      pMgaEnt->masterFbMapSize -
2556fe5e51b7Smrg		      pMga->Dac.CursorOffscreenMemSize;
2557fe5e51b7Smrg		} else {
2558fe5e51b7Smrg		    pMga->HWCursor = FALSE;
2559fe5e51b7Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2560fe5e51b7Smrg			       "Too little offscreen memory for HW cursor; "
2561fe5e51b7Smrg			       "using SW cursor\n");
2562fe5e51b7Smrg		}
2563fe5e51b7Smrg	    }
2564fe5e51b7Smrg	} else { /* Second CRTC */
2565fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->slaveFbMapSize;
2566fe5e51b7Smrg	    pMga->HWCursor = FALSE;
2567fe5e51b7Smrg	}
2568fe5e51b7Smrg    } else {
2569fe5e51b7Smrg        pMga->FbUsableSize = pMga->FbMapSize - pMga->YDstOrg * bytesPerPixel;
2570fe5e51b7Smrg           /* Allocate HW cursor buffer at the end of video ram */
2571fe5e51b7Smrg        if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2572fe5e51b7Smrg	    if( pScrn->virtualY * pScrn->displayWidth *
2573fe5e51b7Smrg	        pScrn->bitsPerPixel / 8 <=
2574fe5e51b7Smrg        	pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2575fe5e51b7Smrg	        pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2576fe5e51b7Smrg	        pMga->FbCursorOffset =
2577fe5e51b7Smrg		  pMga->FbMapSize - pMga->Dac.CursorOffscreenMemSize;
2578fe5e51b7Smrg	    } else {
2579fe5e51b7Smrg	        pMga->HWCursor = FALSE;
2580fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2581fe5e51b7Smrg			   "Too little offscreen memory for HW cursor; "
2582fe5e51b7Smrg			   "using SW cursor\n");
2583fe5e51b7Smrg	    }
2584fe5e51b7Smrg	}
2585fe5e51b7Smrg    }
2586fe5e51b7Smrg    /*
2587fe5e51b7Smrg     * XXX This should be taken into account in some way in the mode valdation
2588fe5e51b7Smrg     * section.
2589fe5e51b7Smrg     */
2590fe5e51b7Smrg
2591fe5e51b7Smrg
2592fe5e51b7Smrg    /* Load the required framebuffer */
2593eda3803bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) {
2594eda3803bSmrg	MGAFreeRec(pScrn);
2595eda3803bSmrg	return FALSE;
2596fe5e51b7Smrg    }
2597fe5e51b7Smrg
2598fe5e51b7Smrg    /* Load ramdac if needed */
2599fe5e51b7Smrg    if (pMga->HWCursor) {
2600fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
2601fe5e51b7Smrg	    MGAFreeRec(pScrn);
2602fe5e51b7Smrg	    return FALSE;
2603fe5e51b7Smrg	}
2604fe5e51b7Smrg    }
2605fe5e51b7Smrg
2606fe5e51b7Smrg    /* Load shadowfb if needed */
2607fe5e51b7Smrg    if (pMga->ShadowFB) {
2608fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2609fe5e51b7Smrg	    MGAFreeRec(pScrn);
2610fe5e51b7Smrg	    return FALSE;
2611fe5e51b7Smrg	}
2612fe5e51b7Smrg    }
2613fe5e51b7Smrg
26140bb88ba4Smrg#ifdef MGADRI
2615fe5e51b7Smrg    /* Load the dri module if requested. */
2616fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_DRI, FALSE)) {
2617643b027fSmrg       xf86LoadSubModule(pScrn, "dri");
2618fe5e51b7Smrg    }
2619fe5e51b7Smrg#endif
2620fe5e51b7Smrg    pMga->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
2621fe5e51b7Smrg    pMga->CurrentLayout.depth = pScrn->depth;
2622fe5e51b7Smrg    pMga->CurrentLayout.displayWidth = pScrn->displayWidth;
2623fe5e51b7Smrg    pMga->CurrentLayout.weight.red = pScrn->weight.red;
2624fe5e51b7Smrg    pMga->CurrentLayout.weight.green = pScrn->weight.green;
2625fe5e51b7Smrg    pMga->CurrentLayout.weight.blue = pScrn->weight.blue;
2626fe5e51b7Smrg    pMga->CurrentLayout.mode = pScrn->currentMode;
2627fe5e51b7Smrg
2628fe5e51b7Smrg
2629fe5e51b7Smrg
2630fe5e51b7Smrg    if(pMga->MergedFB) {
2631fe5e51b7Smrg        MGAPreInitMergedFB(pScrn,flags);
2632fe5e51b7Smrg    };
2633fe5e51b7Smrg
2634fe5e51b7Smrg
2635fe5e51b7Smrg    xf86SetPrimInitDone(pScrn->entityList[0]);
2636fe5e51b7Smrg
2637fe5e51b7Smrg    return TRUE;
2638fe5e51b7Smrg}
2639fe5e51b7Smrg
2640fe5e51b7Smrg
2641fe5e51b7Smrg/*
2642fe5e51b7Smrg * Map the framebuffer and MMIO memory.
2643fe5e51b7Smrg */
2644fe5e51b7Smrg
2645fe5e51b7Smrgstatic Bool
2646fe5e51b7SmrgMGAMapMem(ScrnInfoPtr pScrn)
2647fe5e51b7Smrg{
2648fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2649fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2650fe5e51b7Smrg    struct pci_device *const dev = pMga->PciInfo;
2651fe5e51b7Smrg    struct pci_mem_region *region;
265281f79626Smrg    int err;
2653fe5e51b7Smrg#endif
2654fe5e51b7Smrg
2655fe5e51b7Smrg
2656fe5e51b7Smrg    if (!pMga->FBDev) {
2657fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2658acd6767fSmrg	pciaddr_t fbaddr = pMga->FbAddress;
2659acd6767fSmrg	pciaddr_t fbsize = pMga->FbMapSize;
2660acd6767fSmrg	err = pci_device_map_range(dev,
2661acd6767fSmrg				   fbaddr, fbsize,
26626f68ce78Smrg				   PCI_DEV_MAP_FLAG_WRITABLE |
26636f68ce78Smrg				   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
2664acd6767fSmrg				   (void **)&pMga->FbBase);
2665acd6767fSmrg
2666acd6767fSmrg	if (err) {
2667acd6767fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2668acd6767fSmrg		       "Unable to map Framebuffer %08llX %llx.  %s (%d)\n",
2669acd6767fSmrg		       (long long)fbaddr, (long long)fbsize,
2670acd6767fSmrg		       strerror(err), err);
2671acd6767fSmrg	    return FALSE;
2672acd6767fSmrg	}
2673acd6767fSmrg	else
2674acd6767fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2675acd6767fSmrg		       "MAPPED Framebuffer %08llX %llx to %08llX.\n",
2676acd6767fSmrg		       (long long)fbaddr, (long long)fbsize,
267781f79626Smrg		       (long long)(uintptr_t)pMga->FbBase);
2678acd6767fSmrg
2679acd6767fSmrg	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
2680acd6767fSmrg	    region = &dev->regions[pMga->io_bar];
2681acd6767fSmrg	    err = pci_device_map_range(dev,
2682acd6767fSmrg				       region->base_addr, region->size,
2683acd6767fSmrg				       PCI_DEV_MAP_FLAG_WRITABLE,
2684acd6767fSmrg				       &pMga->IOBase);
2685acd6767fSmrg
2686acd6767fSmrg	    if (err) {
2687acd6767fSmrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2688acd6767fSmrg			 "Unable to map IO Region %i.  %s (%d)\n",
2689acd6767fSmrg			 pMga->io_bar, strerror(err), err);
2690acd6767fSmrg	      return FALSE;
2691acd6767fSmrg	    }
2692fe5e51b7Smrg
2693acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2694acd6767fSmrg		pMga->entityPrivate->mappedIOBase = pMga->IOBase;
2695acd6767fSmrg	}
2696acd6767fSmrg	else
2697acd6767fSmrg		pMga->IOBase = pMga->entityPrivate->mappedIOBase;
2698acd6767fSmrg
2699acd6767fSmrg	if(pMga->entityPrivate != NULL)
2700acd6767fSmrg		pMga->entityPrivate->mappedIOUsage ++;
2701fe5e51b7Smrg
2702fe5e51b7Smrg#else
2703fe5e51b7Smrg	/*
2704fe5e51b7Smrg	 * For Alpha, we need to map SPARSE memory, since we need
2705fe5e51b7Smrg	 * byte/short access.  This is taken care of automatically by the
2706fe5e51b7Smrg	 * os-support layer.
2707fe5e51b7Smrg	 */
2708fe5e51b7Smrg	pMga->IOBase = xf86MapPciMem(pScrn->scrnIndex,
2709fe5e51b7Smrg				     VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
2710fe5e51b7Smrg				     pMga->PciTag, pMga->IOAddress, 0x4000);
2711fe5e51b7Smrg	if (pMga->IOBase == NULL)
2712fe5e51b7Smrg	    return FALSE;
2713fe5e51b7Smrg
27140bb88ba4Smrg    if (pMga->is_G200ER)
27150bb88ba4Smrg    {
27160bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
27170bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
27180bb88ba4Smrg                         pMga->FbMapSize);
27190bb88ba4Smrg    }
27200bb88ba4Smrg    else
27210bb88ba4Smrg    {
27220bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
27230bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
27240bb88ba4Smrg                         pMga->FbMapSize);
27250bb88ba4Smrg    }
2726fe5e51b7Smrg	if (pMga->FbBase == NULL)
2727fe5e51b7Smrg	    return FALSE;
2728fe5e51b7Smrg#endif
2729fe5e51b7Smrg    }
2730fe5e51b7Smrg    else {
2731fe5e51b7Smrg	pMga->FbBase = fbdevHWMapVidmem(pScrn);
2732fe5e51b7Smrg	if (pMga->FbBase == NULL) {
2733fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2734fe5e51b7Smrg		       "Unable to map framebuffer.\n");
2735fe5e51b7Smrg	    return FALSE;
2736fe5e51b7Smrg	}
2737fe5e51b7Smrg
2738fe5e51b7Smrg	pMga->IOBase = fbdevHWMapMMIO(pScrn);
2739fe5e51b7Smrg	if (pMga->IOBase == NULL) {
2740fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map MMIO.\n");
2741fe5e51b7Smrg	    return FALSE;
2742fe5e51b7Smrg	}
2743fe5e51b7Smrg    }
2744fe5e51b7Smrg
2745fe5e51b7Smrg
2746fe5e51b7Smrg    pMga->FbStart = pMga->FbBase + pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
2747fe5e51b7Smrg
2748fe5e51b7Smrg    pMga->ILOADBase = NULL;
2749fe5e51b7Smrg    if (pMga->iload_bar != -1) {
2750fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2751fe5e51b7Smrg        region = &dev->regions[pMga->iload_bar];
2752acd6767fSmrg
2753acd6767fSmrg	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) {
2754acd6767fSmrg	    err = pci_device_map_range(dev,
2755acd6767fSmrg				       region->base_addr, region->size,
2756acd6767fSmrg				       PCI_DEV_MAP_FLAG_WRITABLE,
2757acd6767fSmrg				       (void *) &pMga->ILOADBase);
2758acd6767fSmrg	    if (err) {
2759acd6767fSmrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2760acd6767fSmrg			 "Unable to map BAR 2 (ILOAD region).  %s (%d)\n",
2761acd6767fSmrg			 strerror(err), err);
2762acd6767fSmrg	      return FALSE;
2763acd6767fSmrg	    }
2764acd6767fSmrg
2765acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2766acd6767fSmrg		pMga->entityPrivate->mappedILOADBase = pMga->ILOADBase;
2767fe5e51b7Smrg	}
2768acd6767fSmrg	else
2769acd6767fSmrg		pMga->ILOADBase = pMga->entityPrivate->mappedILOADBase;
2770acd6767fSmrg
2771acd6767fSmrg	if(pMga->entityPrivate != NULL)
2772acd6767fSmrg		pMga->entityPrivate->mappedILOADUsage ++;
2773fe5e51b7Smrg#else
2774fe5e51b7Smrg	pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
2775fe5e51b7Smrg					VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
2776fe5e51b7Smrg					VIDMEM_READSIDEEFFECT,
2777fe5e51b7Smrg					pMga->PciTag, pMga->ILOADAddress,
2778fe5e51b7Smrg					0x800000);
2779fe5e51b7Smrg#endif
2780fe5e51b7Smrg    }
2781fe5e51b7Smrg
2782fe5e51b7Smrg
2783fe5e51b7Smrg    return TRUE;
2784fe5e51b7Smrg}
2785fe5e51b7Smrg
2786fe5e51b7Smrg
2787fe5e51b7Smrg/*
2788fe5e51b7Smrg * Unmap the framebuffer and MMIO memory.
2789fe5e51b7Smrg */
2790fe5e51b7Smrg
2791fe5e51b7Smrgstatic Bool
2792fe5e51b7SmrgMGAUnmapMem(ScrnInfoPtr pScrn)
2793fe5e51b7Smrg{
2794fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2795fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2796fe5e51b7Smrg    struct pci_device * const dev = pMga->PciInfo;
2797fe5e51b7Smrg#endif
2798fe5e51b7Smrg
2799fe5e51b7Smrg
2800fe5e51b7Smrg    if (!pMga->FBDev) {
2801fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2802acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2803acd6767fSmrg		pMga->entityPrivate->mappedIOUsage--;
2804acd6767fSmrg
2805acd6767fSmrg	    if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
2806acd6767fSmrg		pci_device_unmap_range(dev, pMga->IOBase,
2807acd6767fSmrg				       dev->regions[pMga->io_bar].size);
2808acd6767fSmrg
2809acd6767fSmrg		if(pMga->entityPrivate != NULL)
2810acd6767fSmrg			pMga->entityPrivate->mappedIOBase = NULL;
2811acd6767fSmrg	    }
2812acd6767fSmrg
281381f79626Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UNMAPPING framebuffer 0x%08llX, 0x%llX.\n", (long long)(uintptr_t)pMga->FbBase, (long long)pMga->FbMapSize);
2814fe5e51b7Smrg        pci_device_unmap_range(dev, pMga->FbBase,
2815acd6767fSmrg			       pMga->FbMapSize);
2816fe5e51b7Smrg#else
2817fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
2818fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase, pMga->FbMapSize);
2819fe5e51b7Smrg#endif
2820fe5e51b7Smrg    }
2821fe5e51b7Smrg    else {
2822fe5e51b7Smrg	fbdevHWUnmapVidmem(pScrn);
2823fe5e51b7Smrg	fbdevHWUnmapMMIO(pScrn);
2824fe5e51b7Smrg    }
2825fe5e51b7Smrg
2826fe5e51b7Smrg    if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
2827fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2828acd6767fSmrg	    if(pMga->entityPrivate != NULL)
2829acd6767fSmrg		pMga->entityPrivate->mappedILOADUsage--;
2830acd6767fSmrg
2831acd6767fSmrg	    if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) {
2832acd6767fSmrg		pci_device_unmap_range(dev, pMga->ILOADBase,
2833acd6767fSmrg				       dev->regions[pMga->iload_bar].size);
2834acd6767fSmrg
2835acd6767fSmrg		if(pMga->entityPrivate != NULL)
2836acd6767fSmrg		    pMga->entityPrivate->mappedILOADBase = NULL;
2837acd6767fSmrg	    }
2838acd6767fSmrg
2839fe5e51b7Smrg#else
2840fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
2841fe5e51b7Smrg#endif
2842fe5e51b7Smrg    }
2843fe5e51b7Smrg
2844fe5e51b7Smrg    pMga->IOBase = NULL;
2845fe5e51b7Smrg    pMga->FbBase = NULL;
2846fe5e51b7Smrg    pMga->FbStart = NULL;
2847fe5e51b7Smrg    pMga->ILOADBase = NULL;
2848fe5e51b7Smrg
2849fe5e51b7Smrg    return TRUE;
2850fe5e51b7Smrg}
2851fe5e51b7Smrg
2852fe5e51b7Smrg
2853fe5e51b7Smrg/*
2854fe5e51b7Smrg * This function saves the video state.
2855fe5e51b7Smrg */
2856fe5e51b7Smrgstatic void
2857fe5e51b7SmrgMGASave(ScrnInfoPtr pScrn)
2858fe5e51b7Smrg{
2859fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2860fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
2861fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2862fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
2863fe5e51b7Smrg
2864fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) return;
2865fe5e51b7Smrg
2866fe5e51b7Smrg    /* I need to save the registers for the second head also */
2867fe5e51b7Smrg    /* Save the register for 0x80 to 0xa0 */
2868fe5e51b7Smrg    /* Could call it dac2Saved */
2869fe5e51b7Smrg
2870fe5e51b7Smrg    /* Only save text mode fonts/text for the primary card */
2871fe5e51b7Smrg    (*pMga->Save)(pScrn, vgaReg, mgaReg, pMga->Primary);
2872fe5e51b7Smrg}
2873fe5e51b7Smrg
2874fe5e51b7Smrg/*
2875fe5e51b7Smrg * Initialise a new mode.  This is currently still using the old
2876fe5e51b7Smrg * "initialise struct, restore/write struct to HW" model.  That could
2877fe5e51b7Smrg * be changed.
2878fe5e51b7Smrg */
2879fe5e51b7Smrg
2880fe5e51b7Smrgstatic Bool
2881fe5e51b7SmrgMGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
2882fe5e51b7Smrg{
2883fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2884fe5e51b7Smrg    vgaRegPtr vgaReg;
2885fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2886fe5e51b7Smrg    MGARegPtr mgaReg;
2887fe5e51b7Smrg
2888fe5e51b7Smrg    vgaHWUnlock(hwp);
2889fe5e51b7Smrg
2890fe5e51b7Smrg/*    if(pMga->MergedFB && mode && mode->Private && (mode->PrivSize == 0)) {
2891fe5e51b7Smrg        mode = (DisplayModePtr)mode->Private;
2892fe5e51b7Smrg    }*/
2893fe5e51b7Smrg
2894fe5e51b7Smrg    /* Initialise the ModeReg values */
2895fe5e51b7Smrg    if (!vgaHWInit(pScrn, mode))
2896fe5e51b7Smrg	return FALSE;
2897fe5e51b7Smrg    pScrn->vtSema = TRUE;
2898fe5e51b7Smrg
2899fe5e51b7Smrg    if (!(*pMga->ModeInit)(pScrn, mode))
2900fe5e51b7Smrg	return FALSE;
2901fe5e51b7Smrg
2902fe5e51b7Smrg    /* Program the registers */
2903fe5e51b7Smrg    if (pMga->is_G200SE) {
2904fe5e51b7Smrg	MGAG200SEHWProtect(pScrn, TRUE);
2905fe5e51b7Smrg    } else {
2906fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
2907fe5e51b7Smrg    }
2908fe5e51b7Smrg    vgaReg = &hwp->ModeReg;
2909fe5e51b7Smrg    mgaReg = &pMga->ModeReg;
2910fe5e51b7Smrg
29110bb88ba4Smrg#ifdef MGADRI
2912fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
29130bb88ba4Smrg       DRILock(xf86ScrnToScreen(pScrn), 0);
2914fe5e51b7Smrg   }
2915fe5e51b7Smrg#endif
2916fe5e51b7Smrg
2917fe5e51b7Smrg    MGA_NOT_HAL((*pMga->Restore)(pScrn, vgaReg, mgaReg, FALSE));
2918fe5e51b7Smrg
2919fe5e51b7Smrg    MGAStormSync(pScrn);
2920fe5e51b7Smrg    MGAStormEngineInit(pScrn);
2921fe5e51b7Smrg
2922fe5e51b7Smrg    if (pMga->is_G200SE) {
2923fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
2924fe5e51b7Smrg    } else {
2925fe5e51b7Smrg	vgaHWProtect(pScrn, FALSE);
2926fe5e51b7Smrg    }
2927fe5e51b7Smrg
29280bb88ba4Smrg    /* Reset tagfifo*/
29290bb88ba4Smrg	if (pMga->is_G200ER)
29300bb88ba4Smrg    {
29310bb88ba4Smrg        CARD32 ulMemCtl = INREG(MGAREG_MEMCTL);
29320bb88ba4Smrg        CARD8  ucSeq1;
29330bb88ba4Smrg
29340bb88ba4Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reset tagfifo\n");
29350bb88ba4Smrg        /* Screen off */
29360bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
29370bb88ba4Smrg	    ucSeq1 = INREG8(MGAREG_SEQ_DATA) | 0x20;
29380bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1);
29390bb88ba4Smrg
29400bb88ba4Smrg        /* Reset tagfifo */
29410bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl | 0x002000000);
29420bb88ba4Smrg        usleep(1000); /* wait 1ms */
29430bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl & ~0x002000000);
29440bb88ba4Smrg
29450bb88ba4Smrg        /* Screen on */
29460bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1 & ~0x20);
29470bb88ba4Smrg
2948fe5e51b7Smrg    }
2949fe5e51b7Smrg
29500bb88ba4Smrg    /*
29510bb88ba4Smrg     This function optimize the Priority Request control
29520bb88ba4Smrg     Higher HiPriLvl will reduce drawing performance
2953d2b10af6Smrg     We need to give enough bandwidth to crtc to avoid visual artifact
29540bb88ba4Smrg    */
29550bb88ba4Smrg	if (pMga->is_G200SE)
29560bb88ba4Smrg    {
29570bb88ba4Smrg        if (pMga->reg_1e24 >= 0x02)
29580bb88ba4Smrg        {
2959d2b10af6Smrg            /* Calculate CRTC Priority value */
29600bb88ba4Smrg            CARD8  ucHiPriLvl;
29610bb88ba4Smrg            CARD32 ulBitsPerPixel;
29620bb88ba4Smrg            CARD32 ulMemoryBandwidth;
29630bb88ba4Smrg
29640bb88ba4Smrg            /* uiBitsPerPixel can only be 8,16 or32 */
29650bb88ba4Smrg            if (pScrn->bitsPerPixel > 16)
29660bb88ba4Smrg            {
29670bb88ba4Smrg                ulBitsPerPixel = 32;
29680bb88ba4Smrg            }
29690bb88ba4Smrg            else if (pScrn->bitsPerPixel >  8)
29700bb88ba4Smrg            {
29710bb88ba4Smrg                ulBitsPerPixel = 16;
29720bb88ba4Smrg            }
29730bb88ba4Smrg            else
29740bb88ba4Smrg            {
29750bb88ba4Smrg                ulBitsPerPixel = 8;
29760bb88ba4Smrg            }
29770bb88ba4Smrg
29780bb88ba4Smrg
29790bb88ba4Smrg            ulMemoryBandwidth = (mode->Clock * ulBitsPerPixel) / 1000;
29800bb88ba4Smrg
298181f79626Smrg            if (pMga->reg_1e24 >= 0x04)
298281f79626Smrg            {
298381f79626Smrg                ucHiPriLvl = 0;
298481f79626Smrg            }
298581f79626Smrg            else
298681f79626Smrg            {
298781f79626Smrg
298881f79626Smrg                if      (ulMemoryBandwidth    > 3100)  ucHiPriLvl = 0;
298981f79626Smrg                else if (ulMemoryBandwidth    > 2600)  ucHiPriLvl = 1;
299081f79626Smrg                else if (ulMemoryBandwidth    > 1900)  ucHiPriLvl = 2;
299181f79626Smrg                else if (ulMemoryBandwidth    > 1160)  ucHiPriLvl = 3;
299281f79626Smrg                else if (ulMemoryBandwidth    > 440)   ucHiPriLvl = 4;
299381f79626Smrg                else ucHiPriLvl = 5;
299481f79626Smrg            }
29950bb88ba4Smrg
2996fe5e51b7Smrg            OUTREG8(0x1FDE, 0x06);
29970bb88ba4Smrg		    OUTREG8(0x1FDF, ucHiPriLvl);
29980bb88ba4Smrg
299981f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %u\n",   mode->Clock);
300081f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %u\n",   pScrn->bitsPerPixel);
300181f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MemoryBandwidth == %u\n",   (unsigned)ulMemoryBandwidth);
30020bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == %02X\n", ucHiPriLvl);
3003fe5e51b7Smrg        }
30040bb88ba4Smrg        else
30050bb88ba4Smrg        {
30060bb88ba4Smrg            MGA_NOT_HAL(
30070bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %d\n",   mode->Clock);
30080bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %d\n",   pScrn->bitsPerPixel);
30090bb88ba4Smrg                OUTREG8(0x1FDE, 0x06);
30100bb88ba4Smrg	            if (pMga->reg_1e24 >= 0x01)
30110bb88ba4Smrg                {
30120bb88ba4Smrg		            OUTREG8(0x1FDF, 0x03);
30130bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 03\n");
30140bb88ba4Smrg                }
30150bb88ba4Smrg	            else
30160bb88ba4Smrg                {
30170bb88ba4Smrg		            OUTREG8(0x1FDF, 0x14);
30180bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 14h\n");
30190bb88ba4Smrg                }
30200bb88ba4Smrg            );
30210bb88ba4Smrg        }
30220bb88ba4Smrg    }
3023fe5e51b7Smrg
3024fe5e51b7Smrg    pMga->CurrentLayout.mode = mode;
3025fe5e51b7Smrg
3026fe5e51b7Smrg    if(pMga->MergedFB && mode->Private && (mode->PrivSize == 0)) {
3027fe5e51b7Smrg	pMga->M1currentMode = (DisplayModePtr)mode->Private;
3028fe5e51b7Smrg    }
3029fe5e51b7Smrg
30300bb88ba4Smrg#ifdef MGADRI
3031fe5e51b7Smrg   if (pMga->directRenderingEnabled)
30320bb88ba4Smrg     DRIUnlock(xf86ScrnToScreen(pScrn));
3033fe5e51b7Smrg#endif
3034fe5e51b7Smrg#ifdef DEBUG
3035fe5e51b7Smrg   MGAG450PrintPLL(pScrn);
3036fe5e51b7Smrg#endif
3037fe5e51b7Smrg    return TRUE;
3038fe5e51b7Smrg}
3039fe5e51b7Smrg
3040fe5e51b7Smrgstatic
3041fe5e51b7Smrgvoid MGARestoreSecondCrtc(ScrnInfoPtr pScrn)
3042fe5e51b7Smrg{
3043fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3044fe5e51b7Smrg
3045fe5e51b7Smrg    if (MGAISGx50(pMga)) {
3046fe5e51b7Smrg        /* Force to return in clone mode */
3047fe5e51b7Smrg        if (pMga->SecondOutput
3048fe5e51b7Smrg                && (xf86IsEntityShared(pScrn->entityList[0]) || pMga->SecondCrtc)
3049fe5e51b7Smrg                && !pMga->MergedFB) {
3050fe5e51b7Smrg            /* Do this branch if
3051fe5e51b7Smrg             * SecondOutput
3052fe5e51b7Smrg             * and not Unshared Primary
3053d2b10af6Smrg             * and not Merged Mode (usually means Unshared Primary)
3054fe5e51b7Smrg             */
3055fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3056fe5e51b7Smrg
3057fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3058fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3059fe5e51b7Smrg
3060fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3061fe5e51b7Smrg
3062fe5e51b7Smrg       } else {
3063fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3064fe5e51b7Smrg            CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3065fe5e51b7Smrg
3066fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3067fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC1OUTSEL_EN;
3068fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3069fe5e51b7Smrg
3070fe5e51b7Smrg            /* crtcdacsel -> crtc1 */
3071fe5e51b7Smrg            ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_CRTC2;
3072fe5e51b7Smrg            ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC1;
3073fe5e51b7Smrg
3074fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3075fe5e51b7Smrg            OUTREG(MGAREG_C2CTL, ulC2CTL);
3076fe5e51b7Smrg       }
3077fe5e51b7Smrg
3078fe5e51b7Smrg    } else {
3079fe5e51b7Smrg        /* Force to close second crtc */
3080fe5e51b7Smrg        CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3081fe5e51b7Smrg
3082fe5e51b7Smrg        ulC2CTL &= ~MGAREG_C2CTL_C2_EN;
3083fe5e51b7Smrg
3084fe5e51b7Smrg        OUTREG(MGAREG_C2CTL, ulC2CTL);
3085fe5e51b7Smrg    }
3086fe5e51b7Smrg}
3087fe5e51b7Smrg
3088fe5e51b7Smrg/*
3089fe5e51b7Smrg * Restore the initial (text) mode.
3090fe5e51b7Smrg */
3091fe5e51b7Smrgstatic void
3092fe5e51b7SmrgMGARestore(ScrnInfoPtr pScrn)
3093fe5e51b7Smrg{
3094fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3095fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
3096fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3097fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
3098fe5e51b7Smrg
3099fe5e51b7Smrg    if (pScrn->pScreen != NULL)
3100fe5e51b7Smrg	MGAStormSync(pScrn);
3101fe5e51b7Smrg
3102fe5e51b7Smrg    /*
3103fe5e51b7Smrg     * Restore the second crtc if:
3104fe5e51b7Smrg     * first and only driver entity
3105fe5e51b7Smrg     * second entity
3106fe5e51b7Smrg     * Merged Framebuffer mode (first and only driver entity)
3107fe5e51b7Smrg     */
3108fe5e51b7Smrg    if((!xf86IsEntityShared(pScrn->entityList[0]) && !pMga->SecondCrtc)
3109fe5e51b7Smrg       || pMga->SecondCrtc || pMga->MergedFB) {
3110fe5e51b7Smrg	/*       if(pMga->MergedFB) {
3111fe5e51b7Smrg		 if(pMga->pScrn2)
3112fe5e51b7Smrg                 MGARestoreSecondCrtc(pMga->pScrn2);
3113fe5e51b7Smrg		 } else*/
3114fe5e51b7Smrg	MGARestoreSecondCrtc(pScrn);
3115fe5e51b7Smrg	/* if we are second instance of driver, we've done our job, exit */
3116fe5e51b7Smrg	if(pMga->SecondCrtc) return;
3117fe5e51b7Smrg    }
3118fe5e51b7Smrg
3119fe5e51b7Smrg    /* Only restore text mode fonts/text for the primary card */
3120fe5e51b7Smrg    if (pMga->is_G200SE) {
3121fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,TRUE);
3122fe5e51b7Smrg    } else {
3123fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
3124fe5e51b7Smrg    }
3125fe5e51b7Smrg    if (pMga->Primary) {
3126fe5e51b7Smrg        (*pMga->Restore)(pScrn, vgaReg, mgaReg, TRUE);
3127fe5e51b7Smrg    } else {
3128fe5e51b7Smrg        vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
3129fe5e51b7Smrg    }
3130fe5e51b7Smrg
3131fe5e51b7Smrg    if (pMga->is_G200SE) {
3132fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
3133fe5e51b7Smrg    } else {
3134fe5e51b7Smrg	vgaHWProtect(pScrn,FALSE);
3135fe5e51b7Smrg    }
3136fe5e51b7Smrg}
3137fe5e51b7Smrg
3138fe5e51b7Smrg
3139fe5e51b7Smrg/* Workaround for a G400 CRTC2 display problem */
3140fe5e51b7Smrgstatic void
3141fe5e51b7SmrgMGACrtc2FillStrip(ScrnInfoPtr pScrn)
3142fe5e51b7Smrg{
3143fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3144fe5e51b7Smrg
3145fe5e51b7Smrg    if (pMga->NoAccel) {
3146fe5e51b7Smrg	/* Clears the whole screen, but ... */
3147fe5e51b7Smrg	bzero(pMga->FbStart,
3148fe5e51b7Smrg	    (pScrn->bitsPerPixel >> 3) * pScrn->displayWidth * pScrn->virtualY);
3149fe5e51b7Smrg    } else {
3150fe5e51b7Smrg	xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
315181f79626Smrg#ifdef USE_XAA
3152fe5e51b7Smrg	pMga->RestoreAccelState(pScrn);
3153fe5e51b7Smrg	pMga->SetupForSolidFill(pScrn, 0, GXcopy, 0xFFFFFFFF);
3154fe5e51b7Smrg	pMga->SubsequentSolidFillRect(pScrn, pScrn->virtualX, 0,
3155fe5e51b7Smrg				  pScrn->displayWidth - pScrn->virtualX,
3156fe5e51b7Smrg				  pScrn->virtualY);
3157acd6767fSmrg#endif
3158fe5e51b7Smrg	MGAStormSync(pScrn);
3159fe5e51b7Smrg    }
3160fe5e51b7Smrg}
3161fe5e51b7Smrg
3162fe5e51b7Smrg
3163fe5e51b7Smrg/* Mandatory */
3164fe5e51b7Smrg
3165fe5e51b7Smrg/* This gets called at the start of each server generation */
3166fe5e51b7Smrg
3167fe5e51b7Smrgstatic Bool
31680bb88ba4SmrgMGAScreenInit(SCREEN_INIT_ARGS_DECL)
3169fe5e51b7Smrg{
31700bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3171fe5e51b7Smrg    vgaHWPtr hwp;
3172fe5e51b7Smrg    MGAPtr pMga;
3173fe5e51b7Smrg    MGARamdacPtr MGAdac;
3174fe5e51b7Smrg    VisualPtr visual;
3175fe5e51b7Smrg    unsigned char *FBStart;
3176fe5e51b7Smrg    int width, height, displayWidth;
3177fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
3178fe5e51b7Smrg    int f;
317981f79626Smrg    CARD32 VRTemp = 0, FBTemp = 0;
3180fe5e51b7Smrg    DPMSSetProcPtr mga_dpms_set_proc = NULL;
3181fe5e51b7Smrg
3182fe5e51b7Smrg    hwp = VGAHWPTR(pScrn);
3183fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3184fe5e51b7Smrg    MGAdac = &pMga->Dac;
3185fe5e51b7Smrg
31860bb88ba4Smrg    if (pMga->is_G200SE)
31870bb88ba4Smrg    {
31880bb88ba4Smrg        VRTemp = pScrn->videoRam;
31890bb88ba4Smrg        FBTemp = pMga->FbMapSize;
31900bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
31910bb88ba4Smrg        {
31920bb88ba4Smrg            pScrn->videoRam = 16384;
31930bb88ba4Smrg        }
31940bb88ba4Smrg        else
31950bb88ba4Smrg        {
31960bb88ba4Smrg            pScrn->videoRam = 8192;
31970bb88ba4Smrg        }
31980bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
3199fe5e51b7Smrg    }
3200fe5e51b7Smrg
3201fe5e51b7Smrg
3202fe5e51b7Smrg    /* Map the MGA memory and MMIO areas */
3203fe5e51b7Smrg    if (!MGAMapMem(pScrn))
3204fe5e51b7Smrg	return FALSE;
3205fe5e51b7Smrg
3206fe5e51b7Smrg
3207fe5e51b7Smrg    /* Select functions that vary based on the CRTC configureation of the
3208fe5e51b7Smrg     * screen.
3209fe5e51b7Smrg     */
3210fe5e51b7Smrg    if (!pMga->MergedFB) {
3211fe5e51b7Smrg	if (pMga->SecondCrtc) {
3212fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSetCrtc2;
3213fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreenCrtc2;
3214fe5e51b7Smrg	}
3215fe5e51b7Smrg	else {
3216fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSet;
3217fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreen;
3218fe5e51b7Smrg	}
3219fe5e51b7Smrg    }
3220fe5e51b7Smrg    else {
3221fe5e51b7Smrg        pScreen->SaveScreen = MGASaveScreenMerged;
3222fe5e51b7Smrg	mga_dpms_set_proc = MGADisplayPowerManagementSetMerged;
3223fe5e51b7Smrg    }
3224fe5e51b7Smrg
3225fe5e51b7Smrg
3226fe5e51b7Smrg    if ((pMga->Chipset == PCI_CHIP_MGAG100)
3227fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
3228fe5e51b7Smrg        MGAG100BlackMagic(pScrn);
3229fe5e51b7Smrg
3230fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
3231fe5e51b7Smrg       DevUnion *pPriv;
3232fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3233fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3234fe5e51b7Smrg       pMgaEnt->refCount++;
3235fe5e51b7Smrg    } else {
3236fe5e51b7Smrg    }
3237fe5e51b7Smrg    if (pMga->is_G200SE) {
3238fe5e51b7Smrg	pScrn->videoRam = VRTemp;
3239fe5e51b7Smrg	pMga->FbMapSize = FBTemp;
3240fe5e51b7Smrg    }
3241fe5e51b7Smrg
3242fe5e51b7Smrg    /* Initialise the MMIO vgahw functions */
3243fe5e51b7Smrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
3244fe5e51b7Smrg    vgaHWGetIOBase(hwp);
3245fe5e51b7Smrg
3246fe5e51b7Smrg    /* Map the VGA memory when the primary video */
3247fe5e51b7Smrg    if (!pMga->FBDev) {
3248fe5e51b7Smrg	if (pMga->Primary) {
3249fe5e51b7Smrg	    hwp->MapSize = 0x10000;
3250fe5e51b7Smrg	    if (!vgaHWMapMem(pScrn))
3251fe5e51b7Smrg		return FALSE;
3252fe5e51b7Smrg	}
3253fe5e51b7Smrg
3254fe5e51b7Smrg	/* Save the current state */
3255fe5e51b7Smrg	MGASave(pScrn);
3256fe5e51b7Smrg	/* Initialise the first mode */
3257fe5e51b7Smrg	if (!MGAModeInit(pScrn, pScrn->currentMode))
3258fe5e51b7Smrg	    return FALSE;
3259fe5e51b7Smrg    }
3260fe5e51b7Smrg    else {
3261fe5e51b7Smrg	fbdevHWSave(pScrn);
3262fe5e51b7Smrg	/* Disable VGA core, and leave memory access on */
3263fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
3264fe5e51b7Smrg	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
3265fe5e51b7Smrg				  PCI_OPTION_REG);
3266fe5e51b7Smrg#else
3267fe5e51b7Smrg	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
3268fe5e51b7Smrg#endif
3269fe5e51b7Smrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode))
3270fe5e51b7Smrg	    return FALSE;
3271fe5e51b7Smrg
3272fe5e51b7Smrg        if (!pMga->SecondCrtc && pMga->HWCursor
3273fe5e51b7Smrg	    && pMga->chip_attribs->hwcursor_1064) {
3274fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_LOW, pMga->FbCursorOffset >> 10);
3275fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_HI, pMga->FbCursorOffset >> 18);
3276fe5e51b7Smrg	}
3277fe5e51b7Smrg
3278fe5e51b7Smrg	MGAStormEngineInit(pScrn);
3279fe5e51b7Smrg    }
3280fe5e51b7Smrg
3281fe5e51b7Smrg    /* Darken the screen for aesthetic reasons and set the viewport
3282fe5e51b7Smrg     */
3283fe5e51b7Smrg    (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
32840bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3285fe5e51b7Smrg
3286fe5e51b7Smrg
3287fe5e51b7Smrg    /*
3288fe5e51b7Smrg     * The next step is to setup the screen's visuals, and initialise the
3289fe5e51b7Smrg     * framebuffer code.  In cases where the framebuffer's default
3290fe5e51b7Smrg     * choices for things like visual layouts and bits per RGB are OK,
3291fe5e51b7Smrg     * this may be as simple as calling the framebuffer's ScreenInit()
3292fe5e51b7Smrg     * function.  If not, the visuals will need to be setup before calling
3293fe5e51b7Smrg     * a fb ScreenInit() function and fixed up after.
3294fe5e51b7Smrg     *
3295fe5e51b7Smrg     * For most PC hardware at depths >= 8, the defaults that cfb uses
3296fe5e51b7Smrg     * are not appropriate.  In this driver, we fixup the visuals after.
3297fe5e51b7Smrg     */
3298fe5e51b7Smrg
3299fe5e51b7Smrg    /*
3300fe5e51b7Smrg     * Reset the visual list.
3301fe5e51b7Smrg     */
3302fe5e51b7Smrg    miClearVisualTypes();
3303fe5e51b7Smrg
3304fe5e51b7Smrg    /* Setup the visuals we support. */
3305fe5e51b7Smrg
3306eda3803bSmrg    /* All MGA support DirectColor */
3307eda3803bSmrg    if (pMga->SecondCrtc) {
3308fe5e51b7Smrg	/* No DirectColor on the second head */
3309fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
3310fe5e51b7Smrg			      TrueColor))
3311fe5e51b7Smrg		return FALSE;
3312fe5e51b7Smrg	if (!miSetPixmapDepths ())
3313fe5e51b7Smrg	    return FALSE;
3314fe5e51b7Smrg    } else {
3315fe5e51b7Smrg	if (!xf86SetDefaultVisual(pScrn, -1))
3316fe5e51b7Smrg	    return FALSE;
3317fe5e51b7Smrg
3318fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth,
3319fe5e51b7Smrg			      miGetDefaultVisualMask(pScrn->depth),
3320fe5e51b7Smrg			      pScrn->rgbBits, pScrn->defaultVisual))
3321fe5e51b7Smrg	    return FALSE;
3322fe5e51b7Smrg	if (!miSetPixmapDepths ())
3323fe5e51b7Smrg	    return FALSE;
3324fe5e51b7Smrg    }
3325fe5e51b7Smrg
3326fe5e51b7Smrg    /*
3327fe5e51b7Smrg     * Call the framebuffer layer's ScreenInit function, and fill in other
3328fe5e51b7Smrg     * pScreen fields.
3329fe5e51b7Smrg     */
3330fe5e51b7Smrg
3331fe5e51b7Smrg    width = pScrn->virtualX;
3332fe5e51b7Smrg    height = pScrn->virtualY;
3333fe5e51b7Smrg    displayWidth = pScrn->displayWidth;
3334fe5e51b7Smrg
3335fe5e51b7Smrg
3336fe5e51b7Smrg    if(pMga->Rotate) {
3337fe5e51b7Smrg	height = pScrn->virtualX;
3338fe5e51b7Smrg	width = pScrn->virtualY;
3339fe5e51b7Smrg    }
3340fe5e51b7Smrg
3341fe5e51b7Smrg    if(pMga->ShadowFB) {
3342fe5e51b7Smrg 	pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
33430bb88ba4Smrg	pMga->ShadowPtr = malloc(pMga->ShadowPitch * height);
3344fe5e51b7Smrg	displayWidth = pMga->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3345fe5e51b7Smrg        FBStart = pMga->ShadowPtr;
3346fe5e51b7Smrg    } else {
3347fe5e51b7Smrg	pMga->ShadowPtr = NULL;
3348fe5e51b7Smrg	FBStart = pMga->FbStart;
3349fe5e51b7Smrg    }
3350fe5e51b7Smrg
33510bb88ba4Smrg#ifdef MGADRI
3352fe5e51b7Smrg     /*
3353eda3803bSmrg      * Setup DRI after visuals have been established.
3354eda3803bSmrg      *
3355fe5e51b7Smrg      * The DRI does not work when textured video is enabled at this time.
3356fe5e51b7Smrg      */
3357fe5e51b7Smrg    if (pMga->is_G200SE) {
3358fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3359fe5e51b7Smrg		   "Not supported by hardware, not initializing the DRI\n");
3360fe5e51b7Smrg	pMga->directRenderingEnabled = FALSE;
3361fe5e51b7Smrg    } else if (!xf86ReturnOptValBool(pMga->Options, OPTION_DRI, TRUE)) {
3362fe5e51b7Smrg    } else if ( pMga->NoAccel ) {
3363fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3364fe5e51b7Smrg		   "Acceleration disabled, not initializing the DRI\n" );
3365fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3366fe5e51b7Smrg    }
3367fe5e51b7Smrg    else if ( pMga->TexturedVideo == TRUE ) {
3368fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3369fe5e51b7Smrg		   "Textured video enabled, not initializing the DRI\n" );
3370fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3371fe5e51b7Smrg    }
3372fe5e51b7Smrg    else if (pMga->SecondCrtc == TRUE) {
3373fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3374fe5e51b7Smrg		   "Not initializing the DRI on the second head\n" );
3375fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3376fe5e51b7Smrg    }
3377fe5e51b7Smrg    else if ((pMga->FbMapSize /
3378fe5e51b7Smrg	       (width * (pScrn->bitsPerPixel >> 3))) <= height * 3) {
3379fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3380fe5e51b7Smrg	  "Static buffer allocation failed, not initializing the DRI\n");
3381fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3382fe5e51b7Smrg	  "Need at least %d kB video memory at this resolution, bit depth\n",
3383fe5e51b7Smrg	  (3 * displayWidth * height * (pScrn->bitsPerPixel >> 3)) / 1024 );
3384fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3385fe5e51b7Smrg    }
3386fe5e51b7Smrg    else {
3387fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIScreenInit(pScreen);
3388fe5e51b7Smrg    }
3389fe5e51b7Smrg#endif
3390fe5e51b7Smrg
3391fe5e51b7Smrg
3392eda3803bSmrg    if (!fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
3393eda3803bSmrg		      pScrn->yDpi, displayWidth, pScrn->bitsPerPixel)) {
3394fe5e51b7Smrg	return FALSE;
3395eda3803bSmrg    }
3396fe5e51b7Smrg
3397fe5e51b7Smrg
3398fe5e51b7Smrg    if (pScrn->bitsPerPixel > 8) {
3399fe5e51b7Smrg        /* Fixup RGB ordering */
3400fe5e51b7Smrg        visual = pScreen->visuals + pScreen->numVisuals;
3401fe5e51b7Smrg        while (--visual >= pScreen->visuals) {
3402fe5e51b7Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
3403fe5e51b7Smrg		visual->offsetRed = pScrn->offset.red;
3404fe5e51b7Smrg		visual->offsetGreen = pScrn->offset.green;
3405fe5e51b7Smrg		visual->offsetBlue = pScrn->offset.blue;
3406fe5e51b7Smrg		visual->redMask = pScrn->mask.red;
3407fe5e51b7Smrg		visual->greenMask = pScrn->mask.green;
3408fe5e51b7Smrg		visual->blueMask = pScrn->mask.blue;
3409fe5e51b7Smrg	    }
3410fe5e51b7Smrg	}
3411fe5e51b7Smrg    }
3412fe5e51b7Smrg
3413fe5e51b7Smrg    /* must be after RGB ordering fixed */
3414eda3803bSmrg    fbPictureInit (pScreen, 0, 0);
3415eda3803bSmrg
3416fe5e51b7Smrg    xf86SetBlackWhitePixels(pScreen);
3417fe5e51b7Smrg
3418fe5e51b7Smrg    pMga->BlockHandler = pScreen->BlockHandler;
3419fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
3420fe5e51b7Smrg
3421fe5e51b7Smrg    if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */
3422fe5e51b7Smrg	MGADGAInit(pScreen);
3423fe5e51b7Smrg
3424fe5e51b7Smrg    if (!pMga->NoAccel) {
3425fe5e51b7Smrg#ifdef USE_EXA
3426fe5e51b7Smrg	if (pMga->Exa)
3427fe5e51b7Smrg	    mgaExaInit(pScreen);
3428fe5e51b7Smrg	else
3429fe5e51b7Smrg#endif
3430fe5e51b7Smrg	    MGAStormAccelInit(pScreen);
3431fe5e51b7Smrg    }
3432fe5e51b7Smrg
3433fe5e51b7Smrg    xf86SetBackingStore(pScreen);
3434fe5e51b7Smrg    xf86SetSilkenMouse(pScreen);
3435fe5e51b7Smrg
3436fe5e51b7Smrg    /* Initialize software cursor.
3437fe5e51b7Smrg	Must precede creation of the default colormap */
3438fe5e51b7Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
3439fe5e51b7Smrg
3440fe5e51b7Smrg    /* Initialize HW cursor layer.
3441fe5e51b7Smrg	Must follow software cursor initialization*/
3442fe5e51b7Smrg    if (pMga->HWCursor) {
3443fe5e51b7Smrg	if(!MGAHWCursorInit(pScreen))
3444fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3445fe5e51b7Smrg		"Hardware cursor initialization failed\n");
3446fe5e51b7Smrg    }
3447fe5e51b7Smrg    if(pMga->MergedFB) {
3448fe5e51b7Smrg        /* Rotate and MergedFB are mutiualy exclusive, so we can use this
3449fe5e51b7Smrg         * variable.
3450fe5e51b7Smrg         */
3451fe5e51b7Smrg        if (!pMga->PointerMoved)
3452fe5e51b7Smrg            pMga->PointerMoved = pScrn->PointerMoved;
3453fe5e51b7Smrg        pScrn->PointerMoved = MGAMergePointerMoved;
3454fe5e51b7Smrg
3455fe5e51b7Smrg    }
3456fe5e51b7Smrg
3457fe5e51b7Smrg    /* Initialise default colourmap */
3458fe5e51b7Smrg    if (!miCreateDefColormap(pScreen))
3459fe5e51b7Smrg	return FALSE;
3460fe5e51b7Smrg
3461fe5e51b7Smrg    /* Initialize colormap layer.
3462fe5e51b7Smrg	Must follow initialization of the default colormap */
3463fe5e51b7Smrg    if (!pMga->SecondCrtc)
3464fe5e51b7Smrg	f = CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH;
3465fe5e51b7Smrg    else
3466fe5e51b7Smrg	f = CMAP_RELOAD_ON_MODE_SWITCH;
3467fe5e51b7Smrg    if(!xf86HandleColormaps(pScreen, 256, 8,
3468fe5e51b7Smrg	pMga->FBDev ? fbdevHWLoadPaletteWeak() : MGAdac->LoadPalette,
3469fe5e51b7Smrg	NULL, f))
3470fe5e51b7Smrg	return FALSE;
3471fe5e51b7Smrg
3472fe5e51b7Smrg    if(pMga->ShadowFB) {
3473fe5e51b7Smrg	RefreshAreaFuncPtr refreshArea = MGARefreshArea;
3474fe5e51b7Smrg
3475fe5e51b7Smrg	if(pMga->Rotate) {
3476fe5e51b7Smrg	    if (!pMga->PointerMoved) {
3477fe5e51b7Smrg	    pMga->PointerMoved = pScrn->PointerMoved;
3478fe5e51b7Smrg	    pScrn->PointerMoved = MGAPointerMoved;
3479fe5e51b7Smrg	    }
3480fe5e51b7Smrg
3481fe5e51b7Smrg	   switch(pScrn->bitsPerPixel) {
3482fe5e51b7Smrg	   case 8:	refreshArea = MGARefreshArea8;	break;
3483fe5e51b7Smrg	   case 16:	refreshArea = MGARefreshArea16;	break;
3484fe5e51b7Smrg	   case 24:	refreshArea = MGARefreshArea24;	break;
3485fe5e51b7Smrg	   case 32:	refreshArea = MGARefreshArea32;	break;
3486fe5e51b7Smrg	   }
3487fe5e51b7Smrg	}
3488fe5e51b7Smrg
3489fe5e51b7Smrg	ShadowFBInit(pScreen, refreshArea);
3490fe5e51b7Smrg    }
3491fe5e51b7Smrg
3492fe5e51b7Smrg    xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
3493fe5e51b7Smrg
3494fe5e51b7Smrg    pScrn->memPhysBase = pMga->FbAddress;
3495fe5e51b7Smrg    pScrn->fbOffset = pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
3496fe5e51b7Smrg
3497fe5e51b7Smrg    MGAInitVideo(pScreen);
3498fe5e51b7Smrg
34990bb88ba4Smrg#ifdef MGADRI
3500fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3501eda3803bSmrg       /* Now that mi, drm and others have done their thing,
3502fe5e51b7Smrg	* complete the DRI setup.
3503fe5e51b7Smrg	*/
3504fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIFinishScreenInit(pScreen);
3505fe5e51b7Smrg    }
3506fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3507fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
3508fe5e51b7Smrg    } else {
3509fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
3510fe5e51b7Smrg    }
3511fe5e51b7Smrg    if (pMga->DualHeadEnabled && pMga->SecondCrtc == FALSE)
3512fe5e51b7Smrg	pMgaEnt->directRenderingEnabled = pMga->directRenderingEnabled;
3513fe5e51b7Smrg    pMga->haveQuiescense = 1;
3514fe5e51b7Smrg#endif
3515fe5e51b7Smrg
3516fe5e51b7Smrg    /* Wrap the current CloseScreen function */
3517fe5e51b7Smrg    pMga->CloseScreen = pScreen->CloseScreen;
3518fe5e51b7Smrg    pScreen->CloseScreen = MGACloseScreen;
3519fe5e51b7Smrg
3520fe5e51b7Smrg    /* Report any unused options (only for the first generation) */
3521fe5e51b7Smrg    if (serverGeneration == 1) {
3522fe5e51b7Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3523fe5e51b7Smrg    }
3524fe5e51b7Smrg
3525fe5e51b7Smrg    /* For the second head, work around display problem. */
3526fe5e51b7Smrg    if (!pMga->MergedFB && pMga->SecondCrtc) {
3527fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3528fe5e51b7Smrg    }
3529fe5e51b7Smrg
3530fe5e51b7Smrg    /* Done */
3531fe5e51b7Smrg    return TRUE;
3532fe5e51b7Smrg}
3533fe5e51b7Smrg
3534fe5e51b7Smrg
3535fe5e51b7Smrg/* Usually mandatory */
3536fe5e51b7SmrgBool
35370bb88ba4SmrgMGASwitchMode(SWITCH_MODE_ARGS_DECL)
3538fe5e51b7Smrg{
35390bb88ba4Smrg    SCRN_INFO_PTR(arg);
3540fe5e51b7Smrg    if  (mode->Flags & 0x80000000) {
3541fe5e51b7Smrg 	return FALSE;
3542fe5e51b7Smrg    }   else
35430bb88ba4Smrg	return MGAModeInit(pScrn, mode);
3544fe5e51b7Smrg}
3545fe5e51b7Smrg
3546fe5e51b7Smrg /* Adjusts coordinates to match Panning granularity.
3547fe5e51b7Smrg  * does nothing if the HALlib is not loaded
3548fe5e51b7Smrg  */
3549fe5e51b7Smrgvoid
3550fe5e51b7SmrgMGAAdjustGranularity(ScrnInfoPtr pScrn, int* x, int* y)
3551fe5e51b7Smrg{
3552fe5e51b7Smrg}
3553fe5e51b7Smrg
3554fe5e51b7Smrg
3555fe5e51b7Smrg/*
3556fe5e51b7Smrg * This function is used to initialize the Start Address - the first
3557fe5e51b7Smrg * displayed location in the video memory.
3558fe5e51b7Smrg */
3559fe5e51b7Smrg/* Usually mandatory */
3560fe5e51b7Smrgvoid
35610bb88ba4SmrgMGAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
3562fe5e51b7Smrg{
35630bb88ba4Smrg    SCRN_INFO_PTR(arg);
3564493f84f4Smrg    int Base, tmp, count, last_vcount;
3565fe5e51b7Smrg
3566fe5e51b7Smrg    MGAFBLayout *pLayout;
3567fe5e51b7Smrg    MGAPtr pMga;
3568fe5e51b7Smrg
3569fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3570fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3571fe5e51b7Smrg
3572fe5e51b7Smrg        /* wanted to improve panning granularity problems without risking
3573fe5e51b7Smrg         * compatibility issues. Existing code looked hardware dependent.
3574fe5e51b7Smrg         */
3575fe5e51b7Smrg    MGA_NOT_HAL(
3576fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3577fe5e51b7Smrg            y += pScrn->virtualY - 1;
3578fe5e51b7Smrg
3579fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x + pMga->YDstOrg) >>
3580fe5e51b7Smrg                    (3 - pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]);
3581fe5e51b7Smrg
3582fe5e51b7Smrg        if (pLayout->bitsPerPixel == 24) {
3583fe5e51b7Smrg            if (pMga->Chipset == PCI_CHIP_MGAG400
3584fe5e51b7Smrg                || pMga->Chipset == PCI_CHIP_MGAG550)
3585fe5e51b7Smrg                Base &= ~1;  /*1 Not sure why */
3586fe5e51b7Smrg
3587fe5e51b7Smrg            Base *= 3;
3588fe5e51b7Smrg        }
3589fe5e51b7Smrg
3590fe5e51b7Smrg        /* find start of retrace */
3591fe5e51b7Smrg        while (INREG8(0x1FDA) & 0x08);
3592fe5e51b7Smrg        while (!(INREG8(0x1FDA) & 0x08));
3593fe5e51b7Smrg        /* wait until we're past the start (fixseg.c in the DDK) */
3594493f84f4Smrg        last_vcount = INREG(MGAREG_VCOUNT);
3595493f84f4Smrg        count = last_vcount + 2;
3596493f84f4Smrg        while (1) {
3597493f84f4Smrg           int vcount = INREG(MGAREG_VCOUNT);
3598493f84f4Smrg           if (vcount >= count) break;
3599493f84f4Smrg           if (vcount < last_vcount) break;
3600493f84f4Smrg           last_vcount = vcount;
3601493f84f4Smrg        }
3602fe5e51b7Smrg
3603fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, (Base & 0x00FF00) | 0x0C);
3604fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, ((Base & 0x0000FF) << 8) | 0x0D);
3605fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_INDEX, 0x00);
3606fe5e51b7Smrg        tmp = INREG8(MGAREG_CRTCEXT_DATA);
3607fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_DATA, (tmp & 0xF0) | ((Base & 0x0F0000) >> 16));
3608fe5e51b7Smrg    );
3609fe5e51b7Smrg
3610fe5e51b7Smrg}
3611fe5e51b7Smrg
3612fe5e51b7Smrgvoid
36130bb88ba4SmrgMGAAdjustFrameCrtc2(ADJUST_FRAME_ARGS_DECL)
3614fe5e51b7Smrg{
36150bb88ba4Smrg    SCRN_INFO_PTR(arg);
3616fe5e51b7Smrg    int Base;
3617fe5e51b7Smrg    MGAFBLayout *pLayout;
3618fe5e51b7Smrg    MGAPtr pMga;
3619fe5e51b7Smrg
3620fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3621fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3622fe5e51b7Smrg    MGA_NOT_HAL(
3623fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3624fe5e51b7Smrg            y += pScrn->virtualY - 1;
3625fe5e51b7Smrg
3626fe5e51b7Smrg        /* 3-85 c2offset
3627fe5e51b7Smrg            * 3-93 c2startadd0
3628fe5e51b7Smrg            * 3-96 c2vcount
3629fe5e51b7Smrg            */
3630fe5e51b7Smrg
3631fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x) * pLayout->bitsPerPixel >> 3;
3632fe5e51b7Smrg        Base += pMga->DstOrg;
3633fe5e51b7Smrg        Base &= 0x01ffffc0;
3634fe5e51b7Smrg        OUTREG(MGAREG_C2STARTADD0, Base);
3635fe5e51b7Smrg    );
3636fe5e51b7Smrg}
3637fe5e51b7Smrg
3638fe5e51b7Smrg/*
3639fe5e51b7Smrg * This is called when VT switching back to the X server.  Its job is
3640fe5e51b7Smrg * to reinitialise the video mode.
3641fe5e51b7Smrg *
3642fe5e51b7Smrg * We may wish to unmap video/MMIO memory too.
3643fe5e51b7Smrg */
3644fe5e51b7Smrg
3645fe5e51b7Smrg/* Mandatory */
3646fe5e51b7Smrgstatic Bool
36470bb88ba4SmrgMGAEnterVT(VT_FUNC_ARGS_DECL)
3648fe5e51b7Smrg{
36490bb88ba4Smrg    SCRN_INFO_PTR(arg);
3650fe5e51b7Smrg    MGAPtr pMga;
3651fe5e51b7Smrg
3652fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3653fe5e51b7Smrg
36540bb88ba4Smrg#ifdef MGADRI
3655fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3656fe5e51b7Smrg	if (pMga->irq) {
3657fe5e51b7Smrg	    /* Need to make sure interrupts are enabled */
3658fe5e51b7Smrg	    OUTREG(MGAREG_IEN, pMga->reg_ien);
3659fe5e51b7Smrg	}
36600bb88ba4Smrg        DRIUnlock(xf86ScrnToScreen(pScrn));
3661fe5e51b7Smrg    }
3662fe5e51b7Smrg#endif
3663fe5e51b7Smrg
3664fe5e51b7Smrg    if (!MGAModeInit(pScrn, pScrn->currentMode))
3665fe5e51b7Smrg	return FALSE;
36660bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3667fe5e51b7Smrg
3668fe5e51b7Smrg    /* For the second head, work around display problem. */
3669fe5e51b7Smrg   if (pMga->SecondCrtc) {
3670fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3671fe5e51b7Smrg    }
3672fe5e51b7Smrg
3673fe5e51b7Smrg    return TRUE;
3674fe5e51b7Smrg}
3675fe5e51b7Smrg
3676fe5e51b7Smrgstatic Bool
36770bb88ba4SmrgMGAEnterVTFBDev(VT_FUNC_ARGS_DECL)
3678fe5e51b7Smrg{
36790bb88ba4Smrg    SCRN_INFO_PTR(arg);
36800bb88ba4Smrg#ifdef MGADRI
3681fe5e51b7Smrg    ScreenPtr pScreen;
3682fe5e51b7Smrg    MGAPtr pMga;
3683fe5e51b7Smrg
3684fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3685fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
36860bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3687fe5e51b7Smrg        DRIUnlock(pScreen);
3688fe5e51b7Smrg    }
3689fe5e51b7Smrg#endif
3690fe5e51b7Smrg
36910bb88ba4Smrg    fbdevHWEnterVT(VT_FUNC_ARGS);
3692fe5e51b7Smrg    MGAStormEngineInit(pScrn);
3693fe5e51b7Smrg    return TRUE;
3694fe5e51b7Smrg}
3695fe5e51b7Smrg
3696fe5e51b7Smrg#define RESTORE_TEXTMODE_ON_DVI(x)                      \
3697fe5e51b7Smrg    if (MGAISGx50(x) &&                                 \
3698fe5e51b7Smrg       (ISDIGITAL1(x) || ISDIGITAL2(x))) {              \
3699fe5e51b7Smrg        /* Reset DUALDVI register */                    \
3700fe5e51b7Smrg        outMGAdac(MGA1064_DVI_PIPE_CTL, 0x0);           \
3701fe5e51b7Smrg        /* Set Panel mode between 20 and 54 MHz */      \
3702fe5e51b7Smrg        outMGAdac(MGA1064_PAN_CTL, 0x7);                \
3703fe5e51b7Smrg    }
3704fe5e51b7Smrg
3705fe5e51b7Smrg
3706fe5e51b7Smrg/*
3707fe5e51b7Smrg * This is called when VT switching away from the X server.  Its job is
3708fe5e51b7Smrg * to restore the previous (text) mode.
3709fe5e51b7Smrg *
3710fe5e51b7Smrg * We may wish to remap video/MMIO memory too.
3711fe5e51b7Smrg */
3712fe5e51b7Smrg
3713fe5e51b7Smrg/* Mandatory */
3714fe5e51b7Smrgstatic void
37150bb88ba4SmrgMGALeaveVT(VT_FUNC_ARGS_DECL)
3716fe5e51b7Smrg{
37170bb88ba4Smrg    SCRN_INFO_PTR(arg);
3718fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
37190bb88ba4Smrg#ifdef MGADRI
3720fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3721fe5e51b7Smrg    ScreenPtr pScreen;
3722fe5e51b7Smrg#endif
3723fe5e51b7Smrg
3724fe5e51b7Smrg    MGARestore(pScrn);
3725fe5e51b7Smrg    vgaHWLock(hwp);
3726fe5e51b7Smrg
37270bb88ba4Smrg#ifdef MGADRI
3728fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
37290bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3730fe5e51b7Smrg        DRILock(pScreen, 0);
3731fe5e51b7Smrg    }
3732fe5e51b7Smrg#endif
3733fe5e51b7Smrg}
3734fe5e51b7Smrg
3735fe5e51b7Smrg
3736fe5e51b7Smrg/*
3737fe5e51b7Smrg * This is called at the end of each server generation.  It restores the
3738fe5e51b7Smrg * original (text) mode.  It should also unmap the video memory, and free
3739fe5e51b7Smrg * any per-generation data allocated by the driver.  It should finish
3740fe5e51b7Smrg * by unwrapping and calling the saved CloseScreen function.
3741fe5e51b7Smrg */
3742fe5e51b7Smrg
3743fe5e51b7Smrg/* Mandatory */
3744fe5e51b7Smrgstatic Bool
37450bb88ba4SmrgMGACloseScreen(CLOSE_SCREEN_ARGS_DECL)
3746fe5e51b7Smrg{
37470bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3748fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3749fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3750fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
375181f79626Smrg    CARD32 VRTemp = 0, FBTemp = 0;
3752fe5e51b7Smrg
3753fe5e51b7Smrg    if (pMga->MergedFB)
37540bb88ba4Smrg         MGACloseScreenMerged(pScreen);
37550bb88ba4Smrg
37560bb88ba4Smrg    if (pMga->is_G200SE)
37570bb88ba4Smrg    {
37580bb88ba4Smrg        VRTemp = pScrn->videoRam;
37590bb88ba4Smrg        FBTemp = pMga->FbMapSize;
37600bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
37610bb88ba4Smrg        {
37620bb88ba4Smrg            pScrn->videoRam = 16384;
37630bb88ba4Smrg        }
37640bb88ba4Smrg        else
37650bb88ba4Smrg        {
37660bb88ba4Smrg            pScrn->videoRam = 8192;
37670bb88ba4Smrg        }
37680bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
37690bb88ba4Smrg    }
3770fe5e51b7Smrg
3771fe5e51b7Smrg    if (pScrn->vtSema) {
3772fe5e51b7Smrg	if (pMga->FBDev) {
3773fe5e51b7Smrg	    fbdevHWRestore(pScrn);
3774fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3775fe5e51b7Smrg        } else {
3776fe5e51b7Smrg	    MGARestore(pScrn);
3777fe5e51b7Smrg	    vgaHWLock(hwp);
3778fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3779fe5e51b7Smrg	    vgaHWUnmapMem(pScrn);
3780fe5e51b7Smrg	}
3781fe5e51b7Smrg    }
37820bb88ba4Smrg
37830bb88ba4Smrg    if (pMga->is_G200SE)
37840bb88ba4Smrg    {
37850bb88ba4Smrg        pScrn->videoRam = VRTemp;
37860bb88ba4Smrg        pMga->FbMapSize = FBTemp;
37870bb88ba4Smrg    }
37880bb88ba4Smrg
37890bb88ba4Smrg#ifdef MGADRI
3790fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
3791fe5e51b7Smrg       MGADRICloseScreen(pScreen);
3792fe5e51b7Smrg       pMga->directRenderingEnabled=FALSE;
3793fe5e51b7Smrg   }
3794fe5e51b7Smrg#endif
3795fe5e51b7Smrg
3796fe5e51b7Smrg   if (pMga->DualHeadEnabled) {
3797fe5e51b7Smrg       DevUnion *pPriv;
3798fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3799fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3800fe5e51b7Smrg       pMgaEnt->refCount--;
3801fe5e51b7Smrg   }
3802fe5e51b7Smrg
3803acd6767fSmrg#ifdef USE_XAA
3804fe5e51b7Smrg    if (pMga->AccelInfoRec)
3805fe5e51b7Smrg	XAADestroyInfoRec(pMga->AccelInfoRec);
3806fe5e51b7Smrg#endif
3807fe5e51b7Smrg#ifdef USE_EXA
3808fe5e51b7Smrg    if (pMga->ExaDriver) {
3809fe5e51b7Smrg	exaDriverFini(pScreen);
38100bb88ba4Smrg	free(pMga->ExaDriver);
3811fe5e51b7Smrg    }
3812fe5e51b7Smrg#endif
3813fe5e51b7Smrg    if (pMga->CursorInfoRec)
3814fe5e51b7Smrg    	xf86DestroyCursorInfoRec(pMga->CursorInfoRec);
38150bb88ba4Smrg    free(pMga->ShadowPtr);
38160bb88ba4Smrg    free(pMga->DGAModes);
38170bb88ba4Smrg    free(pMga->adaptor);
38180bb88ba4Smrg    free(pMga->portPrivate);
38190bb88ba4Smrg    free(pMga->ScratchBuffer);
3820fe5e51b7Smrg
3821fe5e51b7Smrg    pScrn->vtSema = FALSE;
3822fe5e51b7Smrg
3823fe5e51b7Smrg    xf86ClearPrimInitDone(pScrn->entityList[0]);
3824fe5e51b7Smrg
3825fe5e51b7Smrg    if(pMga->BlockHandler)
3826fe5e51b7Smrg	pScreen->BlockHandler = pMga->BlockHandler;
3827fe5e51b7Smrg
3828fe5e51b7Smrg    pScreen->CloseScreen = pMga->CloseScreen;
3829fe5e51b7Smrg
38300bb88ba4Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3831fe5e51b7Smrg}
3832fe5e51b7Smrg
3833fe5e51b7Smrg
3834fe5e51b7Smrg/* Free up any persistent data structures */
3835fe5e51b7Smrg
3836fe5e51b7Smrg/* Optional */
3837fe5e51b7Smrgstatic void
38380bb88ba4SmrgMGAFreeScreen(FREE_SCREEN_ARGS_DECL)
3839fe5e51b7Smrg{
38400bb88ba4Smrg    SCRN_INFO_PTR(arg);
3841fe5e51b7Smrg    /*
3842fe5e51b7Smrg     * This only gets called when a screen is being deleted.  It does not
3843fe5e51b7Smrg     * get called routinely at the end of a server generation.
3844fe5e51b7Smrg     */
3845fe5e51b7Smrg    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
38460bb88ba4Smrg        vgaHWFreeHWRec(pScrn);
38470bb88ba4Smrg    MGAFreeRec(pScrn);
3848fe5e51b7Smrg
3849fe5e51b7Smrg}
3850fe5e51b7Smrg
3851eda3803bSmrg#ifndef HAVE_XF86MODEBANDWIDTH
3852eda3803bSmrg
3853eda3803bSmrg#define MODE_BANDWIDTH MODE_BAD
3854eda3803bSmrg
3855eda3803bSmrg/** Calculates the memory bandwidth (in MiB/sec) of a mode. */
3856eda3803bSmrgstatic unsigned int
3857eda3803bSmrgxf86ModeBandwidth(DisplayModePtr mode, int depth)
3858eda3803bSmrg{
3859eda3803bSmrg    float a_active, a_total, active_percent, pixels_per_second;
3860eda3803bSmrg    int bytes_per_pixel = (depth + 7) / 8;
3861eda3803bSmrg
3862eda3803bSmrg    if (!mode->HTotal || !mode->VTotal || !mode->Clock)
3863eda3803bSmrg	return 0;
3864eda3803bSmrg
3865eda3803bSmrg    a_active = mode->HDisplay * mode->VDisplay;
3866eda3803bSmrg    a_total = mode->HTotal * mode->VTotal;
3867eda3803bSmrg    active_percent = a_active / a_total;
3868eda3803bSmrg    pixels_per_second = active_percent * mode->Clock * 1000.0;
3869eda3803bSmrg
3870eda3803bSmrg    return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024));
3871eda3803bSmrg}
3872eda3803bSmrg#endif
3873fe5e51b7Smrg
3874fe5e51b7Smrg/* Checks if a mode is suitable for the selected chipset. */
3875fe5e51b7Smrg
3876fe5e51b7Smrg/* Optional */
3877fe5e51b7Smrgstatic ModeStatus
38780bb88ba4SmrgMGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
3879fe5e51b7Smrg{
38800bb88ba4Smrg    SCRN_INFO_PTR(arg);
3881fe5e51b7Smrg    int lace;
3882fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3883fe5e51b7Smrg
3884fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI) {
38850bb88ba4Smrg    	if (pMga->reg_1e24 == 0x01) {
38860bb88ba4Smrg	        if (mode->HDisplay > 1600)
38870bb88ba4Smrg	            return MODE_VIRTUAL_X;
38880bb88ba4Smrg	        if (mode->VDisplay > 1200)
38890bb88ba4Smrg	            return MODE_VIRTUAL_Y;
38900bb88ba4Smrg	        if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 244)
38910bb88ba4Smrg	            return MODE_BANDWIDTH;
389281f79626Smrg        } else if (pMga->reg_1e24 == 0x02) {
389381f79626Smrg            if (mode->HDisplay > 1920)
389481f79626Smrg                return MODE_VIRTUAL_X;
389581f79626Smrg            if (mode->VDisplay > 1200)
389681f79626Smrg                return MODE_VIRTUAL_Y;
389781f79626Smrg            if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 301)
389881f79626Smrg                return MODE_BANDWIDTH;
389981f79626Smrg        }
390081f79626Smrg        else {
390181f79626Smrg            if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 550)
390281f79626Smrg                return MODE_BANDWIDTH;
39030bb88ba4Smrg        }
3904eda3803bSmrg    } else if (pMga->is_G200WB){
3905eda3803bSmrg        if (mode->Flags & V_DBLSCAN)
3906eda3803bSmrg            return MODE_NO_DBLESCAN;
39076f68ce78Smrg        if (pMga->Chipset != PCI_CHIP_MGAG200_EW3_PCI)
39086f68ce78Smrg        {
39096f68ce78Smrg	    if (pMga->KVM && mode->HDisplay > 1280)
39106f68ce78Smrg	        return MODE_VIRTUAL_X;
39116f68ce78Smrg	    if (pMga->KVM && mode->VDisplay > 1024)
39126f68ce78Smrg	        return MODE_VIRTUAL_Y;
39136f68ce78Smrg	    if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 318.77)
39146f68ce78Smrg	        return MODE_BANDWIDTH;
39156f68ce78Smrg        }
3916eda3803bSmrg    } else if (pMga->is_G200EV
3917eda3803bSmrg	       && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 327)) {
39180bb88ba4Smrg	return MODE_BANDWIDTH;
391981f79626Smrg    } else if (pMga->is_G200EH && (pMga->Chipset != PCI_CHIP_MGAG200_EH3_PCI)
3920a31a186aSmrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 375)) {
3921a31a186aSmrg        return MODE_BANDWIDTH;
39220bb88ba4Smrg    } else if (pMga->is_G200ER
39230bb88ba4Smrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 550)) {
39240bb88ba4Smrg        return MODE_BANDWIDTH;
3925fe5e51b7Smrg    }
3926fe5e51b7Smrg
3927fe5e51b7Smrg    lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
3928fe5e51b7Smrg
3929fe5e51b7Smrg    if ((mode->CrtcHDisplay <= 2048) &&
3930fe5e51b7Smrg	(mode->CrtcHSyncStart <= 4096) &&
3931fe5e51b7Smrg	(mode->CrtcHSyncEnd <= 4096) &&
3932fe5e51b7Smrg	(mode->CrtcHTotal <= 4096) &&
3933fe5e51b7Smrg	(mode->CrtcVDisplay <= 2048 * lace) &&
3934fe5e51b7Smrg	(mode->CrtcVSyncStart <= 4096 * lace) &&
3935fe5e51b7Smrg	(mode->CrtcVSyncEnd <= 4096 * lace) &&
3936fe5e51b7Smrg	(mode->CrtcVTotal <= 4096 * lace)) {
3937fe5e51b7Smrg
3938fe5e51b7Smrg	/* Can't have horizontal panning for second head of G400 */
3939fe5e51b7Smrg	if (pMga->SecondCrtc) {
3940fe5e51b7Smrg	    if (flags == MODECHECK_FINAL) {
3941fe5e51b7Smrg		if (pMga->allowedWidth == 0)
3942fe5e51b7Smrg		    pMga->allowedWidth = pScrn->virtualX;
3943fe5e51b7Smrg		if (mode->HDisplay != pMga->allowedWidth)
3944fe5e51b7Smrg		    return(MODE_ONE_WIDTH);
3945fe5e51b7Smrg	    }
3946fe5e51b7Smrg	}
3947fe5e51b7Smrg
3948fe5e51b7Smrg	return(MODE_OK);
3949fe5e51b7Smrg    } else {
3950fe5e51b7Smrg	return(MODE_BAD);
3951fe5e51b7Smrg    }
3952fe5e51b7Smrg}
3953fe5e51b7Smrg
3954fe5e51b7Smrg
3955fe5e51b7Smrg/*
3956fe5e51b7Smrg * This routine is required but since we can't easily blank the
3957fe5e51b7Smrg * second display without risking powering off the monitor, return
3958fe5e51b7Smrg * FALSE and let the X server do something generic.
3959fe5e51b7Smrg */
3960fe5e51b7Smrgstatic Bool
3961fe5e51b7SmrgMGASaveScreenCrtc2(ScreenPtr pScreen, int mode)
3962fe5e51b7Smrg{
3963fe5e51b7Smrg    return FALSE;
3964fe5e51b7Smrg}
3965fe5e51b7Smrg
3966fe5e51b7Smrg/* Do screen blanking */
3967fe5e51b7Smrg
3968fe5e51b7Smrgstatic Bool
3969fe5e51b7SmrgMGASaveScreen(ScreenPtr pScreen, int mode)
3970fe5e51b7Smrg{
3971fe5e51b7Smrg    return vgaHWSaveScreen(pScreen, mode);
3972fe5e51b7Smrg}
3973fe5e51b7Smrg
3974fe5e51b7Smrg
3975fe5e51b7Smrg/*
3976fe5e51b7Smrg * MGADisplayPowerManagementSet --
3977fe5e51b7Smrg *
3978fe5e51b7Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode.
3979fe5e51b7Smrg *
3980fe5e51b7Smrg * XXX This needs fixing for sync-on-green!
3981fe5e51b7Smrg */
3982fe5e51b7Smrgvoid
3983fe5e51b7SmrgMGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
3984fe5e51b7Smrg			     int flags)
3985fe5e51b7Smrg{
3986fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
3987fe5e51b7Smrg	unsigned char seq1 = 0, crtcext1 = 0;
3988fe5e51b7Smrg
3989fe5e51b7Smrg	switch (PowerManagementMode)
3990fe5e51b7Smrg	{
3991fe5e51b7Smrg	case DPMSModeOn:
3992fe5e51b7Smrg	    /* Screen: On; HSync: On, VSync: On */
3993fe5e51b7Smrg	    seq1 = 0x00;
3994fe5e51b7Smrg	    crtcext1 = 0x00;
3995fe5e51b7Smrg	    break;
3996fe5e51b7Smrg	case DPMSModeStandby:
3997fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: On */
3998fe5e51b7Smrg	    seq1 = 0x20;
3999fe5e51b7Smrg	    crtcext1 = 0x10;
4000fe5e51b7Smrg	    break;
4001fe5e51b7Smrg	case DPMSModeSuspend:
4002fe5e51b7Smrg	    /* Screen: Off; HSync: On, VSync: Off */
4003fe5e51b7Smrg	    seq1 = 0x20;
4004fe5e51b7Smrg	    crtcext1 = 0x20;
4005fe5e51b7Smrg	    break;
4006fe5e51b7Smrg	case DPMSModeOff:
4007fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: Off */
4008fe5e51b7Smrg	    seq1 = 0x20;
4009fe5e51b7Smrg	    crtcext1 = 0x30;
4010fe5e51b7Smrg	    break;
4011fe5e51b7Smrg	}
4012fe5e51b7Smrg
4013fe5e51b7Smrg	/* XXX Prefer an implementation that doesn't depend on VGA specifics */
4014fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
4015fe5e51b7Smrg	seq1 |= INREG8(MGAREG_SEQ_DATA) & ~0x20;
4016fe5e51b7Smrg	MGAWAITVSYNC();
4017fe5e51b7Smrg	MGAWAITBUSY();
4018fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_DATA, seq1);
4019fe5e51b7Smrg	usleep(20000);
4020fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);	/* Select CRTCEXT1 */
4021fe5e51b7Smrg	crtcext1 |= INREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
4022fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1);
4023fe5e51b7Smrg}
4024fe5e51b7Smrg
4025fe5e51b7Smrg
4026fe5e51b7Smrgvoid
4027fe5e51b7SmrgMGADisplayPowerManagementSetCrtc2(ScrnInfoPtr pScrn, int PowerManagementMode,
4028fe5e51b7Smrg				  int flags)
4029fe5e51b7Smrg{
4030fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
4031fe5e51b7Smrg	CARD32 val = INREG(MGAREG_C2CTL);
4032fe5e51b7Smrg
4033fe5e51b7Smrg	if (PowerManagementMode==DPMSModeOn) {
4034fe5e51b7Smrg		/* Enable CRTC2 */
4035fe5e51b7Smrg		val |= MGAREG_C2CTL_C2_EN;
4036fe5e51b7Smrg		val &= ~MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4037fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
4038fe5e51b7Smrg		/* Restore normal MAVEN values */
4039fe5e51b7Smrg		if (pMga->Maven) {
4040fe5e51b7Smrg			/* if TV MODE -- for later implementation
4041fe5e51b7Smrg				MAVW(MONEN, 0xb3);
4042fe5e51b7Smrg				MAVW(MONSET, 0x20);
4043fe5e51b7Smrg				MAVW(OUTMODE, 0x08);    output: SVideo/Composite
4044fe5e51b7Smrg			        MAVW(STABLE, 0x02);             makes picture stable?
4045fe5e51b7Smrg				fixme? linux uses 0x14...
4046fe5e51b7Smrg				MAVW(TEST, (MAVR(TEST) & 0x10));
4047fe5e51b7Smrg
4048fe5e51b7Smrg			 */
4049fe5e51b7Smrg			/* else monitor mode */
4050fe5e51b7Smrg
4051fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONEN, 0xb2);
4052fe5e51b7Smrg			/* must be set to this in monitor mode */
4053fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONSET, 0x20);
4054fe5e51b7Smrg			/* output: monitor mode */
4055fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x03);
4056fe5e51b7Smrg			/* makes picture stable? */
4057fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x22);
4058fe5e51b7Smrg			/* turn off test signal */
4059fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x00);
4060fe5e51b7Smrg		}
4061fe5e51b7Smrg	}
4062fe5e51b7Smrg	else {
4063fe5e51b7Smrg		/* Disable CRTC2 video */
4064fe5e51b7Smrg		val |= MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4065fe5e51b7Smrg		val &= ~MGAREG_C2CTL_C2_EN;
4066fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
4067fe5e51b7Smrg
4068fe5e51b7Smrg		/* Disable MAVEN display */
4069fe5e51b7Smrg		if (pMga->Maven) {
4070fe5e51b7Smrg		/* In order to blank the 2nd display, we must set some MAVEN registers.
4071fe5e51b7Smrg		 * It seems that not always the same values work on different hardware so
4072fe5e51b7Smrg		 * we try a few different (possibly redundant) ones. */
4073fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x6a); */
4074fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x03); */
4075fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x10); */
4076fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x80);
4077fe5e51b7Smrg		}
4078fe5e51b7Smrg
4079fe5e51b7Smrg	}
4080fe5e51b7Smrg}
4081fe5e51b7Smrg
4082fe5e51b7Smrg
4083fe5e51b7Smrgstatic void
40840bb88ba4SmrgMGABlockHandler (BLOCKHANDLER_ARGS_DECL)
40850bb88ba4Smrg{
40860bb88ba4Smrg    SCREEN_PTR(arg);
40870bb88ba4Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
4088fe5e51b7Smrg    MGAPtr         pMga = MGAPTR(pScrn);
4089fe5e51b7Smrg
4090fe5e51b7Smrg    if(pMga->PaletteLoadCallback)
4091fe5e51b7Smrg	(*pMga->PaletteLoadCallback)(pScrn);
4092fe5e51b7Smrg
4093fe5e51b7Smrg    pScreen->BlockHandler = pMga->BlockHandler;
40940bb88ba4Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
4095fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
4096fe5e51b7Smrg
4097fe5e51b7Smrg    if(pMga->VideoTimerCallback) {
4098fe5e51b7Smrg	UpdateCurrentTime();
4099fe5e51b7Smrg	(*pMga->VideoTimerCallback)(pScrn, currentTime.milliseconds);
4100fe5e51b7Smrg    }
4101fe5e51b7Smrg
4102fe5e51b7Smrg    if(pMga->RenderCallback)
4103fe5e51b7Smrg	(*pMga->RenderCallback)(pScrn);
4104fe5e51b7Smrg}
4105fe5e51b7Smrg
4106fe5e51b7Smrg#if defined (EXTRADEBUG)
4107fe5e51b7Smrg/*
4108fe5e51b7Smrg * some functions to track input/output in the server
4109fe5e51b7Smrg */
4110fe5e51b7Smrg
4111fe5e51b7SmrgCARD8
4112fe5e51b7SmrgMGAdbg_inreg8(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4113fe5e51b7Smrg{
4114fe5e51b7Smrg    CARD8 ret;
4115fe5e51b7Smrg
4116fe5e51b7Smrg    ret = MMIO_IN8(MGAPTR(pScrn)->IOBase,addr);
4117fe5e51b7Smrg    if(verbose)
4118fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4119fe5e51b7Smrg			"inreg8 : %s: 0x%8x = 0x%x\n",func, addr,ret);
4120fe5e51b7Smrg    return ret;
4121fe5e51b7Smrg}
4122fe5e51b7Smrg
4123fe5e51b7SmrgCARD16
4124fe5e51b7SmrgMGAdbg_inreg16(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4125fe5e51b7Smrg{
4126fe5e51b7Smrg    CARD16 ret;
4127fe5e51b7Smrg
4128fe5e51b7Smrg    ret = MMIO_IN16(MGAPTR(pScrn)->IOBase,addr);
4129fe5e51b7Smrg    if(verbose)
4130fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4131fe5e51b7Smrg			"inreg16: %s: 0x%8x = 0x%x\n",func, addr,ret);
4132fe5e51b7Smrg    return ret;
4133fe5e51b7Smrg}
4134fe5e51b7Smrg
4135fe5e51b7SmrgCARD32
4136fe5e51b7SmrgMGAdbg_inreg32(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4137fe5e51b7Smrg{
4138fe5e51b7Smrg    CARD32 ret;
4139fe5e51b7Smrg
4140fe5e51b7Smrg    ret = MMIO_IN32(MGAPTR(pScrn)->IOBase,addr);
4141fe5e51b7Smrg    if(verbose)
4142fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4143fe5e51b7Smrg			"inreg32: %s: 0x%8x = 0x%x\n",func, addr,ret);
4144fe5e51b7Smrg    return ret;
4145fe5e51b7Smrg}
4146fe5e51b7Smrg
4147fe5e51b7Smrgvoid
4148fe5e51b7SmrgMGAdbg_outreg8(ScrnInfoPtr pScrn,int addr,int val, char* func)
4149fe5e51b7Smrg{
4150fe5e51b7Smrg    CARD8 ret;
4151fe5e51b7Smrg
4152fe5e51b7Smrg#if 0
4153fe5e51b7Smrg    if( addr = MGAREG_CRTCEXT_DATA )
4154fe5e51b7Smrg    	return;
4155fe5e51b7Smrg#endif
4156fe5e51b7Smrg    if( addr != 0x3c00 ) {
4157fe5e51b7Smrg	ret = MGAdbg_inreg8(pScrn,addr,0,func);
4158fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4159fe5e51b7Smrg			"outreg8 : %s: 0x%8x = 0x%x was 0x%x\n",
4160fe5e51b7Smrg			func,addr,val,ret);
4161fe5e51b7Smrg    }
4162fe5e51b7Smrg    else {
4163fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "outreg8 : %s: index 0x%x\n",
4164fe5e51b7Smrg	func,val);
4165fe5e51b7Smrg    }
4166fe5e51b7Smrg    MMIO_OUT8(MGAPTR(pScrn)->IOBase,addr,val);
4167fe5e51b7Smrg}
4168fe5e51b7Smrg
4169fe5e51b7Smrgvoid
4170fe5e51b7SmrgMGAdbg_outreg16(ScrnInfoPtr pScrn,int addr,int val, char* func)
4171fe5e51b7Smrg{
4172fe5e51b7Smrg    CARD16 ret;
4173fe5e51b7Smrg
4174fe5e51b7Smrg#if 0
4175fe5e51b7Smrg    if (addr == MGAREG_CRTCEXT_INDEX)
4176fe5e51b7Smrg    	return;
4177fe5e51b7Smrg#endif
4178fe5e51b7Smrg    ret = MGAdbg_inreg16(pScrn,addr,0, func);
4179fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4180fe5e51b7Smrg			"outreg16: %s: 0x%8x = 0x%x was 0x%x\n",
4181fe5e51b7Smrg			func,addr,val,ret);
4182fe5e51b7Smrg    MMIO_OUT16(MGAPTR(pScrn)->IOBase,addr,val);
4183fe5e51b7Smrg}
4184fe5e51b7Smrg
4185fe5e51b7Smrgvoid
4186fe5e51b7SmrgMGAdbg_outreg32(ScrnInfoPtr pScrn,int addr,int val, char* func)
4187fe5e51b7Smrg{
4188fe5e51b7Smrg    CARD32 ret;
4189fe5e51b7Smrg
4190fe5e51b7Smrg    if (((addr & 0xff00) == 0x1c00)
4191fe5e51b7Smrg    	&& (addr != 0x1c04)
4192fe5e51b7Smrg/*    	&& (addr != 0x1c1c) */
4193fe5e51b7Smrg    	&& (addr != 0x1c20)
4194fe5e51b7Smrg    	&& (addr != 0x1c24)
4195fe5e51b7Smrg    	&& (addr != 0x1c80)
4196fe5e51b7Smrg    	&& (addr != 0x1c8c)
4197fe5e51b7Smrg    	&& (addr != 0x1c94)
4198fe5e51b7Smrg    	&& (addr != 0x1c98)
4199fe5e51b7Smrg    	&& (addr != 0x1c9c)
4200fe5e51b7Smrg	 ) {
4201fe5e51b7Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: refused address 0x%x\n",
4202fe5e51b7Smrg			func,addr);
4203fe5e51b7Smrg    	return;
4204fe5e51b7Smrg    }
4205fe5e51b7Smrg    ret = MGAdbg_inreg32(pScrn,addr,0, func);
4206fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4207fe5e51b7Smrg			"outreg32: %s: 0x%8x = 0x%x was 0x%x\n",
4208fe5e51b7Smrg			func,addr,val,ret);
4209fe5e51b7Smrg    MMIO_OUT32(MGAPTR(pScrn)->IOBase,addr,val);
4210fe5e51b7Smrg}
4211fe5e51b7Smrg#endif /* DEBUG */
4212fe5e51b7Smrg
4213fe5e51b7Smrgstatic void
4214fe5e51b7SmrgMGAG100BlackMagic(ScrnInfoPtr pScrn)
4215fe5e51b7Smrg{
4216fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
4217fe5e51b7Smrg
4218fe5e51b7Smrg    OUTREG(MGAREG_PLNWT, ~(CARD32)0x0);
4219fe5e51b7Smrg    /* reset memory */
4220fe5e51b7Smrg    OUTREG(MGAREG_MACCESS, 1<<15);
4221fe5e51b7Smrg    usleep(10);
4222fe5e51b7Smrg}
4223