neo_driver.c revision 692f60a7
1/**********************************************************************
2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas.
3
4                        All Rights Reserved
5
6Permission to use, copy, modify, distribute, and sell this software and
7its documentation for any purpose is hereby granted without fee,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of Precision Insight not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.  Precision Insight
13and its suppliers make no representations about the suitability of this
14software for any purpose.  It is provided "as is" without express or
15implied warranty.
16
17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24**********************************************************************/
25
26/*
27 * Copyright 1998, 1999 Egbert Eich
28 * Copyright 2000, 2001 SuSE GmbH, Author: Egbert Eich
29 * Copyright 2002 SuSE Linux AG, Author: Egbert Eich
30 * Copyright 2002 Shigehiro Nomura
31 */
32
33/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c,v 1.74 2003/12/31 05:07:30 dawes Exp $ */
34
35/*
36 * The original Precision Insight driver for
37 * XFree86 v.3.3 has been sponsored by Red Hat.
38 *
39 * Authors:
40 *   Jens Owen (jens@tungstengraphics.com)
41 *   Kevin E. Martin (kevin@precisioninsight.com)
42 *
43 * Port to Xfree86 v.4.0
44 *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
45 */
46
47#ifdef HAVE_CONFIG_H
48#include "config.h"
49#endif
50
51/* All drivers should typically include these */
52#include "xf86.h"
53#include "xf86_OSproc.h"
54
55/* Everything using inb/outb, etc needs "compiler.h" */
56#include "compiler.h"
57
58#include "xf86Resources.h"
59
60/* Drivers for PCI hardware need this */
61#include "xf86PciInfo.h"
62
63/* Drivers that need to access the PCI config space directly need this */
64#include "xf86Pci.h"
65
66/* This is used for module versioning */
67#include "xf86Version.h"
68
69/* All drivers using the vgahw module need this */
70#include "vgaHW.h"
71
72/* All drivers initialising the SW cursor need this */
73#include "mipointer.h"
74
75/* All drivers implementing backing store need this */
76#include "mibstore.h"
77
78/* All drivers using the mi banking wrapper need this */
79#include "mibank.h"
80
81/* All drivers using the mi colormap manipulation need this */
82#include "micmap.h"
83
84#include "xf86cmap.h"
85
86#include "fb.h"
87#include "fbpseudocolor.h"
88
89/* Needed by Resources Access Control (RAC) */
90#include "xf86RAC.h"
91
92/* int10 */
93#include "xf86int10.h"
94#include "vbe.h"
95
96/* Needed for Device Data Channel (DDC) support */
97#include "xf86DDC.h"
98
99#include "picturestr.h"
100
101#include "xf86xv.h"
102#include <X11/extensions/Xv.h>
103
104/*
105 * Driver data structures.
106 */
107#include "neo.h"
108#include "neo_reg.h"
109#include "neo_macros.h"
110
111/* These need to be checked */
112#include <X11/X.h>
113#include <X11/Xproto.h>
114#include "scrnintstr.h"
115#include "servermd.h"
116#ifdef XFreeXDGA
117#define _XF86DGA_SERVER_
118#include <X11/extensions/xf86dgastr.h>
119#endif
120
121/* Mandatory functions */
122static const OptionInfoRec *	NEOAvailableOptions(int chipid, int busid);
123static void     NEOIdentify(int flags);
124static Bool     NEOProbe(DriverPtr drv, int flags);
125static Bool     NEOPreInit(ScrnInfoPtr pScrn, int flags);
126static Bool     NEOScreenInit(int Index, ScreenPtr pScreen, int argc,
127                                  char **argv);
128static Bool     NEOEnterVT(int scrnIndex, int flags);
129static void     NEOLeaveVT(int scrnIndex, int flags);
130static Bool     NEOCloseScreen(int scrnIndex, ScreenPtr pScreen);
131static void     NEOFreeScreen(int scrnIndex, int flags);
132static ModeStatus NEOValidMode(int scrnIndex, DisplayModePtr mode,
133                               Bool verbose, int flags);
134
135/* Internally used functions */
136static int      neoFindIsaDevice(GDevPtr dev);
137static Bool     neoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
138static void     neoSave(ScrnInfoPtr pScrn);
139static void     neoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg,
140				 NeoRegPtr NeoReg, Bool restoreText);
141static void     neoLock(ScrnInfoPtr pScrn);
142static void     neoUnlock(ScrnInfoPtr pScrn);
143static Bool	neoMapMem(ScrnInfoPtr pScrn);
144static Bool	neoUnmapMem(ScrnInfoPtr pScrn);
145static void     neoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg,
146				     NeoRegPtr restore);
147static void     neoCalcVCLK(ScrnInfoPtr pScrn, long freq);
148static xf86MonPtr  neo_ddc1(int scrnIndex);
149static Bool     neoDoDDC1(ScrnInfoPtr pScrn);
150static Bool     neoDoDDC2(ScrnInfoPtr pScrn);
151static Bool     neoDoDDCVBE(ScrnInfoPtr pScrn);
152static void     neoProbeDDC(ScrnInfoPtr pScrn, int index);
153static void     NeoDisplayPowerManagementSet(ScrnInfoPtr pScrn,
154				int PowerManagementMode, int flags);
155static int      neoFindMode(int xres, int yres, int depth);
156
157#define NEO_VERSION 4000
158#define NEO_NAME "NEOMAGIC"
159#define NEO_DRIVER_NAME "neomagic"
160
161#define NEO_MAJOR_VERSION 1
162#define NEO_MINOR_VERSION 1
163#define NEO_PATCHLEVEL 1
164
165/*
166 * This is intentionally screen-independent.  It indicates the binding
167 * choice made in the first PreInit.
168 */
169static int pix24bpp = 0;
170
171
172static biosMode bios8[] = {
173    { 320, 240, 0x40 },
174    { 300, 400, 0x42 },
175    { 640, 400, 0x20 },
176    { 640, 480, 0x21 },
177    { 800, 600, 0x23 },
178    { 1024, 768, 0x25 }
179};
180
181static biosMode bios15[] = {
182    { 320, 200, 0x2D },
183    { 640, 480, 0x30 },
184    { 800, 600, 0x33 },
185    { 1024, 768, 0x36 }
186};
187
188static biosMode bios16[] = {
189    { 320, 200, 0x2e },
190    { 320, 240, 0x41 },
191    { 300, 400, 0x43 },
192    { 640, 480, 0x31 },
193    { 800, 600, 0x34 },
194    { 1024, 768, 0x37 }
195};
196
197static biosMode bios24[] = {
198    { 640, 480, 0x32 },
199    { 800, 600, 0x35 },
200    { 1024, 768, 0x38 }
201};
202
203static DisplayModeRec neo800x480Mode = {
204	NULL,           /* prev */
205	NULL,           /* next */
206	"800x480",      /* identifier of this mode */
207	MODE_OK,        /* mode status */
208	M_T_BUILTIN,    /* mode type */
209	35260,		/* Clock frequency */
210	800,		/* HDisplay */
211	856,		/* HSyncStart */
212	1040,		/* HSyncEnd */
213	1056,		/* HTotal */
214	0,		/* HSkew */
215	480,		/* VDisplay */
216	480,		/* VSyncStart */
217	486,		/* VSyncEnd */
218	488,		/* VTotal */
219	0,		/* VScan */
220	V_PHSYNC | V_PVSYNC,	/* Flags */
221	-1,		/* ClockIndex */
222	35260,		/* SynthClock */
223	800,		/* CRTC HDisplay */
224	800,            /* CRTC HBlankStart */
225	856,            /* CRTC HSyncStart */
226	1040,           /* CRTC HSyncEnd */
227	872,            /* CRTC HBlankEnd */
228	1048,           /* CRTC HTotal */
229	0,              /* CRTC HSkew */
230	480,		/* CRTC VDisplay */
231	480,		/* CRTC VBlankStart */
232	480,		/* CRTC VSyncStart */
233	486,		/* CRTC VSyncEnd */
234	487,		/* CRTC VBlankEnd */
235	488,		/* CRTC VTotal */
236	FALSE,		/* CrtcHAdjusted */
237	FALSE,		/* CrtcVAdjusted */
238	0,		/* PrivSize */
239	NULL,		/* Private */
240	0.0,		/* HSync */
241	0.0		/* VRefresh */
242};
243
244static DisplayModeRec neo1024x480Mode = {
245	NULL,           /* prev */
246	NULL,           /* next */
247	"1024x480",      /* identifier of this mode */
248	MODE_OK,        /* mode status */
249	M_T_BUILTIN,    /* mode type */
250	45900,		/* Clock frequency */
251	1024,		/* HDisplay */
252	1048,		/* HSyncStart */
253	1184,		/* HSyncEnd */
254	1344,		/* HTotal */
255	0,		/* HSkew */
256	480,		/* VDisplay */
257	480,		/* VSyncStart */
258	486,		/* VSyncEnd */
259	488,		/* VTotal */
260	0,		/* VScan */
261	V_PHSYNC | V_PVSYNC,	/* Flags */
262	-1,		/* ClockIndex */
263	45900,		/* SynthClock */
264	1024,		/* CRTC HDisplay */
265	1024,            /* CRTC HBlankStart */
266	1048,            /* CRTC HSyncStart */
267	1184,           /* CRTC HSyncEnd */
268	1072,            /* CRTC HBlankEnd */
269	1344,           /* CRTC HTotal */
270	0,              /* CRTC HSkew */
271	480,		/* CRTC VDisplay */
272	480,		/* CRTC VBlankStart */
273	480,		/* CRTC VSyncStart */
274	486,		/* CRTC VSyncEnd */
275	487,		/* CRTC VBlankEnd */
276	488,		/* CRTC VTotal */
277	FALSE,		/* CrtcHAdjusted */
278	FALSE,		/* CrtcVAdjusted */
279	0,		/* PrivSize */
280	NULL,		/* Private */
281	0.0,		/* HSync */
282	0.0		/* VRefresh */
283};
284
285/*
286 * This contains the functions needed by the server after loading the driver
287 * module.  It must be supplied, and gets passed back by the SetupProc
288 * function in the dynamic case.  In the static case, a reference to this
289 * is compiled in, and this requires that the name of this DriverRec be
290 * an upper-case version of the driver name.
291 */
292
293_X_EXPORT DriverRec NEOMAGIC = {
294    NEO_VERSION,
295    NEO_DRIVER_NAME,
296    NEOIdentify,
297    NEOProbe,
298    NEOAvailableOptions,
299    NULL,
300    0
301};
302
303static SymTabRec NEOChipsets[] = {
304    { NM2070,   "neo2070" },
305    { NM2090,   "neo2090" },
306    { NM2093,   "neo2093" },
307    { NM2097,   "neo2097" },
308    { NM2160,   "neo2160" },
309    { NM2200,   "neo2200" },
310    { NM2230,   "neo2230" },
311    { NM2360,   "neo2360" },
312    { NM2380,   "neo2380" },
313    { -1,		 NULL }
314};
315
316/* Conversion PCI ID to chipset name */
317static PciChipsets NEOPCIchipsets[] = {
318    { NM2070,  PCI_CHIP_NM2070,  RES_SHARED_VGA },
319    { NM2090,  PCI_CHIP_NM2090,  RES_SHARED_VGA },
320    { NM2093,  PCI_CHIP_NM2093,  RES_SHARED_VGA },
321    { NM2097,  PCI_CHIP_NM2097,  RES_SHARED_VGA },
322    { NM2160,  PCI_CHIP_NM2160,  RES_SHARED_VGA },
323    { NM2200,  PCI_CHIP_NM2200,  RES_SHARED_VGA },
324    { NM2230,  PCI_CHIP_NM2230,  RES_SHARED_VGA },
325    { NM2360,  PCI_CHIP_NM2360,  RES_SHARED_VGA },
326    { NM2380,  PCI_CHIP_NM2380,  RES_SHARED_VGA },
327    { -1,	     -1,	     RES_UNDEFINED}
328};
329
330static IsaChipsets NEOISAchipsets[] = {
331    { NM2070,               RES_EXCLUSIVE_VGA },
332    { NM2090,               RES_EXCLUSIVE_VGA },
333    { NM2093,               RES_EXCLUSIVE_VGA },
334    { NM2097,               RES_EXCLUSIVE_VGA },
335    { NM2160,               RES_EXCLUSIVE_VGA },
336    { NM2200,               RES_EXCLUSIVE_VGA },
337    { -1,			RES_UNDEFINED }
338};
339
340/* The options supported by the Neomagic Driver */
341typedef enum {
342    OPTION_NOLINEAR_MODE,
343    OPTION_NOACCEL,
344    OPTION_SW_CURSOR,
345    OPTION_NO_MMIO,
346    OPTION_INTERN_DISP,
347    OPTION_EXTERN_DISP,
348    OPTION_LCD_CENTER,
349    OPTION_LCD_STRETCH,
350    OPTION_SHADOW_FB,
351    OPTION_PCI_BURST,
352    OPTION_PROG_LCD_MODE_REGS,
353    OPTION_PROG_LCD_MODE_STRETCH,
354    OPTION_OVERRIDE_VALIDATE_MODE,
355    OPTION_SHOWCACHE,
356    OPTION_ROTATE,
357    OPTION_VIDEO_KEY,
358    OPTION_OVERLAYMEM,
359    OPTION_VIDEO_INTERLACE,
360    OPTION_DISPLAY_HEIGHT_480,
361    OPTION_STRANGE_LOCKUPS
362} NEOOpts;
363
364static const OptionInfoRec NEO_2070_Options[] = {
365    { OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
366    { OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
367    { OPTION_NO_MMIO,	"noMMIO",	OPTV_BOOLEAN,	{0}, FALSE },
368    { OPTION_INTERN_DISP,"internDisp",	OPTV_BOOLEAN,	{0}, FALSE },
369    { OPTION_EXTERN_DISP,"externDisp",  OPTV_BOOLEAN,	{0}, FALSE },
370    { OPTION_LCD_CENTER, "LcdCenter",	OPTV_BOOLEAN,	{0}, FALSE },
371    { OPTION_LCD_STRETCH, "NoStretch",	OPTV_BOOLEAN,	{0}, FALSE },
372    { OPTION_SHADOW_FB,   "ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
373    { OPTION_PCI_BURST,	 "pciBurst",	OPTV_BOOLEAN,   {0}, FALSE },
374    { OPTION_SHOWCACHE,  "ShowCache",   OPTV_BOOLEAN,	{0}, FALSE },
375    { OPTION_ROTATE, 	 "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
376    { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs",
377      OPTV_BOOLEAN, {0}, FALSE },
378    { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch",
379      OPTV_BOOLEAN, {0}, FALSE },
380    { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
381      OPTV_BOOLEAN, {0}, FALSE },
382    { OPTION_VIDEO_KEY, "VideoKey",     OPTV_INTEGER,   {0}, FALSE },
383    { OPTION_OVERLAYMEM, "OverlayMem",  OPTV_INTEGER,   {0}, FALSE },
384    { OPTION_VIDEO_INTERLACE, "Interlace",
385      OPTV_INTEGER,   {0}, FALSE },
386    { -1,                  NULL,           OPTV_NONE,	{0}, FALSE }
387};
388
389static const OptionInfoRec NEOOptions[] = {
390    { OPTION_NOLINEAR_MODE,"NoLinear",  OPTV_BOOLEAN,	{0}, FALSE },
391    { OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
392    { OPTION_SW_CURSOR,	"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
393    { OPTION_NO_MMIO,	"noMMIO",	OPTV_BOOLEAN,	{0}, FALSE },
394    { OPTION_INTERN_DISP,"internDisp",	OPTV_BOOLEAN,	{0}, FALSE },
395    { OPTION_EXTERN_DISP,"externDisp",	OPTV_BOOLEAN,	{0}, FALSE },
396    { OPTION_LCD_CENTER, "LcdCenter",	OPTV_BOOLEAN,	{0}, FALSE },
397    { OPTION_SHADOW_FB,  "ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
398    { OPTION_LCD_STRETCH,"NoStretch",	OPTV_BOOLEAN,	{0}, FALSE },
399    { OPTION_PCI_BURST,	 "pciBurst",	OPTV_BOOLEAN,	{0}, FALSE },
400    { OPTION_SHOWCACHE,  "ShowCache",   OPTV_BOOLEAN,	{0}, FALSE },
401    { OPTION_ROTATE, 	 "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
402    { OPTION_STRANGE_LOCKUPS, "StrangeLockups", OPTV_BOOLEAN, {0}, FALSE },
403    { OPTION_DISPLAY_HEIGHT_480, "DisplayHeight480",
404      OPTV_BOOLEAN, {0}, FALSE },
405    { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs",
406      OPTV_BOOLEAN, {0}, FALSE },
407    { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch",
408      OPTV_BOOLEAN, {0}, FALSE },
409    { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
410      OPTV_BOOLEAN, {0}, FALSE },
411    { OPTION_VIDEO_KEY, "VideoKey",     OPTV_INTEGER,   {0}, FALSE },
412    { OPTION_OVERLAYMEM, "OverlayMem",  OPTV_INTEGER,   {0}, FALSE },
413    { OPTION_VIDEO_INTERLACE, "Interlace",
414      OPTV_INTEGER,   {0}, FALSE },
415    { -1,                  NULL,           OPTV_NONE,	{0}, FALSE }
416};
417
418/*
419 * List of symbols from other modules that this module references.  This
420 * list is used to tell the loader that it is OK for symbols here to be
421 * unresolved providing that it hasn't been told that they haven't been
422 * told that they are essential via a call to xf86LoaderReqSymbols() or
423 * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
424 * unresolved symbols that are not required.
425 */
426
427static const char *vgahwSymbols[] = {
428    "vgaHWFreeHWRec",
429    "vgaHWGetHWRec",
430    "vgaHWGetIOBase",
431    "vgaHWGetIndex",
432    "vgaHWInit",
433    "vgaHWLock",
434    "vgaHWMapMem",
435    "vgaHWProtect",
436    "vgaHWRestore",
437    "vgaHWSave",
438    "vgaHWSaveScreenWeak",
439    "vgaHWSetStdFuncs",
440    "vgaHWUnlock",
441    "vgaHWddc1SetSpeedWeak",
442    NULL
443};
444
445static const char *fbSymbols[] = {
446    "fbPictureInit",
447    "fbScreenInit",
448    NULL
449};
450
451static const char *xaaSymbols[] = {
452    "XAACreateInfoRec",
453    "XAADestroyInfoRec",
454    "XAAInit",
455    NULL
456};
457
458static const char *ramdacSymbols[] = {
459    "xf86CreateCursorInfoRec",
460    "xf86DestroyCursorInfoRec",
461    "xf86InitCursor",
462    NULL
463};
464
465static const char *shadowSymbols[] = {
466    "shadowInit",
467    NULL
468};
469
470static const char *ddcSymbols[] = {
471    "xf86DoEDID_DDC1",
472    "xf86DoEDID_DDC2",
473    "xf86PrintEDID",
474    "xf86SetDDCproperties",
475    NULL
476};
477
478static const char *vbeSymbols[] = {
479    "VBEInit",
480    "vbeDoEDID",
481    "vbeFree",
482    NULL
483};
484
485static const char *i2cSymbols[] = {
486    "xf86CreateI2CBusRec",
487    "xf86I2CBusInit",
488    NULL
489};
490
491#ifdef XFree86LOADER
492
493static MODULESETUPPROTO(neoSetup);
494
495static XF86ModuleVersionInfo neoVersRec =
496{
497	"neomagic",
498	MODULEVENDORSTRING,
499	MODINFOSTRING1,
500	MODINFOSTRING2,
501	XORG_VERSION_CURRENT,
502	NEO_MAJOR_VERSION, NEO_MINOR_VERSION, NEO_PATCHLEVEL,
503	ABI_CLASS_VIDEODRV,
504	ABI_VIDEODRV_VERSION,
505	MOD_CLASS_VIDEODRV,
506	{0,0,0,0}
507};
508
509/*
510 * This is the module init data.
511 * Its name has to be the driver name followed by ModuleData
512 */
513_X_EXPORT XF86ModuleData neomagicModuleData = { &neoVersRec, neoSetup, NULL };
514
515static pointer
516neoSetup(pointer module, pointer opts, int *errmaj, int *errmin)
517{
518    static Bool setupDone = FALSE;
519
520    if (!setupDone) {
521	setupDone = TRUE;
522        xf86AddDriver(&NEOMAGIC, module, 0);
523
524	/*
525	 * Modules that this driver always requires can be loaded here
526	 * by calling LoadSubModule().
527	 */
528
529	/*
530	 * Tell the loader about symbols from other modules that this module
531	 * might refer to.
532	 */
533	LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
534			  ramdacSymbols, shadowSymbols,
535			  ddcSymbols, vbeSymbols, i2cSymbols, NULL);
536	/*
537	 * The return value must be non-NULL on success even though there
538	 * is no TearDownProc.
539	 */
540  	return (pointer)1;
541    } else {
542	if (errmaj) *errmaj = LDR_ONCEONLY;
543	return NULL;
544    }
545}
546
547#endif /* XFree86LOADER */
548
549static Bool
550NEOGetRec(ScrnInfoPtr pScrn)
551{
552    /*
553     * Allocate a NEORec, and hook it into pScrn->driverPrivate.
554     * pScrn->driverPrivate is initialised to NULL, so we can check if
555     * the allocation has already been done.
556     */
557    if (pScrn->driverPrivate != NULL)
558	return TRUE;
559
560    pScrn->driverPrivate = xnfcalloc(sizeof(NEORec), 1);
561
562    if (pScrn->driverPrivate == NULL)
563	return FALSE;
564        return TRUE;
565}
566
567static void
568NEOFreeRec(ScrnInfoPtr pScrn)
569{
570    if (pScrn->driverPrivate == NULL)
571	return;
572    xfree(pScrn->driverPrivate);
573    pScrn->driverPrivate = NULL;
574}
575
576static const OptionInfoRec *
577NEOAvailableOptions(int chipid, int busid)
578{
579    int chip = (chipid & 0x0000ffff);
580
581    if (chip == PCI_CHIP_NM2070)
582	return NEO_2070_Options;
583    else
584    	return NEOOptions;
585}
586
587/* Mandatory */
588static void
589NEOIdentify(int flags)
590{
591    xf86PrintChipsets(NEO_NAME, "Driver for Neomagic chipsets",
592			NEOChipsets);
593}
594
595/* Mandatory */
596static Bool
597NEOProbe(DriverPtr drv, int flags)
598{
599    Bool foundScreen = FALSE;
600    int numDevSections, numUsed;
601    GDevPtr *devSections;
602    int *usedChips;
603    int i;
604
605    /*
606     * Find the config file Device sections that match this
607     * driver, and return if there are none.
608     */
609    if ((numDevSections = xf86MatchDevice(NEO_DRIVER_NAME,
610					  &devSections)) <= 0) {
611	return FALSE;
612    }
613
614    /* PCI BUS */
615    if (xf86GetPciVideoInfo() ) {
616	numUsed = xf86MatchPciInstances(NEO_NAME, PCI_VENDOR_NEOMAGIC,
617					NEOChipsets, NEOPCIchipsets,
618					devSections,numDevSections,
619					drv, &usedChips);
620
621	if (numUsed > 0) {
622	    if (flags & PROBE_DETECT)
623		foundScreen = TRUE;
624	    else for (i = 0; i < numUsed; i++) {
625		ScrnInfoPtr pScrn = NULL;
626		/* Allocate a ScrnInfoRec and claim the slot */
627		if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
628						       NEOPCIchipsets,NULL, NULL,
629						       NULL, NULL, NULL))) {
630		    pScrn->driverVersion = NEO_VERSION;
631		    pScrn->driverName    = NEO_DRIVER_NAME;
632		    pScrn->name          = NEO_NAME;
633		    pScrn->Probe         = NEOProbe;
634		    pScrn->PreInit       = NEOPreInit;
635		    pScrn->ScreenInit    = NEOScreenInit;
636		    pScrn->SwitchMode    = NEOSwitchMode;
637		    pScrn->AdjustFrame   = NEOAdjustFrame;
638		    pScrn->EnterVT       = NEOEnterVT;
639		    pScrn->LeaveVT       = NEOLeaveVT;
640		    pScrn->FreeScreen    = NEOFreeScreen;
641		    pScrn->ValidMode     = NEOValidMode;
642		    foundScreen = TRUE;
643		}
644	    }
645	    xfree(usedChips);
646	}
647    }
648
649    /* Isa Bus */
650
651    numUsed = xf86MatchIsaInstances(NEO_NAME,NEOChipsets,NEOISAchipsets,
652				     drv,neoFindIsaDevice,devSections,
653				     numDevSections,&usedChips);
654    if (numUsed > 0) {
655      if (flags & PROBE_DETECT)
656	foundScreen = TRUE;
657      else for (i = 0; i < numUsed; i++) {
658	ScrnInfoPtr pScrn = NULL;
659	if ((pScrn = xf86ConfigIsaEntity(pScrn, 0, usedChips[i],
660					 NEOISAchipsets, NULL, NULL,
661					 NULL, NULL, NULL))) {
662	    pScrn->driverVersion = NEO_VERSION;
663	    pScrn->driverName    = NEO_DRIVER_NAME;
664	    pScrn->name          = NEO_NAME;
665	    pScrn->Probe         = NEOProbe;
666	    pScrn->PreInit       = NEOPreInit;
667	    pScrn->ScreenInit    = NEOScreenInit;
668	    pScrn->SwitchMode    = NEOSwitchMode;
669	    pScrn->AdjustFrame   = NEOAdjustFrame;
670	    pScrn->EnterVT       = NEOEnterVT;
671	    pScrn->LeaveVT       = NEOLeaveVT;
672	    pScrn->FreeScreen    = NEOFreeScreen;
673	    pScrn->ValidMode     = NEOValidMode;
674	    foundScreen = TRUE;
675	}
676      }
677      xfree(usedChips);
678    }
679
680    xfree(devSections);
681    return foundScreen;
682}
683
684static int
685neoFindIsaDevice(GDevPtr dev)
686{
687    unsigned int vgaIOBase;
688    unsigned char id;
689
690    vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
691    /* §§§ Too intrusive ? */
692    outw(GRAX, 0x2609); /* Unlock NeoMagic registers */
693
694    outb(vgaIOBase + 4, 0x1A);
695    id = inb(vgaIOBase + 5);
696
697    outw(GRAX, 0x0009); /* Lock NeoMagic registers */
698
699    switch (id) {
700    case PROBED_NM2070 :
701	return NM2070;
702    case PROBED_NM2090 :
703	return NM2090;
704    case PROBED_NM2093 :
705	return NM2093;
706    default :
707	return -1;
708    }
709}
710
711
712/* Mandatory */
713Bool
714NEOPreInit(ScrnInfoPtr pScrn, int flags)
715{
716    ClockRangePtr clockRanges;
717    int i;
718    NEOPtr nPtr;
719    vgaHWPtr hwp;
720    int bppSupport = NoDepth24Support;
721    int videoRam = 896;
722    int maxClock = 65000;
723    int CursorMem = 1024;
724    int CursorOff = 0x100;
725    int linearSize = 1024;
726    int maxWidth = 1024;
727    int maxHeight = 1024;
728    unsigned char type, dpy;
729    int w;
730    int apertureSize;
731    Bool height_480 = FALSE;
732    Bool lcdCenterOptSet = FALSE;
733    char *s;
734
735    if (flags & PROBE_DETECT)  {
736	neoProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
737	return TRUE;
738    }
739
740    /* The vgahw module should be loaded here when needed */
741    if (!xf86LoadSubModule(pScrn, "vgahw"))
742	return FALSE;
743
744    xf86LoaderReqSymLists(vgahwSymbols, NULL);
745
746    /*
747     * Allocate a vgaHWRec.
748     */
749    if (!vgaHWGetHWRec(pScrn))
750	return FALSE;
751    hwp = VGAHWPTR(pScrn);
752
753    /* Allocate the NeoRec driverPrivate */
754    if (!NEOGetRec(pScrn)) {
755	return FALSE;
756    }
757# define RETURN \
758    { NEOFreeRec(pScrn);\
759			    return FALSE;\
760					     }
761
762    nPtr = NEOPTR(pScrn);
763
764    /* Since, the capabilities are determined by the chipset the very
765     * first thing to do is, figure out the chipset and its capabilities
766     */
767    /* This driver doesn't expect more than one entity per screen */
768    if (pScrn->numEntities > 1)
769	RETURN;
770
771    /* This is the general case */
772    for (i = 0; i<pScrn->numEntities; i++) {
773	nPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
774	if (nPtr->pEnt->resources) return FALSE;
775	nPtr->NeoChipset = nPtr->pEnt->chipset;
776	pScrn->chipset = (char *)xf86TokenToString(NEOChipsets,
777						   nPtr->pEnt->chipset);
778	/* This driver can handle ISA and PCI buses */
779	if (nPtr->pEnt->location.type == BUS_PCI) {
780	    nPtr->PciInfo = xf86GetPciInfoForEntity(nPtr->pEnt->index);
781	    nPtr->PciTag = pciTag(nPtr->PciInfo->bus,
782				  nPtr->PciInfo->device,
783				  nPtr->PciInfo->func);
784	}
785    }
786    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Chipset is a ");
787    switch(nPtr->NeoChipset){
788    case NM2070:
789	xf86ErrorF("MagicGraph 128 (NM2070)");
790	break;
791    case NM2090 :
792	xf86ErrorF("MagicGraph 128V (NM2090)");
793	break;
794    case NM2093 :
795	xf86ErrorF("MagicGraph 128ZV (NM2093)");
796	break;
797    case NM2097 :
798	xf86ErrorF("MagicGraph 128ZV+ (NM2097)");
799	break;
800    case NM2160 :
801	xf86ErrorF("MagicGraph 128XD (NM2160)");
802	break;
803    case NM2200 :
804        xf86ErrorF("MagicMedia 256AV (NM2200)");
805	break;
806    case NM2230 :
807        xf86ErrorF("MagicMedia 256AV+ (NM2230)");
808	break;
809    case NM2360 :
810        xf86ErrorF("MagicMedia 256ZX (NM2360)");
811	break;
812    case NM2380 :
813        xf86ErrorF("MagicMedia 256XL+ (NM2380)");
814	break;
815    }
816    xf86ErrorF("\n");
817
818    vgaHWGetIOBase(hwp);
819    nPtr->vgaIOBase = hwp->IOBase;
820    vgaHWSetStdFuncs(hwp);
821
822    /* Determine the panel type */
823    VGAwGR(0x09,0x26);
824    type = VGArGR(0x21);
825    dpy = VGArGR(0x20);
826
827    /* Determine panel width -- used in NeoValidMode. */
828    w = VGArGR(0x20);
829    VGAwGR(0x09,0x00);
830    switch ((w & 0x18) >> 3) {
831    case 0x00 :
832	nPtr->NeoPanelWidth  = 640;
833	nPtr->NeoPanelHeight = 480;
834	break;
835    case 0x01 :
836	nPtr->NeoPanelWidth  = 800;
837	nPtr->NeoPanelHeight = 600;
838	break;
839    case 0x02 :
840	nPtr->NeoPanelWidth  = 1024;
841	nPtr->NeoPanelHeight = 768;
842	break;
843    case 0x03 :
844        /* 1280x1024 panel support needs to be added */
845#ifdef NOT_DONE
846	nPtr->NeoPanelWidth  = 1280;
847	nPtr->NeoPanelHeight = 1024;
848	break;
849#else
850	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
851		     "Only 640x480,\n"
852                     "     800x600,\n"
853                     " and 1024x768 panels are currently supported\n");
854	return FALSE;
855#endif
856    default :
857	nPtr->NeoPanelWidth  = 640;
858	nPtr->NeoPanelHeight = 480;
859	break;
860    }
861
862    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel is a %dx%d %s %s display\n",
863	       nPtr->NeoPanelWidth,
864	       nPtr->NeoPanelHeight,
865	       (type & 0x02) ? "color" : "monochrome",
866	       (type & 0x10) ? "TFT" : "dual scan");
867
868
869    switch (nPtr->NeoChipset){
870    case NM2070:
871	bppSupport = NoDepth24Support;
872	videoRam   = 896;
873	maxClock   = 65000;
874	CursorMem  = 2048;
875	CursorOff  = 0x100;
876	linearSize = 1024;
877	maxWidth   = 1024;
878	maxHeight  = 1024;
879	break;
880    case NM2090:
881    case NM2093:
882	bppSupport = Support24bppFb | Support32bppFb |
883	    SupportConvert32to24 | PreferConvert32to24;
884	videoRam   = 1152;
885	maxClock   = 80000;
886	CursorMem  = 2048;
887	CursorOff  = 0x100;
888	linearSize = 2048;
889	maxWidth   = 1024;
890	maxHeight  = 1024;
891	break;
892    case NM2097:
893	bppSupport = Support24bppFb | Support32bppFb |
894	  SupportConvert32to24 | PreferConvert32to24;
895	videoRam   = 1152;
896	maxClock   = 80000;
897	CursorMem  = 1024;
898	CursorOff  = 0x100;
899	linearSize = 2048;
900	maxWidth   = 1024;
901	maxHeight  = 1024;
902	break;
903    case NM2160:
904	bppSupport = Support24bppFb | Support32bppFb |
905	    SupportConvert32to24 | PreferConvert32to24;
906	videoRam   = 2048;
907	maxClock   = 90000;
908	CursorMem  = 1024;
909	CursorOff  = 0x100;
910	linearSize = 2048;
911	maxWidth   = 1024;
912	maxHeight  = 1024;
913	break;
914    case NM2200:
915	bppSupport = Support24bppFb | Support32bppFb |
916	    SupportConvert32to24 | PreferConvert32to24;
917	videoRam   = 2560;
918	maxClock   = 110000;
919	CursorMem  = 1024;
920	CursorOff  = 0x1000;
921	linearSize = 4096;
922	maxWidth   = 1280;
923	maxHeight  = 1024;  /* ???? */
924	break;
925    case NM2230:
926	bppSupport = Support24bppFb | Support32bppFb |
927	    SupportConvert32to24 | PreferConvert32to24;
928	videoRam   = 3008;
929	maxClock   = 110000;
930	CursorMem  = 1024;
931	CursorOff  = 0x1000;
932	linearSize = 4096;
933	maxWidth   = 1280;
934	maxHeight  = 1024;  /* ???? */
935	break;
936    case NM2360:
937	bppSupport = Support24bppFb | Support32bppFb |
938	    SupportConvert32to24 | PreferConvert32to24;
939	videoRam   = 4096;
940	maxClock   = 110000;
941	CursorMem  = 1024;
942	CursorOff  = 0x1000;
943	linearSize = 4096;
944	maxWidth   = 1280;
945	maxHeight  = 1024;  /* ???? */
946	break;
947    case NM2380:
948	bppSupport = Support24bppFb | Support32bppFb |
949	    SupportConvert32to24 | PreferConvert32to24;
950	videoRam   = 6144;
951	maxClock   = 110000;
952	CursorMem  = 1024;
953	CursorOff  = 0x1000;
954	linearSize = 8192;
955	maxWidth   = 1280;
956	maxHeight  = 1024;  /* ???? */
957	break;
958    }
959
960    pScrn->monitor = pScrn->confScreen->monitor;
961
962    if (xf86LoadSubModule(pScrn, "ddc")) {
963        xf86LoaderReqSymLists(ddcSymbols, NULL);
964#if 1 /* for DDC1 testing */
965	if (!neoDoDDCVBE(pScrn))
966	  if (!neoDoDDC2(pScrn))
967#endif
968	      neoDoDDC1(pScrn);
969    }
970
971    if (!xf86SetDepthBpp(pScrn, 16, 0, 0, bppSupport ))
972	return FALSE;
973    else {
974	/* Check that the returned depth is one we support */
975	switch (pScrn->depth) {
976	case 8:
977	case 15:
978	case 16:
979	    break;
980	case 24:
981	    if (nPtr->NeoChipset != NM2070)
982		break;
983	default:
984	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
985		       "Given depth (%d) is not supported by this driver\n",
986		       pScrn->depth);
987	    return FALSE;
988	}
989    }
990    xf86PrintDepthBpp(pScrn);
991    if (pScrn->depth == 8)
992	pScrn->rgbBits = 6;
993
994    /* Get the depth24 pixmap format */
995    if (pScrn->depth == 24 && pix24bpp == 0)
996	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
997
998    /*
999     * This must happen after pScrn->display has been set because
1000     * xf86SetWeight references it.
1001     */
1002    if (pScrn->depth > 8) {
1003	/* The defaults are OK for us */
1004	rgb zeros = {0, 0, 0};
1005
1006	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1007	    return FALSE;
1008	} else {
1009	    /* XXX check that weight returned is supported */
1010	    ;
1011	}
1012    }
1013
1014    if (!xf86SetDefaultVisual(pScrn, -1))
1015	return FALSE;
1016
1017    if (pScrn->depth > 1) {
1018	Gamma zeros = {0.0, 0.0, 0.0};
1019
1020	if (!xf86SetGamma(pScrn, zeros))
1021	    return FALSE;
1022    }
1023
1024    nPtr->strangeLockups = TRUE;
1025
1026    /* Collect all of the relevant option flags (fill in pScrn->options) */
1027    xf86CollectOptions(pScrn, NULL);
1028    /* Process the options */
1029    if (nPtr->NeoChipset == NM2070) {
1030	if (!(nPtr->Options = xalloc(sizeof(NEO_2070_Options))))
1031	    return FALSE;
1032	memcpy(nPtr->Options, NEO_2070_Options, sizeof(NEO_2070_Options));
1033    } else {
1034	if (!(nPtr->Options = xalloc(sizeof(NEOOptions))))
1035	    return FALSE;
1036	memcpy(nPtr->Options, NEOOptions, sizeof(NEOOptions));
1037    }
1038
1039    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, nPtr->Options);
1040
1041    xf86GetOptValBool(nPtr->Options, OPTION_NOLINEAR_MODE,&nPtr->noLinear);
1042    xf86GetOptValBool(nPtr->Options, OPTION_SW_CURSOR,&nPtr->swCursor);
1043    xf86GetOptValBool(nPtr->Options, OPTION_NO_MMIO,&nPtr->noMMIO);
1044    xf86GetOptValBool(nPtr->Options, OPTION_INTERN_DISP,&nPtr->internDisp);
1045    xf86GetOptValBool(nPtr->Options, OPTION_EXTERN_DISP,&nPtr->externDisp);
1046    if (xf86GetOptValBool(nPtr->Options, OPTION_LCD_CENTER,&nPtr->lcdCenter))
1047	lcdCenterOptSet = TRUE;
1048    xf86GetOptValBool(nPtr->Options, OPTION_LCD_STRETCH,&nPtr->noLcdStretch);
1049    xf86GetOptValBool(nPtr->Options, OPTION_SHADOW_FB,&nPtr->shadowFB);
1050    xf86GetOptValBool(nPtr->Options, OPTION_SHOWCACHE,&nPtr->showcache);
1051    nPtr->onPciBurst = TRUE;
1052    xf86GetOptValBool(nPtr->Options, OPTION_PCI_BURST,&nPtr->onPciBurst);
1053    xf86GetOptValBool(nPtr->Options,
1054		      OPTION_PROG_LCD_MODE_REGS,&nPtr->progLcdRegs);
1055    if (xf86GetOptValBool(nPtr->Options,
1056		      OPTION_PROG_LCD_MODE_STRETCH,&nPtr->progLcdStretch))
1057	nPtr->progLcdStretchOpt = TRUE;
1058    xf86GetOptValBool(nPtr->Options,
1059		      OPTION_OVERRIDE_VALIDATE_MODE, &nPtr->overrideValidate);
1060    xf86GetOptValBool(nPtr->Options, OPTION_DISPLAY_HEIGHT_480,&height_480);
1061    xf86GetOptValBool(nPtr->Options, OPTION_STRANGE_LOCKUPS,
1062		      &nPtr->strangeLockups);
1063    nPtr->noAccelSet =
1064	xf86GetOptValBool(nPtr->Options, OPTION_NOACCEL,&nPtr->noAccel);
1065
1066    nPtr->rotate = 0;
1067    if ((s = xf86GetOptValString(nPtr->Options, OPTION_ROTATE))) {
1068	if(!xf86NameCmp(s, "CW")) {
1069	    /* accel is disabled below for shadowFB */
1070	    nPtr->shadowFB = TRUE;
1071	    nPtr->swCursor = TRUE;
1072	    nPtr->rotate = 1;
1073	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1074		       "Rotating screen clockwise - acceleration disabled\n");
1075	} else if(!xf86NameCmp(s, "CCW")) {
1076	    nPtr->shadowFB = TRUE;
1077	    nPtr->swCursor = TRUE;
1078	    nPtr->rotate = -1;
1079	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
1080		       "counter clockwise - acceleration disabled\n");
1081	} else {
1082	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
1083		       "value for Option \"Rotate\"\n", s);
1084	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1085		       "Valid options are \"CW\" or \"CCW\"\n");
1086      }
1087    }
1088
1089    if(xf86GetOptValInteger(nPtr->Options,
1090			    OPTION_VIDEO_KEY, &(nPtr->videoKey))) {
1091        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1092		   nPtr->videoKey);
1093    } else {
1094        nPtr->videoKey = (1 << pScrn->offset.red) |
1095	    (1 << pScrn->offset.green) |
1096	    (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
1097	     << pScrn->offset.blue);
1098    }
1099    if(xf86GetOptValInteger(nPtr->Options, OPTION_OVERLAYMEM,
1100			    &(nPtr->overlay))) {
1101        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1102		   "reserve %d bytes for overlay.\n", nPtr->overlay);
1103    } else {
1104	nPtr->overlay = 0;
1105    }
1106    nPtr->interlace = 0;
1107    if(xf86GetOptValInteger(nPtr->Options, OPTION_VIDEO_INTERLACE,
1108			    &(nPtr->interlace))) {
1109	if (nPtr->interlace >= 0  &&  nPtr->interlace <= 2){
1110	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "interlace flag = %d\n",
1111		       nPtr->interlace);
1112	} else {
1113	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1114		       "\"%s\" is not a valid value for "
1115		       "Option \"Interlaced\"\n", s);
1116	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are  0..2\n");
1117        }
1118    }
1119
1120    if (height_480
1121	&& (nPtr->NeoPanelWidth == 800 || nPtr->NeoPanelWidth == 1024)) {
1122	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1123		   "Overriding Panel height: Set to 480\n");
1124	nPtr->NeoPanelHeight = 480;
1125	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1126		   "Disabling LCD stretching for panel height 480\n");
1127	nPtr->noLcdStretch = TRUE;
1128	if (!lcdCenterOptSet)
1129	    nPtr->lcdCenter = TRUE;
1130    }
1131
1132    if (nPtr->internDisp && nPtr->externDisp)
1133	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1134		   "Simultaneous LCD/CRT display mode\n");
1135    else if (nPtr->externDisp)
1136	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1137		   "External CRT only display mode\n");
1138    else  if (nPtr->internDisp)
1139	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1140		   "Internal LCD only display mode\n");
1141    else {
1142	nPtr->internDisp = ((dpy & 0x02) == 0x02);
1143    	nPtr->externDisp = ((dpy & 0x01) == 0x01);
1144	if (nPtr->internDisp && nPtr->externDisp)
1145	    xf86DrvMsg(pScrn->scrnIndex,X_PROBED,
1146		       "Simultaneous LCD/CRT display mode\n");
1147	else if (nPtr->externDisp)
1148	    xf86DrvMsg(pScrn->scrnIndex,X_PROBED,
1149		       "External CRT only display mode\n");
1150	else if (nPtr->internDisp)
1151	    xf86DrvMsg(pScrn->scrnIndex,X_PROBED,
1152		       "Internal LCD only display mode\n");
1153	else {
1154	    /* this is a fallback if probed values are bogus */
1155	    nPtr->internDisp = TRUE;
1156	    xf86DrvMsg(pScrn->scrnIndex,X_DEFAULT,
1157		       "Internal LCD only display mode\n");
1158	}
1159    }
1160
1161    if (nPtr->noLcdStretch)
1162	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1163		   "Low resolution video modes are not stretched\n");
1164    if (nPtr->lcdCenter)
1165	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1166		   "Video modes are centered on the display\n");
1167    if (nPtr->noLinear)
1168	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using nonlinear mode\n");
1169    else
1170	xf86DrvMsg(pScrn->scrnIndex,X_DEFAULT, "using linear mode\n");
1171    if (nPtr->swCursor)
1172	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using sofware cursor\n");
1173    if (nPtr->noMMIO)
1174	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "MMIO mode disabled\n");
1175    if (nPtr->onPciBurst)
1176	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using PCI Burst mode\n");
1177    if (nPtr->strangeLockups)
1178	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1179		   "Option StrangeLockups set: disabling some acceleration\n");
1180    if (nPtr->showcache)
1181	xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
1182		   "Show chache for debugging\n");
1183    if (nPtr->shadowFB) {
1184	if (nPtr->noLinear) {
1185    	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1186		       "Option \"ShadowFB\" ignored. Not supported without"
1187		       " linear addressing\n");
1188	    nPtr->shadowFB = FALSE;
1189	    nPtr->rotate = 0;
1190	} else {
1191	    nPtr->noAccel = TRUE;
1192	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1193		    "Using \"Shadow Framebuffer\" - acceleration disabled\n");
1194	}
1195    }
1196
1197    nPtr->NeoFbMapSize = linearSize * 1024;
1198    nPtr->NeoCursorOffset = CursorOff;
1199
1200    if (nPtr->pEnt->device->MemBase) {
1201	/* XXX Check this matches a PCI base address */
1202	nPtr->NeoLinearAddr = nPtr->pEnt->device->MemBase;
1203	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1204		   "FB base address is set at 0x%lX.\n",
1205		   nPtr->NeoLinearAddr);
1206    } else {
1207	nPtr->NeoLinearAddr = 0;
1208    }
1209
1210    nPtr->NeoMMIOAddr2 = 0;
1211    nPtr->NeoMMIOBase2 = NULL;
1212    if (nPtr->pEnt->device->IOBase && !nPtr->noMMIO) {
1213	/* XXX Check this matches a PCI base address */
1214	nPtr->NeoMMIOAddr = nPtr->pEnt->device->IOBase;
1215	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1216		   "MMIO base address is set at 0x%lX.\n",
1217		   nPtr->NeoMMIOAddr);
1218    } else {
1219	nPtr->NeoMMIOAddr = 0;
1220    }
1221
1222    if (nPtr->pEnt->location.type == BUS_PCI) {
1223	if (!nPtr->NeoLinearAddr) {
1224	    nPtr->NeoLinearAddr = nPtr->PciInfo->memBase[0];
1225	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1226		       "FB base address is set at 0x%lX.\n",
1227		       nPtr->NeoLinearAddr);
1228	}
1229	if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
1230	    switch (nPtr->NeoChipset) {
1231	    case NM2070 :
1232		nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
1233		break;
1234	    case NM2090:
1235	    case NM2093:
1236		nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x200000;
1237		break;
1238	    case NM2160:
1239	    case NM2097:
1240	    case NM2200:
1241	    case NM2230:
1242	    case NM2360:
1243	    case NM2380:
1244		nPtr->NeoMMIOAddr = nPtr->PciInfo->memBase[1];
1245		nPtr->NeoMMIOAddr2 = nPtr->PciInfo->memBase[2];
1246		break;
1247	    }
1248	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1249		       "MMIO base address is set at 0x%lX.\n",
1250		       nPtr->NeoMMIOAddr);
1251	    if (nPtr->NeoMMIOAddr2 != 0){
1252	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1253		           "MMIO base address2 is set at 0x%lX.\n",
1254		           nPtr->NeoMMIOAddr2);
1255	    }
1256	}
1257	/* XXX What about VGA resources in OPERATING mode? */
1258	if (xf86RegisterResources(nPtr->pEnt->index, NULL, ResExclusive))
1259	    RETURN;
1260
1261    } else if (nPtr->pEnt->location.type == BUS_ISA) {
1262	unsigned int addr;
1263	resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END };
1264
1265	if (!nPtr->NeoLinearAddr) {
1266	    VGAwGR(0x09,0x26);
1267	    addr = VGArGR(0x13);
1268	    VGAwGR(0x09,0x00);
1269	    nPtr->NeoLinearAddr = addr << 20;
1270	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1271		       "FB base address is set at 0x%lX.\n",
1272		       nPtr->NeoLinearAddr);
1273	}
1274	if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
1275	    nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
1276	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1277		       "MMIO base address is set at 0x%lX.\n",
1278		       nPtr->NeoMMIOAddr);
1279	}
1280	linearRes[0].rBegin = nPtr->NeoLinearAddr;
1281	linearRes[1].rEnd = nPtr->NeoLinearAddr + nPtr->NeoFbMapSize - 1;
1282	if (xf86RegisterResources(nPtr->pEnt->index,linearRes,ResNone)) {
1283	    nPtr->noLinear = TRUE; /* XXX */
1284	}
1285    } else
1286	RETURN;
1287
1288    if (nPtr->pEnt->device->videoRam != 0) {
1289	pScrn->videoRam = nPtr->pEnt->device->videoRam;
1290	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n",
1291		   pScrn->videoRam);
1292    } else {
1293	pScrn->videoRam = videoRam;
1294	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n",
1295		   pScrn->videoRam);
1296    }
1297
1298    if (nPtr->pEnt->device->dacSpeeds[0] != 0) {
1299	maxClock = nPtr->pEnt->device->dacSpeeds[0];
1300	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Max Clock: %d kHz\n",
1301		   maxClock);
1302    } else {
1303	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max Clock: %d kHz\n",
1304		   maxClock);
1305    }
1306
1307    pScrn->progClock = TRUE;
1308    /*
1309     * Setup the ClockRanges, which describe what clock ranges are available,
1310     * and what sort of modes they can be used for.
1311     */
1312    clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1);
1313    clockRanges->next = NULL;
1314    clockRanges->ClockMulFactor = 1;
1315    clockRanges->minClock = 11000;   /* guessed §§§ */
1316    clockRanges->maxClock = maxClock;
1317    clockRanges->clockIndex = -1;		/* programmable */
1318	clockRanges->interlaceAllowed = FALSE;
1319    clockRanges->doubleScanAllowed = TRUE;
1320
1321    /* Subtract memory for HW cursor */
1322    if (!nPtr->swCursor)
1323	nPtr->NeoCursorMem = CursorMem;
1324    else
1325	nPtr->NeoCursorMem = 0;
1326    apertureSize = (pScrn->videoRam * 1024) - nPtr->NeoCursorMem;
1327
1328    if ((nPtr->NeoPanelWidth == 800) && (nPtr->NeoPanelHeight == 480)) {
1329	neo800x480Mode.next = pScrn->monitor->Modes;
1330	pScrn->monitor->Modes = &neo800x480Mode;
1331    }
1332    if ((nPtr->NeoPanelWidth == 1024) && (nPtr->NeoPanelHeight == 480)) {
1333	neo1024x480Mode.next = pScrn->monitor->Modes;
1334	pScrn->monitor->Modes = &neo1024x480Mode;
1335    }
1336
1337    if (!pScrn->monitor->DDC) {
1338	/*
1339	 * If the monitor parameters are not specified explicitly, set them
1340	 * so that 60Hz modes up to the panel size are allowed.
1341	 */
1342	if (pScrn->monitor->nHsync == 0) {
1343	    pScrn->monitor->nHsync = 1;
1344	    pScrn->monitor->hsync[0].lo = 28;
1345	    pScrn->monitor->hsync[0].hi =
1346				60.0 * 1.07 * nPtr->NeoPanelHeight / 1000.0;
1347	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1348		       "Using hsync range matching panel size: %.2f-%.2f kHz\n",
1349		       pScrn->monitor->hsync[0].lo,
1350		       pScrn->monitor->hsync[0].hi);
1351	}
1352	if (pScrn->monitor->nVrefresh == 0) {
1353	    pScrn->monitor->nVrefresh = 1;
1354	    pScrn->monitor->vrefresh[0].lo = 55.0;
1355	    pScrn->monitor->vrefresh[0].hi = 65.0;
1356	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1357		       "Using vsync range for panel: %.2f-%.2f kHz\n",
1358		       pScrn->monitor->vrefresh[0].lo,
1359		       pScrn->monitor->vrefresh[0].hi);
1360	}
1361    }
1362
1363    /*
1364     * For external displays, limit the width to 1024 pixels or less.
1365     */
1366    {
1367       i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
1368			  pScrn->display->modes, clockRanges,
1369			  NULL, 256, maxWidth,(8 * pScrn->bitsPerPixel),/*§§§*/
1370			  128, maxHeight, pScrn->display->virtualX,
1371			  pScrn->display->virtualY, apertureSize,
1372			  LOOKUP_BEST_REFRESH);
1373
1374       if (i == -1)
1375           RETURN;
1376    }
1377
1378    /* Prune the modes marked as invalid */
1379    xf86PruneDriverModes(pScrn);
1380
1381    if (i == 0 || pScrn->modes == NULL) {
1382	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
1383	RETURN;
1384    }
1385
1386    /*
1387     * Set the CRTC parameters for all of the modes based on the type
1388     * of mode, and the chipset's interlace requirements.
1389     *
1390     * Calling this is required if the mode->Crtc* values are used by the
1391     * driver and if the driver doesn't provide code to set them.  They
1392     * are not pre-initialised at all.
1393     */
1394    xf86SetCrtcForModes(pScrn, 0);
1395
1396    /* Set the current mode to the first in the list */
1397    pScrn->currentMode = pScrn->modes;
1398
1399    /* Print the list of modes being used */
1400    xf86PrintModes(pScrn);
1401
1402    /* If monitor resolution is set on the command line, use it */
1403    xf86SetDpi(pScrn, 0, 0);
1404
1405    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
1406	RETURN;
1407    }
1408
1409    xf86LoaderReqSymLists(fbSymbols, NULL);
1410
1411    if (!nPtr->noLinear) {
1412	if (!xf86LoadSubModule(pScrn, "xaa"))
1413	    RETURN;
1414	xf86LoaderReqSymLists(xaaSymbols, NULL);
1415    }
1416
1417    if (nPtr->shadowFB) {
1418	if (!xf86LoadSubModule(pScrn, "shadow")) {
1419	    RETURN;
1420	}
1421	xf86LoaderReqSymLists(shadowSymbols, NULL);
1422    }
1423
1424    if (!nPtr->swCursor) {
1425	if (!xf86LoadSubModule(pScrn, "ramdac"))
1426	    RETURN;
1427	xf86LoaderReqSymLists(ramdacSymbols, NULL);
1428    }
1429    return TRUE;
1430}
1431#undef RETURN
1432
1433/* Mandatory */
1434static Bool
1435NEOEnterVT(int scrnIndex, int flags)
1436{
1437    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1438    NEOPtr nPtr = NEOPTR(pScrn);
1439
1440    /* Should we re-save the text mode on each VT enter? */
1441    if(!neoModeInit(pScrn, pScrn->currentMode))
1442      return FALSE;
1443
1444    if (nPtr->video)
1445	NEOResetVideo(pScrn);
1446
1447    if (nPtr->NeoHWCursorShown)
1448	NeoShowCursor(pScrn);
1449    NEOAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1450
1451    return TRUE;
1452}
1453
1454/* Mandatory */
1455static void
1456NEOLeaveVT(int scrnIndex, int flags)
1457{
1458    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1459    NEOPtr nPtr = NEOPTR(pScrn);
1460
1461    /* Invalidate the cached acceleration registers */
1462    if (nPtr->NeoHWCursorShown)
1463	NeoHideCursor(pScrn);
1464    neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE);
1465    neoLock(pScrn);
1466
1467}
1468
1469static void
1470NEOLoadPalette(
1471   ScrnInfoPtr pScrn,
1472   int numColors,
1473   int *indices,
1474   LOCO *colors,
1475   VisualPtr pVisual
1476){
1477   int i, index, shift, Gshift;
1478   vgaHWPtr hwp = VGAHWPTR(pScrn);
1479
1480   switch(pScrn->depth) {
1481   case 15:
1482	shift = Gshift = 1;
1483	break;
1484   case 16:
1485	shift = 0;
1486        Gshift = 0;
1487	break;
1488   default:
1489	shift = Gshift = 0;
1490	break;
1491   }
1492
1493   for(i = 0; i < numColors; i++) {
1494        index = indices[i];
1495        hwp->writeDacWriteAddr(hwp, index);
1496	DACDelay(hwp);
1497        hwp->writeDacData(hwp, colors[index].red << shift);
1498	DACDelay(hwp);
1499        hwp->writeDacData(hwp, colors[index].green << Gshift);
1500	DACDelay(hwp);
1501        hwp->writeDacData(hwp, colors[index].blue << shift);
1502	DACDelay(hwp);
1503   }
1504}
1505
1506/* Mandatory */
1507static Bool
1508NEOScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1509{
1510    ScrnInfoPtr pScrn;
1511    vgaHWPtr hwp;
1512    NEOPtr nPtr;
1513    NEOACLPtr nAcl;
1514    int ret;
1515    VisualPtr visual;
1516    int allocatebase, freespace, currentaddr;
1517    unsigned int racflag = RAC_FB;
1518    unsigned char *FBStart;
1519    int height, width, displayWidth;
1520
1521    /*
1522     * we need to get the ScrnInfoRec for this screen, so let's allocate
1523     * one first thing
1524     */
1525    pScrn = xf86Screens[pScreen->myNum];
1526    nPtr = NEOPTR(pScrn);
1527    nAcl = NEOACLPTR(pScrn);
1528
1529    hwp = VGAHWPTR(pScrn);
1530    hwp->MapSize = 0x10000;		/* Standard 64k VGA window */
1531    /* Map the VGA memory */
1532    if (!vgaHWMapMem(pScrn))
1533	return FALSE;
1534
1535    /* Map the Neo memory and possible MMIO areas */
1536    if (!neoMapMem(pScrn))
1537	return FALSE;
1538
1539    /*
1540     * next we save the current state and setup the first mode
1541     */
1542    neoSave(pScrn);
1543
1544    if (!neoModeInit(pScrn,pScrn->currentMode))
1545	return FALSE;
1546    vgaHWSaveScreen(pScreen,SCREEN_SAVER_ON);
1547    NEOAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1548
1549    /*
1550     * Reset visual list.
1551     */
1552    miClearVisualTypes();
1553
1554    /* Setup the visuals we support. */
1555#if 0
1556    if (!miSetVisualTypes(pScrn->depth,
1557      		      miGetDefaultVisualMask(pScrn->depth),
1558		      pScrn->rgbBits, pScrn->defaultVisual))
1559         return FALSE;
1560#else
1561    if (!miSetVisualTypes(pScrn->depth,
1562      		      miGetDefaultVisualMask(pScrn->depth),
1563		      pScrn->rgbBits, pScrn->defaultVisual))
1564         return FALSE;
1565    if (pScrn->depth > 8) {
1566	if (!miSetVisualTypes(8, miGetDefaultVisualMask(8), 6,
1567			      pScrn->defaultVisual))
1568	    return FALSE;
1569    }
1570#endif
1571    if (!miSetPixmapDepths ()) return FALSE;
1572
1573    /*
1574     * Call the framebuffer layer's ScreenInit function, and fill in other
1575     * pScreen fields.
1576     */
1577    displayWidth = pScrn->displayWidth;
1578    if (nPtr->rotate) {
1579	height = pScrn->virtualX;
1580	width = pScrn->virtualY;
1581    } else {
1582	width = pScrn->virtualX;
1583	height = pScrn->virtualY;
1584    }
1585
1586    if(nPtr->shadowFB) {
1587	nPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
1588	nPtr->ShadowPtr = xalloc(nPtr->ShadowPitch * height);
1589	displayWidth = nPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3);
1590	FBStart = nPtr->ShadowPtr;
1591    } else {
1592	nPtr->ShadowPtr = NULL;
1593	FBStart = nPtr->NeoFbBase;
1594    }
1595
1596    ret = fbScreenInit(pScreen, FBStart,
1597			    width, height,
1598			    pScrn->xDpi, pScrn->yDpi,
1599			    displayWidth, pScrn->bitsPerPixel);
1600    if (!ret)
1601	return FALSE;
1602    if (pScrn->depth > 8) {
1603        /* Fixup RGB ordering */
1604        visual = pScreen->visuals + pScreen->numVisuals;
1605        while (--visual >= pScreen->visuals) {
1606	    if ((visual->class | DynamicClass) == DirectColor
1607		&& visual->nplanes > 8) {
1608		visual->offsetRed = pScrn->offset.red;
1609		visual->offsetGreen = pScrn->offset.green;
1610		visual->offsetBlue = pScrn->offset.blue;
1611		visual->redMask = pScrn->mask.red;
1612		visual->greenMask = pScrn->mask.green;
1613		visual->blueMask = pScrn->mask.blue;
1614	    }
1615	}
1616    }
1617
1618    /* must be after RGB ordering fixed */
1619    fbPictureInit(pScreen, 0, 0);
1620
1621    xf86SetBlackWhitePixels(pScreen);
1622
1623    if (!nPtr->shadowFB)
1624	NEODGAInit(pScreen);
1625
1626    nPtr->NeoHWCursorShown = FALSE;
1627    nPtr->NeoHWCursorInitialized = FALSE;
1628    nAcl->UseHWCursor = FALSE;
1629    nAcl->CursorAddress = -1;
1630
1631    if (nPtr->noLinear) {
1632	miBankInfoPtr pBankInfo;
1633
1634	/* Setup the vga banking variables */
1635	pBankInfo = (miBankInfoPtr)xnfcalloc(sizeof(miBankInfoRec),1);
1636	if (pBankInfo == NULL)
1637	    return FALSE;
1638
1639	pBankInfo->pBankA = hwp->Base;
1640	pBankInfo->pBankB = (unsigned char *)hwp->Base;
1641	pBankInfo->BankSize = 0x10000;
1642	pBankInfo->nBankDepth = pScrn->depth;
1643
1644	pBankInfo->SetSourceBank = (miBankProcPtr)NEOSetRead;
1645	pBankInfo->SetDestinationBank =
1646	    (miBankProcPtr)NEOSetWrite;
1647	pBankInfo->SetSourceAndDestinationBanks =
1648	    (miBankProcPtr)NEOSetReadWrite;
1649	if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
1650				 pScrn->displayWidth, pBankInfo)) {
1651	    xfree(pBankInfo);
1652	    pBankInfo = NULL;
1653	    return FALSE;
1654	}
1655	xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Using nonlinear mode\n");
1656	xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Using software cursor in "
1657		   "nonlinear mode\n");
1658    } else {
1659	nAcl->cacheStart = -1;
1660	nAcl->cacheEnd = -1;
1661	xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1662		   "Using linear framebuffer at: 0x%08lX\n",
1663		   nPtr->NeoLinearAddr);
1664	/* Setup pointers to free space in video ram */
1665	allocatebase = (pScrn->videoRam << 10);
1666	freespace = allocatebase - pScrn->displayWidth *
1667	    pScrn->virtualY * (pScrn->bitsPerPixel >> 3);
1668	currentaddr = allocatebase;
1669	xf86DrvMsg(scrnIndex, X_PROBED,
1670		   "%d bytes off-screen memory available\n", freespace);
1671
1672	if (nPtr->swCursor || !nPtr->NeoMMIOBase) {
1673	    xf86DrvMsg(scrnIndex, X_CONFIG,
1674		       "Using Software Cursor.\n");
1675	} else if (nPtr->NeoCursorMem <= freespace) {
1676	    currentaddr -= nPtr->NeoCursorMem;
1677	    freespace  -= nPtr->NeoCursorMem;
1678	    /* alignment */
1679	    freespace  -= currentaddr & 0x3FF;
1680	    currentaddr &= 0xfffffc00;
1681	    nAcl->CursorAddress = currentaddr;
1682	    xf86DrvMsg(scrnIndex, X_INFO,
1683		       "Using H/W Cursor.\n");
1684	} else {
1685	    xf86DrvMsg(scrnIndex, X_ERROR,
1686		       "Too little space for H/W cursor.\n");
1687	}
1688
1689	if (!nPtr->noAccel && !nPtr->NeoMMIOBase)
1690	  xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1691		     "Acceleration disabled when not using MMIO\n");
1692
1693	if (nPtr->overlay > 0){
1694	    if (nPtr->overlay > freespace){
1695		xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1696			   "Can not reserve %d bytes for overlay. "
1697			   "Resize to %d bytes.\n",
1698			   nPtr->overlay, freespace);
1699		nPtr->overlay = freespace;
1700	    }
1701	    currentaddr -= nPtr->overlay;
1702	    freespace -= nPtr->overlay;
1703	    nPtr->overlay_offset = currentaddr;
1704	    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Overlay at 0x%x\n",
1705		       nPtr->overlay_offset);
1706	}
1707
1708	nAcl->cacheStart = currentaddr - freespace;
1709	nAcl->cacheEnd = currentaddr;
1710	freespace = 0;
1711	if (nAcl->cacheStart < nAcl->cacheEnd) {
1712	    BoxRec AvailFBArea;
1713	    int lines = nAcl->cacheEnd /
1714		(pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
1715	    if (!nPtr->noAccel && nPtr->NeoMMIOBase && lines > 1024)
1716		lines = 1024;
1717	    AvailFBArea.x1 = 0;
1718	    AvailFBArea.y1 = 0;
1719	    AvailFBArea.x2 = pScrn->displayWidth;
1720	    AvailFBArea.y2 = lines;
1721	    xf86InitFBManager(pScreen, &AvailFBArea);
1722
1723	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1724		       "Using %i scanlines of offscreen memory \n",
1725		       lines - pScrn->virtualY);
1726	}
1727
1728	/* Setup the acceleration primitives */
1729	if (!nPtr->noAccel && nPtr->NeoMMIOBase) {
1730	    Bool ret = FALSE;
1731	    if (nAcl->cacheStart >= nAcl->cacheEnd) {
1732		xf86DrvMsg(scrnIndex, X_ERROR,
1733			   "Too little space for pixmap cache.\n");
1734	    }
1735	    switch(nPtr->NeoChipset) {
1736	    case NM2070 :
1737		ret = Neo2070AccelInit(pScreen);
1738		break;
1739	    case NM2090 :
1740	    case NM2093 :
1741		ret = Neo2090AccelInit(pScreen);
1742		break;
1743	    case NM2097 :
1744	    case NM2160 :
1745		ret = Neo2097AccelInit(pScreen);
1746		break;
1747	    case NM2200 :
1748	    case NM2230 :
1749	    case NM2360 :
1750	    case NM2380 :
1751	        ret = Neo2200AccelInit(pScreen);
1752		break;
1753	    }
1754	    xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1755		       "Acceleration %s Initialized\n",ret ? "" : "not");
1756	}
1757
1758    }
1759    miInitializeBackingStore(pScreen);
1760    xf86SetBackingStore(pScreen);
1761    xf86SetSilkenMouse(pScreen);
1762
1763    /* Initialise cursor functions */
1764    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
1765
1766    if (nAcl->CursorAddress != -1) {
1767      /* HW cursor functions */
1768      if (!NeoCursorInit(pScreen)) {
1769	xf86DrvMsg(scrnIndex, X_ERROR,
1770		   "Hardware cursor initialization failed\n");
1771	return FALSE;
1772      }
1773      nAcl->UseHWCursor = TRUE;
1774      nPtr->NeoHWCursorInitialized = TRUE;
1775    } else
1776      nAcl->UseHWCursor = FALSE;
1777
1778    if (nPtr->shadowFB) {
1779        nPtr->refreshArea = neoRefreshArea;
1780
1781	if(nPtr->rotate) {
1782	    if (!nPtr->PointerMoved) {
1783		nPtr->PointerMoved = pScrn->PointerMoved;
1784		pScrn->PointerMoved = neoPointerMoved;
1785	    }
1786	    switch(pScrn->bitsPerPixel) {
1787	    case 8:	nPtr->refreshArea = neoRefreshArea8;	break;
1788	    case 16:	nPtr->refreshArea = neoRefreshArea16;	break;
1789	    case 24:	nPtr->refreshArea = neoRefreshArea24;	break;
1790	    case 32:	nPtr->refreshArea = neoRefreshArea32;	break;
1791	    }
1792	}
1793#if 0
1794	ShadowFBInit(pScreen, nPtr->refreshArea);
1795#else
1796	shadowInit (pScreen, neoShadowUpdate, 0);
1797#endif
1798    }
1799
1800    /* Initialise default colourmap */
1801    if(!miCreateDefColormap(pScreen))
1802	return FALSE;
1803
1804    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,
1805                         NEOLoadPalette, NULL,
1806                         CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH))
1807	return FALSE;
1808
1809	if (pScrn->depth == 16)
1810	    xxSetup(pScreen,8, pScrn->depth, NULL, nPtr->accelSync); /*@!@*/
1811
1812    racflag |= RAC_COLORMAP;
1813    if (nPtr->NeoHWCursorInitialized)
1814        racflag |= RAC_CURSOR;
1815
1816    pScrn->racIoFlags = pScrn->racMemFlags = racflag;
1817
1818    NEOInitVideo(pScreen);
1819
1820    pScreen->SaveScreen = vgaHWSaveScreenWeak();
1821
1822    /* Setup DPMS mode */
1823    if (nPtr->NeoChipset != NM2070)
1824	xf86DPMSInit(pScreen, (DPMSSetProcPtr)NeoDisplayPowerManagementSet,
1825		     0);
1826
1827    if (!nPtr->noLinear) {
1828	pScrn->memPhysBase = (unsigned long)nPtr->NeoLinearAddr;
1829	pScrn->fbOffset = 0;
1830    }
1831
1832    /* Wrap the current CloseScreen function */
1833    nPtr->CloseScreen = pScreen->CloseScreen;
1834    pScreen->CloseScreen = NEOCloseScreen;
1835
1836    /* Report any unused options (only for the first generation) */
1837    if (serverGeneration == 1) {
1838	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1839    }
1840
1841    return TRUE;
1842}
1843
1844/* Mandatory */
1845Bool
1846NEOSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1847{
1848    return neoModeInit(xf86Screens[scrnIndex], mode);
1849}
1850
1851/* Mandatory */
1852void
1853NEOAdjustFrame(int scrnIndex, int x, int y, int flags)
1854{
1855    ScrnInfoPtr pScrn;
1856    NEOPtr nPtr;
1857    vgaHWPtr hwp;
1858    int oldExtCRTDispAddr;
1859    int Base;
1860
1861    pScrn = xf86Screens[scrnIndex];
1862    hwp = VGAHWPTR(pScrn);
1863    nPtr = NEOPTR(pScrn);
1864
1865    if (nPtr->showcache && y) {
1866	int lastline = nPtr->NeoFbMapSize /
1867	    ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
1868
1869	lastline -= pScrn->currentMode->VDisplay;
1870	y += pScrn->virtualY - 1;
1871        if (y > lastline) y = lastline;
1872    }
1873
1874    Base = (y * pScrn->displayWidth + x) >> 2;
1875
1876    /* Scale Base by the number of bytes per pixel. */
1877    switch (pScrn->depth) {
1878    case  8 :
1879	break;
1880    case 15 :
1881    case 16 :
1882	Base *= 2;
1883	break;
1884    case 24 :
1885	Base *= 3;
1886	break;
1887    default :
1888	break;
1889    }
1890    /*
1891     * These are the generic starting address registers.
1892     */
1893    VGAwCR(0x0C, (Base & 0x00FF00) >> 8);
1894    VGAwCR(0x0D, (Base & 0x00FF));
1895
1896    /*
1897     * Make sure we don't clobber some other bits that might already
1898     * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
1899     * be needed.
1900     */
1901    oldExtCRTDispAddr = VGArGR(0x0E);
1902    VGAwGR(0x0E,(((Base >> 16) & 0x07) | (oldExtCRTDispAddr & 0xf8)));
1903#if 0
1904    /*
1905     * This is a workaround for a higher level bug that causes the cursor
1906     * to be at the wrong position after a virtual screen resolution change
1907     */
1908    if (nPtr->NeoHWCursorInitialized) { /*§§§ do we still need this?*/
1909	NeoRepositionCursor();
1910    }
1911#endif
1912}
1913
1914/* Mandatory */
1915static Bool
1916NEOCloseScreen(int scrnIndex, ScreenPtr pScreen)
1917{
1918    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1919    NEOPtr nPtr = NEOPTR(pScrn);
1920
1921    if(pScrn->vtSema){
1922	if (nPtr->NeoHWCursorShown)
1923	    NeoHideCursor(pScrn);
1924	neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE);
1925
1926	neoLock(pScrn);
1927	neoUnmapMem(pScrn);
1928    }
1929    if (nPtr->AccelInfoRec)
1930	XAADestroyInfoRec(nPtr->AccelInfoRec);
1931    if (nPtr->CursorInfo)
1932	xf86DestroyCursorInfoRec(nPtr->CursorInfo);
1933    if (nPtr->ShadowPtr)
1934	xfree(nPtr->ShadowPtr);
1935
1936    pScrn->vtSema = FALSE;
1937    pScreen->CloseScreen = nPtr->CloseScreen;
1938    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1939}
1940
1941/* Optional */
1942static void
1943NEOFreeScreen(int scrnIndex, int flags)
1944{
1945    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1946	vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1947    NEOFreeRec(xf86Screens[scrnIndex]);
1948}
1949
1950/* Optional */
1951static ModeStatus
1952NEOValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1953{
1954    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1955    NEOPtr nPtr = NEOPTR(pScrn);
1956    int vDisplay = mode->VDisplay * ((mode->Flags & V_DBLSCAN) ? 2 : 1);
1957
1958    /*
1959     * Is there any LineCompare Bit 10? Where?
1960     * The 9 well known VGA bits give us a maximum height of 1024
1961     */
1962    if (vDisplay > 1024)
1963	return MODE_BAD;
1964
1965    /*
1966     * Limit the modes to just those allowed by the various NeoMagic
1967     * chips.
1968     */
1969
1970    if (nPtr->overrideValidate) {
1971	xf86DrvMsg(scrnIndex, X_WARNING, "display mode validation disabled\n");
1972    } else {
1973	/*
1974	 * When the LCD is active, only allow modes that are (1) equal to
1975	 * or smaller than the size of the panel and (2) are one of the
1976	 * following sizes: 1024x768, 800x600, 640x480.
1977	 */
1978	if (nPtr->internDisp || !nPtr->externDisp) {
1979	    /* Is the mode larger than the LCD panel? */
1980	    if ((mode->HDisplay > nPtr->NeoPanelWidth) ||
1981		(vDisplay > nPtr->NeoPanelHeight)) {
1982		xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) "
1983			   "larger than the LCD panel (%dx%d)\n",
1984			   mode->HDisplay,
1985			   mode->VDisplay,
1986			   nPtr->NeoPanelWidth,
1987			   nPtr->NeoPanelHeight);
1988		return(MODE_BAD);
1989	    }
1990
1991	    /* Is the mode one of the acceptable sizes? */
1992	    switch (mode->HDisplay) {
1993	    case 1280:
1994		if (mode->VDisplay == 1024)
1995		    return(MODE_OK);
1996		break;
1997	    case 1024 :
1998		if (mode->VDisplay == 768)
1999		    return(MODE_OK);
2000		if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480))
2001		    return(MODE_OK);
2002		break;
2003	    case  800 :
2004		if (mode->VDisplay == 600)
2005		    return(MODE_OK);
2006		if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480))
2007		    return(MODE_OK);
2008		break;
2009	    case  640 :
2010		if (mode->VDisplay == 480)
2011		    return(MODE_OK);
2012		break;
2013#if 1
2014	    case 320:
2015		if (mode->VDisplay == 240)
2016		    return(MODE_OK);
2017		break;
2018#endif
2019	    default:
2020		break;
2021	    }
2022
2023	    xf86DrvMsg(scrnIndex, X_INFO, "Removing mode (%dx%d) that won't "
2024		       "display properly on LCD\n",
2025		       mode->HDisplay,
2026		       mode->VDisplay);
2027	    return(MODE_BAD);
2028	}
2029    }
2030    return(MODE_OK);
2031}
2032
2033static void
2034neoLock(ScrnInfoPtr pScrn)
2035{
2036    vgaHWPtr hwp = VGAHWPTR(pScrn);
2037
2038    VGAwGR(0x09,0x00);
2039    vgaHWLock(hwp);
2040}
2041
2042static void
2043neoUnlock(ScrnInfoPtr pScrn)
2044{
2045    vgaHWPtr hwp = VGAHWPTR(pScrn);
2046
2047    vgaHWUnlock(hwp);
2048    VGAwGR(0x09,0x26);
2049}
2050
2051static Bool
2052neoMapMem(ScrnInfoPtr pScrn)
2053{
2054    NEOPtr nPtr = NEOPTR(pScrn);
2055    vgaHWPtr hwp = VGAHWPTR(pScrn);
2056
2057    if (!nPtr->noLinear) {
2058	if (!nPtr->noMMIO) {
2059	    if (nPtr->pEnt->location.type == BUS_PCI){
2060		nPtr->NeoMMIOBase =
2061		    xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
2062				  nPtr->PciTag, nPtr->NeoMMIOAddr,
2063				  0x200000L);
2064		if (nPtr->NeoMMIOAddr2 != 0){
2065		    nPtr->NeoMMIOBase2 =
2066		        xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
2067				      nPtr->PciTag, nPtr->NeoMMIOAddr2,
2068				      0x100000L);
2069		}
2070	    } else
2071		nPtr->NeoMMIOBase =
2072		    xf86MapVidMem(pScrn->scrnIndex,
2073				  VIDMEM_MMIO, nPtr->NeoMMIOAddr,
2074				  0x200000L);
2075	    if (nPtr->NeoMMIOBase == NULL)
2076	        return FALSE;
2077	}
2078
2079	if (nPtr->pEnt->location.type == BUS_PCI)
2080	    nPtr->NeoFbBase =
2081		xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
2082			      nPtr->PciTag,
2083			      (unsigned long)nPtr->NeoLinearAddr,
2084			      nPtr->NeoFbMapSize);
2085	else
2086	    nPtr->NeoFbBase =
2087		xf86MapVidMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
2088			      (unsigned long)nPtr->NeoLinearAddr,
2089			      nPtr->NeoFbMapSize);
2090	if (nPtr->NeoFbBase == NULL)
2091	    return FALSE;
2092    } else {
2093	/* In paged mode Base is the VGA window at 0xA0000 */
2094	nPtr->NeoFbBase = hwp->Base;
2095    }
2096    return TRUE;
2097}
2098
2099/*
2100 * Unmap the framebuffer and MMIO memory.
2101 */
2102
2103static Bool
2104neoUnmapMem(ScrnInfoPtr pScrn)
2105{
2106    NEOPtr nPtr = NEOPTR(pScrn);
2107
2108    if (!nPtr->noLinear) {
2109      if (nPtr->NeoMMIOBase)
2110	  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase,
2111			  0x200000L);
2112      nPtr->NeoMMIOBase = NULL;
2113      if (nPtr->NeoMMIOBase2)
2114	  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase2,
2115			  0x100000L);
2116      nPtr->NeoMMIOBase2 = NULL;
2117      xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoFbBase,
2118		    nPtr->NeoFbMapSize);
2119    }
2120    nPtr->NeoFbBase = NULL;
2121
2122    return TRUE;
2123}
2124
2125static void
2126neoSave(ScrnInfoPtr pScrn)
2127{
2128    vgaRegPtr VgaSave = &VGAHWPTR(pScrn)->SavedReg;
2129    vgaHWPtr hwp = VGAHWPTR(pScrn);
2130    NEOPtr nPtr = NEOPTR(pScrn);
2131    NeoRegPtr save;
2132    int i;
2133
2134    save = &nPtr->NeoSavedReg;
2135
2136    VGAwGR(0x09,0x26);
2137    /*
2138     * Whatever code is needed to get back to bank zero goes here.
2139     */
2140    VGAwGR(0x15,0x00);
2141
2142    /* get generic registers */
2143    vgaHWSave(pScrn, VgaSave, VGA_SR_ALL);
2144
2145    /*
2146     * The port I/O code necessary to read in the extended registers
2147     * into the fields of the vgaNeoRec structure goes here.
2148     */
2149
2150    save->GeneralLockReg = VGArGR(0x0A);
2151
2152    save->ExtCRTDispAddr = VGArGR(0x0E);
2153    if (nPtr->NeoChipset != NM2070) {
2154	save->ExtCRTOffset = VGArGR(0x0F);
2155    }
2156    save->SysIfaceCntl1 = VGArGR(0x10);
2157    save->SysIfaceCntl2 = VGArGR(0x11);
2158    save->SingleAddrPage = VGArGR(0x15);
2159    save->DualAddrPage = VGArGR(0x16);
2160    save->PanelDispCntlReg1 = VGArGR(0x20);
2161    save->PanelDispCntlReg2 = VGArGR(0x25);
2162    save->PanelDispCntlReg3 = VGArGR(0x30);
2163    save->PanelVertCenterReg1 = VGArGR(0x28);
2164    save->PanelVertCenterReg2 = VGArGR(0x29);
2165    save->PanelVertCenterReg3 = VGArGR(0x2A);
2166    if (nPtr->NeoChipset != NM2070) {
2167        save->PanelVertCenterReg4 = VGArGR(0x32);
2168	save->PanelHorizCenterReg1 = VGArGR(0x33);
2169	save->PanelHorizCenterReg2 = VGArGR(0x34);
2170	save->PanelHorizCenterReg3 = VGArGR(0x35);
2171    }
2172    if (nPtr->NeoChipset == NM2160) {
2173        save->PanelHorizCenterReg4 = VGArGR(0x36);
2174    }
2175    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
2176	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
2177	save->PanelHorizCenterReg4 = VGArGR(0x36);
2178	save->PanelVertCenterReg5  = VGArGR(0x37);
2179	save->PanelHorizCenterReg5 = VGArGR(0x38);
2180    }
2181    save->ExtColorModeSelect = VGArGR(0x90);
2182    save->VCLK3NumeratorLow = VGArGR(0x9B);
2183    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
2184	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380)
2185	save->VCLK3NumeratorHigh = VGArGR(0x8F);
2186    save->VCLK3Denominator = VGArGR(0x9F);
2187    save->ProgramVCLK = TRUE;
2188
2189    if (save->reg == NULL)
2190        save->reg = (regSavePtr)xnfcalloc(sizeof(regSaveRec), 1);
2191    else
2192        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2193		   "Non-NULL reg in NeoSave: reg=%p\n", (void *)save->reg);
2194
2195    save->reg->CR[0x23] = VGArCR(0x23);
2196    save->reg->CR[0x25] = VGArCR(0x25);
2197    save->reg->CR[0x2F] = VGArCR(0x2F);
2198    for (i = 0x40; i <= 0x59; i++) {
2199	save->reg->CR[i] = VGArCR(i);
2200    }
2201    for (i = 0x60; i <= 0x69; i++) {
2202	save->reg->CR[i] = VGArCR(i);
2203    }
2204    for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) {
2205	save->reg->CR[i] = VGArCR(i);
2206    }
2207
2208    for (i = 0x0A; i <= NEO_EXT_GR_MAX; i++) {
2209        save->reg->GR[i] = VGArGR(i);
2210    }
2211}
2212
2213/*
2214 * neoProgramShadowRegs
2215 *
2216 * Setup the shadow registers to their default values.  The NeoSave
2217 * routines will restore the proper values on server exit.
2218 */
2219static void
2220neoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore)
2221{
2222    int i;
2223    Bool noProgramShadowRegs;
2224    vgaHWPtr hwp = VGAHWPTR(pScrn);
2225    NEOPtr nPtr = NEOPTR(pScrn);
2226    Bool prog_lcd;
2227
2228    /*
2229     * If display is external only and we want internal
2230     * we need to program the shadow registers.
2231     */
2232    prog_lcd = (((VGArGR(0x20) & 0x3) == 0x1) && nPtr->internDisp);
2233
2234
2235    /*
2236     * Convoluted logic for shadow register programming.
2237     *
2238     * As far as we know, shadow programming is needed for the 2070,
2239     * but not in stretched modes.  Special case this code.
2240     */
2241    switch (nPtr->NeoChipset) {
2242    case NM2070:
2243	/* Program the shadow regs by default */
2244	noProgramShadowRegs = FALSE;
2245	if (!nPtr->progLcdRegs && !prog_lcd)
2246	    noProgramShadowRegs = TRUE;
2247
2248	if (restore->PanelDispCntlReg2 & 0x84) {
2249	    /* Don't program by default if in stretch mode */
2250	    noProgramShadowRegs = TRUE;
2251	    if (nPtr->progLcdStretch)
2252		noProgramShadowRegs = FALSE;
2253	}
2254	break;
2255    case NM2090:
2256    case NM2093:
2257    case NM2097:
2258    case NM2160:
2259    case NM2200:
2260    case NM2230:
2261    case NM2360:
2262    case NM2380:
2263    default:
2264	/* Don't program the shadow regs by default */
2265	noProgramShadowRegs = TRUE;
2266	if (nPtr->progLcdRegs || prog_lcd)
2267	    noProgramShadowRegs = FALSE;
2268
2269	if (restore->PanelDispCntlReg2 & 0x84) {
2270	    /* Only change the behavior if an option is set */
2271	    if (nPtr->progLcdStretchOpt)
2272		noProgramShadowRegs = !nPtr->progLcdStretch;
2273	}
2274	break;
2275    }
2276
2277    if (noProgramShadowRegs) {
2278	xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,5,"Not programming shadow registers\n");
2279	if (nPtr->NeoSavedReg.reg){
2280	    for (i = 0x40; i <= 0x59; i++) {
2281		VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]);
2282	    }
2283	    for (i = 0x60; i <= 0x64; i++) {
2284		VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]);
2285	    }
2286	}
2287    } else {
2288	/*
2289	 * Program the shadow regs based on the panel width.  This works
2290	 * fine for normal sized panels, but what about the odd ones like
2291	 * the Libretto 100 which has an 800x480 panel???
2292	 */
2293	switch (nPtr->NeoPanelWidth) {
2294	case 640 :
2295	    VGAwCR(0x40,0x5F);
2296	    VGAwCR(0x41,0x50);
2297	    VGAwCR(0x42,0x02);
2298	    VGAwCR(0x43,0x55);
2299	    VGAwCR(0x44,0x81);
2300	    VGAwCR(0x45,0x0B);
2301	    VGAwCR(0x46,0x2E);
2302	    VGAwCR(0x47,0xEA);
2303	    VGAwCR(0x48,0x0C);
2304	    VGAwCR(0x49,0xE7);
2305	    VGAwCR(0x4A,0x04);
2306	    VGAwCR(0x4B,0x2D);
2307	    VGAwCR(0x4C,0x28);
2308	    VGAwCR(0x4D,0x90);
2309	    VGAwCR(0x4E,0x2B);
2310	    VGAwCR(0x4F,0xA0);
2311	    break;
2312	case 800 :
2313	    switch (nPtr->NeoPanelHeight) {
2314	    case 600:
2315		VGAwCR(0x40,0x7F);
2316		VGAwCR(0x41,0x63);
2317		VGAwCR(0x42,0x02);
2318		VGAwCR(0x43,0x6C);
2319		VGAwCR(0x44,0x1C);
2320		VGAwCR(0x45,0x72);
2321		VGAwCR(0x46,0xE0);
2322		VGAwCR(0x47,0x58);
2323		VGAwCR(0x48,0x0C);
2324		VGAwCR(0x49,0x57);
2325		VGAwCR(0x4A,0x73);
2326		VGAwCR(0x4B,0x3D);
2327		VGAwCR(0x4C,0x31);
2328		VGAwCR(0x4D,0x01);
2329		VGAwCR(0x4E,0x36);
2330		VGAwCR(0x4F,0x1E);
2331		if (nPtr->NeoChipset != NM2070) {
2332		    VGAwCR(0x50,0x6B);
2333		    VGAwCR(0x51,0x4F);
2334		    VGAwCR(0x52,0x0E);
2335		    VGAwCR(0x53,0x58);
2336		    VGAwCR(0x54,0x88);
2337		    VGAwCR(0x55,0x33);
2338		    VGAwCR(0x56,0x27);
2339		    VGAwCR(0x57,0x16);
2340		    VGAwCR(0x58,0x2C);
2341		    VGAwCR(0x59,0x94);
2342		}
2343		break;
2344	    case 480:
2345		VGAwCR(0x40,0x7F);
2346		VGAwCR(0x41,0x63);
2347		VGAwCR(0x42,0x02);
2348		VGAwCR(0x43,0x6B);
2349		VGAwCR(0x44,0x1B);
2350		VGAwCR(0x45,0x72);
2351		VGAwCR(0x46,0xE0);
2352		VGAwCR(0x47,0x1C);
2353		VGAwCR(0x48,0x00);
2354		VGAwCR(0x49,0x57);
2355		VGAwCR(0x4A,0x73);
2356		VGAwCR(0x4B,0x3E);
2357		VGAwCR(0x4C,0x31);
2358		VGAwCR(0x4D,0x01);
2359		VGAwCR(0x4E,0x36);
2360		VGAwCR(0x4F,0x1E);
2361		VGAwCR(0x50,0x6B);
2362		VGAwCR(0x51,0x4F);
2363		VGAwCR(0x52,0x0E);
2364		VGAwCR(0x53,0x57);
2365		VGAwCR(0x54,0x87);
2366		VGAwCR(0x55,0x33);
2367		VGAwCR(0x56,0x27);
2368		VGAwCR(0x57,0x16);
2369		VGAwCR(0x58,0x2C);
2370		VGAwCR(0x59,0x94);
2371		break;
2372		break;
2373		/* Not done */
2374	    }
2375	    break;
2376	case 1024 :
2377	    switch (nPtr->NeoPanelHeight) {
2378	    case 768:
2379		VGAwCR(0x40,0xA3);
2380		VGAwCR(0x41,0x7F);
2381		VGAwCR(0x42,0x06);
2382		VGAwCR(0x43,0x85);
2383		VGAwCR(0x44,0x96);
2384		VGAwCR(0x45,0x24);
2385		VGAwCR(0x46,0xE5);
2386		VGAwCR(0x47,0x02);
2387		VGAwCR(0x48,0x08);
2388		VGAwCR(0x49,0xFF);
2389		VGAwCR(0x4A,0x25);
2390		VGAwCR(0x4B,0x4F);
2391		VGAwCR(0x4C,0x40);
2392		VGAwCR(0x4D,0x00);
2393		VGAwCR(0x4E,0x44);
2394		VGAwCR(0x4F,0x0C);
2395		VGAwCR(0x50,0x7A);
2396		VGAwCR(0x51,0x56);
2397		VGAwCR(0x52,0x00);
2398		VGAwCR(0x53,0x5D);
2399		VGAwCR(0x54,0x0E);
2400		VGAwCR(0x55,0x3B);
2401		VGAwCR(0x56,0x2B);
2402		VGAwCR(0x57,0x00);
2403		VGAwCR(0x58,0x2F);
2404		VGAwCR(0x59,0x18);
2405		VGAwCR(0x60,0x88);
2406		VGAwCR(0x61,0x63);
2407		VGAwCR(0x62,0x0B);
2408		VGAwCR(0x63,0x69);
2409		VGAwCR(0x64,0x1A);
2410		break;
2411	    case 480:
2412		VGAwCR(0x40,0xA3);
2413		VGAwCR(0x41,0x7F);
2414		VGAwCR(0x42,0x1B);
2415		VGAwCR(0x43,0x89);
2416		VGAwCR(0x44,0x16);
2417		VGAwCR(0x45,0x0B);
2418		VGAwCR(0x46,0x2C);
2419		VGAwCR(0x47,0xE8);
2420		VGAwCR(0x48,0x0C);
2421		VGAwCR(0x49,0xE7);
2422		VGAwCR(0x4A,0x09);
2423		VGAwCR(0x4B,0x4F);
2424		VGAwCR(0x4C,0x40);
2425		VGAwCR(0x4D,0x00);
2426		VGAwCR(0x4E,0x44);
2427		VGAwCR(0x4F,0x0C);
2428		VGAwCR(0x50,0x7A);
2429		VGAwCR(0x51,0x56);
2430		VGAwCR(0x52,0x00);
2431		VGAwCR(0x53,0x5D);
2432		VGAwCR(0x54,0x0E);
2433		VGAwCR(0x55,0x3B);
2434		VGAwCR(0x56,0x2A);
2435		VGAwCR(0x57,0x00);
2436		VGAwCR(0x58,0x2F);
2437		VGAwCR(0x59,0x18);
2438		VGAwCR(0x60,0x88);
2439		VGAwCR(0x61,0x63);
2440		VGAwCR(0x62,0x0B);
2441		VGAwCR(0x63,0x69);
2442		VGAwCR(0x64,0x1A);
2443		break;
2444	    }
2445	    break;
2446	case 1280:
2447#ifdef NOT_DONE
2448	    VGAwCR(0x40,0x?? );
2449            .
2450		.
2451		.
2452		VGAwCR(0x64,0x?? );
2453		break;
2454#else
2455		/* Probe should prevent this case for now */
2456		FatalError("1280 panel support incomplete\n");
2457#endif
2458	}
2459    }
2460}
2461
2462static void
2463neoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore,
2464	     Bool restoreText)
2465{
2466    NEOPtr nPtr = NEOPTR(pScrn);
2467    vgaHWPtr hwp = VGAHWPTR(pScrn);
2468    unsigned char temp;
2469    int i;
2470    Bool clock_hi = FALSE;
2471
2472    vgaHWProtect(pScrn,TRUE);		/* Blank the screen */
2473
2474    VGAwGR(0x09,0x26);
2475
2476    /* Init the shadow registers if necessary */
2477    neoProgramShadowRegs(pScrn, VgaReg, restore);
2478
2479    VGAwGR(0x15,0x00);
2480
2481    VGAwGR(0x0A,restore->GeneralLockReg);
2482
2483    /*
2484     * The color mode needs to be set before calling vgaHWRestore
2485     * to ensure the DAC is initialized properly.
2486     *
2487     * NOTE: Make sure we don't change bits make sure we don't change
2488     * any reserved bits.
2489     */
2490    temp = VGArGR(0x90);
2491
2492    switch (nPtr->NeoChipset) {
2493    case NM2070 :
2494	temp &= 0xF0; /* Save bits 7:4 */
2495	temp |= (restore->ExtColorModeSelect & ~0xF0);
2496	break;
2497    case NM2090 :
2498    case NM2093 :
2499    case NM2097 :
2500    case NM2160 :
2501    case NM2200 :
2502    case NM2230 :
2503    case NM2360 :
2504    case NM2380 :
2505	temp &= 0x70; /* Save bits 6:4 */
2506	temp |= (restore->ExtColorModeSelect & ~0x70);
2507	break;
2508    }
2509    VGAwGR(0x90,temp);
2510
2511    /*
2512     * In some rare cases a lockup might occur if we don't delay
2513     * here. (Reported by Miles Lane)
2514     */
2515    xf86UDelay(200000);
2516    /*
2517     * Disable horizontal and vertical graphics and text expansions so
2518     * that vgaHWRestore works properly.
2519     */
2520    temp = VGArGR(0x25);
2521    temp &= 0x39;
2522    VGAwGR(0x25, temp);
2523
2524    /*
2525     * Sleep for 200ms to make sure that the two operations above have
2526     * had time to take effect.
2527     */
2528    xf86UDelay(200000);
2529    /*
2530     * This function handles restoring the generic VGA registers.  */
2531    vgaHWRestore(pScrn, VgaReg,
2532		 VGA_SR_MODE
2533		 | (restoreText ? (VGA_SR_FONTS | VGA_SR_CMAP) : 0));
2534
2535    VGAwGR(0x0E, restore->ExtCRTDispAddr);
2536    VGAwGR(0x0F, restore->ExtCRTOffset);
2537    temp = VGArGR(0x10);
2538    temp &= 0x0F; /* Save bits 3:0 */
2539    temp |= (restore->SysIfaceCntl1 & ~0x0F);
2540    VGAwGR(0x10, temp);
2541
2542    VGAwGR(0x11, restore->SysIfaceCntl2);
2543    VGAwGR(0x15, restore->SingleAddrPage);
2544    VGAwGR(0x16, restore->DualAddrPage);
2545
2546    temp = VGArGR(0x20);
2547    switch (nPtr->NeoChipset) {
2548    case NM2070 :
2549	temp &= 0xFC; /* Save bits 7:2 */
2550	temp |= (restore->PanelDispCntlReg1 & ~0xFC);
2551	break;
2552    case NM2090 :
2553    case NM2093 :
2554    case NM2097 :
2555    case NM2160 :
2556	temp &= 0xDC; /* Save bits 7:6,4:2 */
2557	temp |= (restore->PanelDispCntlReg1 & ~0xDC);
2558	break;
2559    case NM2200 :
2560    case NM2230 :
2561    case NM2360 :
2562    case NM2380 :
2563	temp &= 0x98; /* Save bits 7,4:3 */
2564	temp |= (restore->PanelDispCntlReg1 & ~0x98);
2565	break;
2566    }
2567    VGAwGR(0x20, temp);
2568
2569    temp = VGArGR(0x25);
2570    temp &= 0x38; /* Save bits 5:3 */
2571    temp |= (restore->PanelDispCntlReg2 & ~0x38);
2572    VGAwGR(0x25, temp);
2573
2574    if (nPtr->NeoChipset != NM2070) {
2575	temp = VGArGR(0x30);
2576	temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
2577	temp |= (restore->PanelDispCntlReg3 & ~0xEF);
2578	VGAwGR(0x30, temp);
2579    }
2580
2581    VGAwGR(0x28, restore->PanelVertCenterReg1);
2582    VGAwGR(0x29, restore->PanelVertCenterReg2);
2583    VGAwGR(0x2a, restore->PanelVertCenterReg3);
2584
2585    if (nPtr->NeoChipset != NM2070) {
2586	VGAwGR(0x32, restore->PanelVertCenterReg4);
2587	VGAwGR(0x33, restore->PanelHorizCenterReg1);
2588	VGAwGR(0x34, restore->PanelHorizCenterReg2);
2589	VGAwGR(0x35, restore->PanelHorizCenterReg3);
2590    }
2591
2592    if (nPtr->NeoChipset == NM2160) {
2593	VGAwGR(0x36, restore->PanelHorizCenterReg4);
2594    }
2595
2596    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
2597	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
2598        VGAwGR(0x36, restore->PanelHorizCenterReg4);
2599        VGAwGR(0x37, restore->PanelVertCenterReg5);
2600        VGAwGR(0x38, restore->PanelHorizCenterReg5);
2601    }
2602    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
2603	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380)
2604	clock_hi = TRUE;
2605
2606    /* Program VCLK3 if needed. */
2607    if (restore->ProgramVCLK
2608	 && ((VGArGR(0x9B) != restore->VCLK3NumeratorLow)
2609	    || (VGArGR(0x9F) !=  restore->VCLK3Denominator)
2610	    || (clock_hi && ((VGArGR(0x8F) & ~0x0f)
2611			     != (restore->VCLK3NumeratorHigh & ~0x0F))))) {
2612	VGAwGR(0x9B, restore->VCLK3NumeratorLow);
2613	if (clock_hi) {
2614	    temp = VGArGR(0x8F);
2615	    temp &= 0x0F; /* Save bits 3:0 */
2616	    temp |= (restore->VCLK3NumeratorHigh & ~0x0F);
2617	    VGAwGR(0x8F, temp);
2618	}
2619	VGAwGR(0x9F, restore->VCLK3Denominator);
2620    }
2621    if (restore->biosMode)
2622	VGAwCR(0x23,restore->biosMode);
2623
2624    if (restore->reg) {
2625	VGAwCR(0x23,restore->reg->CR[0x23]);
2626	VGAwCR(0x25,restore->reg->CR[0x25]);
2627	VGAwCR(0x2F,restore->reg->CR[0x2F]);
2628	for (i = 0x40; i <= 0x59; i++) {
2629	    VGAwCR(i, restore->reg->CR[i]);
2630	}
2631	for (i = 0x60; i <= 0x69; i++) {
2632	    VGAwCR(i, restore->reg->CR[i]);
2633	}
2634	for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) {
2635	    VGAwCR(i, restore->reg->CR[i]);
2636	}
2637
2638	for (i = 0x0a; i <= 0x3f; i++) {
2639	    VGAwGR(i, restore->reg->GR[i]);
2640	}
2641	for (i = 0x90; i <= NEO_EXT_GR_MAX; i++) {
2642	    VGAwGR(i, restore->reg->GR[i]);
2643	}
2644    }
2645
2646    VGAwGR (0x93, 0xc0); /* Gives faster framebuffer writes */
2647
2648    /* Program vertical extension register */
2649    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
2650	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
2651	VGAwCR(0x70, restore->VerticalExt);
2652    }
2653
2654    vgaHWProtect(pScrn, FALSE);		/* Turn on screen */
2655}
2656
2657static Bool
2658neoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
2659{
2660    NEOPtr nPtr = NEOPTR(pScrn);
2661    NEOACLPtr nAcl = NEOACLPTR(pScrn);
2662    int hoffset, voffset;
2663    vgaHWPtr hwp = VGAHWPTR(pScrn);
2664    NeoRegPtr NeoNew = &nPtr->NeoModeReg;
2665    vgaRegPtr NeoStd = &hwp->ModeReg;
2666    Bool noLcdStretch = nPtr->noLcdStretch;
2667    int clockMul = 1;
2668
2669    neoUnlock(pScrn);
2670
2671    /*
2672     * This will allocate the datastructure and initialize all of the
2673     * generic VGA registers.
2674     */
2675
2676    if (!vgaHWInit(pScrn, mode))
2677	return(FALSE);
2678
2679    /*
2680     * Several registers need to be corrected from the default values
2681     * assigned by vgaHWinit().
2682     */
2683    pScrn->vtSema = TRUE;
2684
2685    /*
2686     * The default value assigned by vgaHW.c is 0x41, but this does
2687     * not work for NeoMagic.
2688     */
2689    NeoStd->Attribute[16] = 0x01;
2690
2691    switch (pScrn->depth) { /*@!@*/
2692    case  8 :
2693	NeoStd->CRTC[0x13] = pScrn->displayWidth >> 3;
2694	NeoNew->ExtCRTOffset   = pScrn->displayWidth >> 11;
2695	NeoNew->ExtColorModeSelect = 0x11;
2696	break;
2697    case 15 :
2698        NeoNew->ExtColorModeSelect = 0x12;
2699	NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2;
2700	NeoNew->ExtCRTOffset   = pScrn->displayWidth >> 10;
2701        break;
2702    case 16 :
2703        NeoNew->ExtColorModeSelect = 0x13;
2704	NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2;
2705	NeoNew->ExtCRTOffset   = pScrn->displayWidth >> 10;
2706	break;
2707    case 24 :
2708	NeoStd->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
2709	NeoNew->ExtCRTOffset   = (pScrn->displayWidth * 3) >> 11;
2710	NeoNew->ExtColorModeSelect = 0x14;
2711	break;
2712    default :
2713	break;
2714    }
2715
2716    NeoNew->ExtCRTDispAddr = 0x10;
2717
2718    /* Vertical Extension */
2719    NeoNew->VerticalExt = (((mode->CrtcVTotal -2) & 0x400) >> 10 )
2720      | (((mode->CrtcVDisplay -1) & 0x400) >> 9 )
2721        | (((mode->CrtcVSyncStart) & 0x400) >> 8 )
2722          | (((mode->CrtcVBlankStart - 1) & 0x400) >> 7 );
2723
2724    /* Fast write bursts on unless disabled. */
2725    if (nPtr->onPciBurst) {
2726	NeoNew->SysIfaceCntl1 = 0x30;
2727    } else {
2728	NeoNew->SysIfaceCntl1 = 0x00;
2729    }
2730
2731    /* If they are used, enable linear addressing and/or enable MMIO. */
2732    NeoNew->SysIfaceCntl2 = 0x00;
2733    if (!nPtr->noLinear)
2734	NeoNew->SysIfaceCntl2 |= 0x80;
2735    if (!nPtr->noMMIO)
2736	NeoNew->SysIfaceCntl2 |= 0x40;
2737
2738    /* Enable any user specified display devices. */
2739    NeoNew->PanelDispCntlReg1 = 0x00;
2740    if (nPtr->internDisp) {
2741	NeoNew->PanelDispCntlReg1 |= 0x02;
2742    }
2743    if (nPtr->externDisp) {
2744	NeoNew->PanelDispCntlReg1 |= 0x01;
2745    }
2746
2747#if 0
2748    /*
2749     * This was replaced: if no devices are specified take the
2750     * probed settings. If the probed settings are bogus fallback
2751     * to internal only.
2752     */
2753    /* If the user did not specify any display devices, then... */
2754    if (NeoNew->PanelDispCntlReg1 == 0x00) {
2755	/* Default to internal (i.e., LCD) only. */
2756	NeoNew->PanelDispCntlReg1 |= 0x02;
2757    }
2758#endif
2759    /* If we are using a fixed mode, then tell the chip we are. */
2760    switch (mode->HDisplay) {
2761    case 1280:
2762	NeoNew->PanelDispCntlReg1 |= 0x60;
2763        break;
2764    case 1024:
2765	NeoNew->PanelDispCntlReg1 |= 0x40;
2766        break;
2767    case 800:
2768	NeoNew->PanelDispCntlReg1 |= 0x20;
2769        break;
2770    case 640:
2771    default:
2772        break;
2773    }
2774
2775    /* Setup shadow register locking. */
2776    switch (NeoNew->PanelDispCntlReg1 & 0x03) {
2777    case 0x01 : /* External CRT only mode: */
2778	NeoNew->GeneralLockReg = 0x00;
2779	/* We need to program the VCLK for external display only mode. */
2780	NeoNew->ProgramVCLK = TRUE;
2781	break;
2782    case 0x02 : /* Internal LCD only mode: */
2783    case 0x03 : /* Simultaneous internal/external (LCD/CRT) mode: */
2784	NeoNew->GeneralLockReg = 0x01;
2785	/* Don't program the VCLK when using the LCD. */
2786	NeoNew->ProgramVCLK = FALSE;
2787	break;
2788    }
2789
2790    /*
2791     * If the screen is to be stretched, turn on stretching for the
2792     * various modes.
2793     *
2794     * OPTION_LCD_STRETCH means stretching should be turned off!
2795     */
2796    NeoNew->PanelDispCntlReg2 = 0x00;
2797    NeoNew->PanelDispCntlReg3 = 0x00;
2798    nAcl->NoCursorMode = FALSE;
2799
2800    if ((!noLcdStretch) &&
2801	(NeoNew->PanelDispCntlReg1 & 0x02)) {
2802	if (mode->HDisplay == nPtr->NeoPanelWidth) {
2803	    /*
2804	     * Don't disable the flag.  It will be needed if another mode
2805	     * is selected.
2806	     */
2807	    /*
2808	     * No stretching required when the requested display width
2809	     * equals the panel width.
2810	     */
2811	    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Stretching disabled\n");
2812	        noLcdStretch = TRUE;
2813	} else {
2814
2815	    switch (mode->HDisplay) {
2816	    case  320 : /* Needs testing.  KEM -- 24 May 98 */
2817	    case  400 : /* Needs testing.  KEM -- 24 May 98 */
2818	    case  640 :
2819	    case  800 :
2820	    case 1024 :
2821		NeoNew->PanelDispCntlReg2 |= 0xC6;
2822		nAcl->NoCursorMode = TRUE;
2823		break;
2824	    default   :
2825		/* No stretching in these modes. */
2826		xf86DrvMsg(pScrn->scrnIndex,X_INFO,
2827			   "Stretching disabled not supported in this mode\n");
2828		noLcdStretch = TRUE;
2829		break;
2830	    }
2831	}
2832    } else if (mode->Flags & V_DBLSCAN) {
2833	nAcl->NoCursorMode = TRUE;
2834    }
2835
2836    /*
2837     * If the screen is to be centerd, turn on the centering for the
2838     * various modes.
2839     */
2840    NeoNew->PanelVertCenterReg1  = 0x00;
2841    NeoNew->PanelVertCenterReg2  = 0x00;
2842    NeoNew->PanelVertCenterReg3  = 0x00;
2843    NeoNew->PanelVertCenterReg4  = 0x00;
2844    NeoNew->PanelVertCenterReg5  = 0x00;
2845    NeoNew->PanelHorizCenterReg1 = 0x00;
2846    NeoNew->PanelHorizCenterReg2 = 0x00;
2847    NeoNew->PanelHorizCenterReg3 = 0x00;
2848    NeoNew->PanelHorizCenterReg4 = 0x00;
2849    NeoNew->PanelHorizCenterReg5 = 0x00;
2850
2851    if (nPtr->lcdCenter &&
2852	(NeoNew->PanelDispCntlReg1 & 0x02)) {
2853	Bool doCenter = FALSE;
2854
2855	hoffset = 0;
2856	voffset = 0;
2857	if (mode->HDisplay == nPtr->NeoPanelWidth) {
2858	    /*
2859	     * No centering required when the requested display width
2860	     * equals the panel width.
2861	     */
2862	} else {
2863	    NeoNew->PanelDispCntlReg3 |= 0x10;
2864	    if (noLcdStretch) {
2865		/* Calculate the horizontal offsets. */
2866		int HDisplay = mode->HDisplay
2867		    << ((mode->VDisplay < 480) ? 1 : 0);
2868		hoffset = ((nPtr->NeoPanelWidth - HDisplay) >> 4) - 1;
2869		if (mode->VDisplay < 480)
2870		    hoffset >>= 1;
2871		doCenter = TRUE;
2872	    } else {
2873		/* Stretched modes cannot be centered. */
2874		hoffset = 0;
2875	    }
2876	}
2877	if (mode->VDisplay == nPtr->NeoPanelHeight) {
2878	    /*
2879	     * No centering required when the requested display width
2880	     * equals the panel width.
2881	     */
2882	} else {
2883	    NeoNew->PanelDispCntlReg2 |= 0x01;
2884	    if (noLcdStretch) {
2885		/* Calculate the vertical offsets. */
2886		int VDisplay = mode->VDisplay
2887		    << ((mode->Flags & V_DBLSCAN) ? 1 : 0);
2888		voffset = ((nPtr->NeoPanelHeight - VDisplay) >> 1) - 2;
2889		doCenter = TRUE;
2890	    } else {
2891		/* Stretched modes cannot be centered. */
2892		voffset = 0;
2893	    }
2894	}
2895
2896	if (doCenter) {
2897	    switch (mode->HDisplay) {
2898	    case  320 : /* Needs testing.  KEM -- 24 May 98 */
2899  		NeoNew->PanelHorizCenterReg3 = hoffset;
2900		NeoNew->PanelVertCenterReg3  = voffset;
2901		break;
2902	    case  400 : /* Needs testing.  KEM -- 24 May 98 */
2903		NeoNew->PanelHorizCenterReg4 = hoffset;
2904		NeoNew->PanelVertCenterReg1  = voffset;
2905		break;
2906	    case  640 :
2907		NeoNew->PanelHorizCenterReg1 = hoffset;
2908		NeoNew->PanelVertCenterReg3  = voffset;
2909		break;
2910	    case  800 :
2911		NeoNew->PanelHorizCenterReg2 = hoffset;
2912		switch (mode->VDisplay) {
2913		case 600:
2914		    NeoNew->PanelVertCenterReg4  = voffset;
2915		    break;
2916		case 480:
2917		    /* Not sure if this is correct */
2918		    NeoNew->PanelVertCenterReg3  = voffset;
2919		    break;
2920		}
2921		break;
2922	    case 1024 :
2923		NeoNew->PanelHorizCenterReg5 = hoffset;
2924		NeoNew->PanelVertCenterReg5  = voffset;
2925		break;
2926	    case 1280 :
2927	    default   :
2928		/* No centering in these modes. */
2929		break;
2930	    }
2931	}
2932    }
2933
2934    if (!noLcdStretch &&
2935	(NeoNew->PanelDispCntlReg1 & 0x02))  {
2936	if (mode->HDisplay != nPtr->NeoPanelWidth)
2937	    nPtr->videoHZoom = (double)nPtr->NeoPanelWidth/mode->HDisplay;
2938	if (mode->VDisplay != nPtr->NeoPanelHeight)
2939	    nPtr->videoVZoom = (double)nPtr->NeoPanelHeight/mode->VDisplay;
2940    } else {
2941	nPtr->videoHZoom = 1.0;
2942	nPtr->videoVZoom = 1.0;
2943    }
2944    /* Do double scan */
2945    if (mode->VDisplay < 480) {
2946	NeoStd->Sequencer[1] |= 0x8;
2947	clockMul = 2;
2948    }
2949
2950    NeoNew->biosMode = neoFindMode(mode->HDisplay,mode->VDisplay,pScrn->depth);
2951
2952    /*
2953     * New->reg should be empty.  Just in
2954     * case it isn't, warn us and clear it anyway.
2955     */
2956    if (NeoNew->reg) {
2957	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2958		   "Non-NULL reg in NeoInit: reg=%p\n", (void *)NeoNew->reg);
2959	xfree(NeoNew->reg);
2960	NeoNew->reg = NULL;
2961    }
2962
2963    /*
2964     * Calculate the VCLK that most closely matches the requested dot
2965     * clock.
2966     */
2967    neoCalcVCLK(pScrn, mode->SynthClock*clockMul);
2968
2969    /* Since we program the clocks ourselves, always use VCLK3. */
2970    NeoStd->MiscOutReg |= 0x0C;
2971
2972    neoRestore(pScrn, NeoStd, NeoNew, FALSE);
2973
2974    return(TRUE);
2975}
2976
2977/*
2978 * neoCalcVCLK --
2979 *
2980 * Determine the closest clock frequency to the one requested.
2981 */
2982#define REF_FREQ 14.31818
2983#define MAX_N 127
2984#define MAX_D 31
2985#define MAX_F 1
2986
2987static void
2988neoCalcVCLK(ScrnInfoPtr pScrn, long freq)
2989{
2990    NEOPtr nPtr = NEOPTR(pScrn);
2991
2992    int n, d, f;
2993    double f_out;
2994    double f_diff;
2995    int n_best = 0, d_best = 1, f_best = 0;
2996    double f_best_diff = 999999.0;
2997    double f_target = freq/1000.0;
2998
2999    for (f = 0; f <= MAX_F; f++)
3000	for (n = 0; n <= MAX_N; n++)
3001	    for (d = 1; d <= MAX_D; d++) {
3002		f_out = (n+1.0)/((d+1.0)*(1<<f))*REF_FREQ;
3003		f_diff = abs(f_out-f_target);
3004		if (f_diff < f_best_diff) {
3005		    f_best_diff = f_diff;
3006		    n_best = n;
3007		    d_best = d;
3008		    f_best = f;
3009		}
3010	    }
3011
3012    if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
3013	|| nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
3014        /* NOT_DONE:  We are trying the full range of the 2200 clock.
3015           We should be able to try n up to 2047 */
3016	nPtr->NeoModeReg.VCLK3NumeratorLow  = n_best;
3017	nPtr->NeoModeReg.VCLK3NumeratorHigh = (f_best << 7);
3018    }
3019    else {
3020	nPtr->NeoModeReg.VCLK3NumeratorLow  = n_best | (f_best << 7);
3021    }
3022    nPtr->NeoModeReg.VCLK3Denominator = d_best;
3023#ifdef DEBUG
3024    ErrorF("neoVCLK: f:%f NumLow=%i NumHi=%i Den=%i Df=%f\n",
3025	   f_target,
3026	   nPtr->NeoModeReg.VCLK3NumeratorLow,
3027	   nPtr->NeoModeReg.VCLK3NumeratorHigh,
3028	   nPtr->NeoModeReg.VCLK3Denominator,
3029	   f_best_diff);
3030#endif
3031}
3032
3033/*
3034 * NeoDisplayPowerManagementSet --
3035 *
3036 * Sets VESA Display Power Management Signaling (DPMS) Mode.
3037 */
3038static void
3039NeoDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
3040			     int flags)
3041{
3042    NEOPtr nPtr = NEOPTR(pScrn);
3043    vgaHWPtr hwp = VGAHWPTR(pScrn);
3044    unsigned char SEQ01 = 0;
3045    unsigned char LogicPowerMgmt = 0;
3046    unsigned char LCD_on = 0;
3047
3048    if (!pScrn->vtSema)
3049	return;
3050
3051    switch (PowerManagementMode) {
3052    case DPMSModeOn:
3053	/* Screen: On; HSync: On, VSync: On */
3054	SEQ01 = 0x00;
3055	LogicPowerMgmt = 0x00;
3056	if (nPtr->internDisp || ! nPtr->externDisp)
3057	    LCD_on = 0x02;
3058	else
3059	    LCD_on = 0x00;
3060	break;
3061    case DPMSModeStandby:
3062	/* Screen: Off; HSync: Off, VSync: On */
3063	SEQ01 = 0x20;
3064	LogicPowerMgmt = 0x10;
3065	LCD_on = 0x00;
3066	break;
3067    case DPMSModeSuspend:
3068	/* Screen: Off; HSync: On, VSync: Off */
3069	SEQ01 = 0x20;
3070	LogicPowerMgmt = 0x20;
3071	LCD_on = 0x00;
3072	break;
3073    case DPMSModeOff:
3074	/* Screen: Off; HSync: Off, VSync: Off */
3075	SEQ01 = 0x20;
3076	LogicPowerMgmt = 0x30;
3077	LCD_on = 0x00;
3078	break;
3079    }
3080
3081    /* Turn the screen on/off */
3082    SEQ01 |= VGArSR(0x01) & ~0x20;
3083    VGAwSR(0x01, SEQ01);
3084
3085    /* Turn the LCD on/off */
3086    LCD_on |= VGArGR(0x20) & ~0x02;
3087    VGAwGR(0x20, LCD_on);
3088
3089    /* Set the DPMS mode */
3090    LogicPowerMgmt |= 0x80;
3091    LogicPowerMgmt |= VGArGR(0x01) & ~0xF0;
3092    VGAwGR(0x01,LogicPowerMgmt);
3093}
3094
3095static unsigned int
3096neo_ddc1Read(ScrnInfoPtr pScrn)
3097{
3098    register vgaHWPtr hwp = VGAHWPTR(pScrn);
3099    register unsigned int tmp;
3100
3101    /* This needs to be investigated: we may have to swap this around */
3102    while (!(hwp->readST01(hwp)&0x8)) {};
3103    while (hwp->readST01(hwp)&0x8) {};
3104
3105    tmp = (VGArGR(0xA1) & 0x08);
3106
3107    return (tmp);
3108}
3109
3110static xf86MonPtr
3111neo_ddc1(int scrnIndex)
3112{
3113    vgaHWPtr hwp = VGAHWPTR(xf86Screens[scrnIndex]);
3114    unsigned int reg1, reg2, reg3;
3115    xf86MonPtr ret;
3116
3117    /* initialize chipset */
3118    reg1 = VGArCR(0x21);
3119    reg2 = VGArCR(0x1D);
3120    reg3 = VGArCR(0xA1);
3121    VGAwCR(0x21,0x00);
3122    VGAwCR(0x1D,0x01);  /* some Voodoo */
3123    VGAwGR(0xA1,0x2F);
3124    ret =  xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),neo_ddc1Read);
3125    /* undo initialization */
3126    VGAwCR(0x21,reg1);
3127    VGAwCR(0x1D,reg2);
3128    VGAwGR(0xA1,reg3);
3129    return ret;
3130}
3131
3132static Bool
3133neoDoDDC1(ScrnInfoPtr pScrn)
3134{
3135    Bool ret = FALSE;
3136    vgaHWPtr hwp = VGAHWPTR(pScrn);
3137
3138    VGAwGR(0x09,0x26);
3139    ret = xf86SetDDCproperties(pScrn,
3140				xf86PrintEDID(neo_ddc1(pScrn->scrnIndex)));
3141    VGAwGR(0x09,0x00);
3142
3143    return ret;
3144}
3145
3146static Bool
3147neoDoDDC2(ScrnInfoPtr pScrn)
3148{
3149    NEOPtr nPtr = NEOPTR(pScrn);
3150    vgaHWPtr hwp = VGAHWPTR(pScrn);
3151    Bool ret = FALSE;
3152
3153    VGAwGR(0x09,0x26);
3154    if (xf86LoadSubModule(pScrn, "i2c")) {
3155        xf86LoaderReqSymLists(i2cSymbols, NULL);
3156	if (neo_I2CInit(pScrn)) {
3157	    ret = xf86SetDDCproperties(pScrn,xf86PrintEDID(xf86DoEDID_DDC2(
3158					      pScrn->scrnIndex,nPtr->I2C)));
3159	}
3160    }
3161    VGAwGR(0x09,0x00);
3162
3163    return ret;
3164}
3165
3166static Bool
3167neoDoDDCVBE(ScrnInfoPtr pScrn)
3168{
3169    NEOPtr nPtr = NEOPTR(pScrn);
3170    vgaHWPtr hwp = VGAHWPTR(pScrn);
3171    vbeInfoPtr pVbe;
3172    Bool ret = FALSE;
3173
3174    VGAwGR(0x09,0x26);
3175    if (xf86LoadSubModule(pScrn, "vbe")) {
3176	xf86LoaderReqSymLists(vbeSymbols, NULL);
3177        if ((pVbe = VBEInit(NULL,nPtr->pEnt->index))) {
3178	  ret = xf86SetDDCproperties(
3179				     pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
3180	  vbeFree(pVbe);
3181	}
3182    }
3183    VGAwGR(0x09,0x00);
3184    return ret;
3185}
3186
3187static int
3188neoFindMode(int xres, int yres, int depth)
3189{
3190    int xres_s;
3191    int i, size;
3192    biosMode *mode;
3193
3194    switch (depth) {
3195    case 8:
3196	size = sizeof(bios8) / sizeof(biosMode);
3197	mode = bios8;
3198	break;
3199    case 15:
3200	size = sizeof(bios15) / sizeof(biosMode);
3201	mode = bios15;
3202	break;
3203    case 16:
3204	size = sizeof(bios16) / sizeof(biosMode);
3205	mode = bios16;
3206	break;
3207    case 24:
3208	size = sizeof(bios24) / sizeof(biosMode);
3209	mode = bios24;
3210	break;
3211    default:
3212	return 0;
3213    }
3214
3215    for (i = 0; i < size; i++) {
3216	if (xres <= mode[i].x_res) {
3217	    xres_s = mode[i].x_res;
3218	    for (; i < size; i++) {
3219		if (mode[i].x_res != xres_s)
3220		    return mode[i-1].mode;
3221		if (yres <= mode[i].y_res)
3222		    return mode[i].mode;
3223	    }
3224	}
3225    }
3226    return mode[size - 1].mode;
3227
3228}
3229
3230static void
3231neoProbeDDC(ScrnInfoPtr pScrn, int index)
3232{
3233    vbeInfoPtr pVbe;
3234
3235    if (xf86LoadSubModule(pScrn, "vbe")) {
3236        if ((pVbe = VBEInit(NULL,index))) {
3237	    ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
3238	    vbeFree(pVbe);
3239	}
3240    }
3241}
3242