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