summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ati.c72
-rw-r--r--src/ati.h37
-rw-r--r--src/atiaccel.c81
-rw-r--r--src/atiaccel.h36
-rw-r--r--src/atiadapter.c54
-rw-r--r--src/atiadapter.h60
-rw-r--r--src/atiadjust.c224
-rw-r--r--src/atiadjust.h33
-rw-r--r--src/atibank.c409
-rw-r--r--src/atibank.h88
-rw-r--r--src/atibus.c183
-rw-r--r--src/atibus.h59
-rw-r--r--src/atichip.c688
-rw-r--r--src/atichip.h144
-rw-r--r--src/aticlock.c1586
-rw-r--r--src/aticlock.h86
-rw-r--r--src/aticonfig.c244
-rw-r--r--src/aticonfig.h34
-rw-r--r--src/aticonsole.c360
-rw-r--r--src/aticonsole.h46
-rw-r--r--src/aticrtc.h43
-rw-r--r--src/aticursor.c75
-rw-r--r--src/aticursor.h44
-rw-r--r--src/atidac.c522
-rw-r--r--src/atidac.h103
-rw-r--r--src/atidga.c479
-rw-r--r--src/atidga.h38
-rw-r--r--src/atidsp.c323
-rw-r--r--src/atidsp.h38
-rw-r--r--src/atiident.c134
-rw-r--r--src/atiident.h55
-rw-r--r--src/atiio.h83
-rw-r--r--src/atiload.c179
-rw-r--r--src/atiload.h56
-rw-r--r--src/atilock.c586
-rw-r--r--src/atilock.h33
-rw-r--r--src/atimach64.c2164
-rw-r--r--src/atimach64.h50
-rw-r--r--src/atimach64io.c100
-rw-r--r--src/atimach64io.h269
-rw-r--r--src/atimisc.c104
-rw-r--r--src/atimode.c1128
-rw-r--r--src/atimode.h41
-rw-r--r--src/atimodule.c126
-rw-r--r--src/atimodule.h31
-rw-r--r--src/atimono.h43
-rw-r--r--src/atioption.c150
-rw-r--r--src/atioption.h60
-rw-r--r--src/atipreinit.c3090
-rw-r--r--src/atipreinit.h33
-rw-r--r--src/atiprint.c823
-rw-r--r--src/atiprint.h37
-rw-r--r--src/atipriv.h31
-rw-r--r--src/atiprobe.c2353
-rw-r--r--src/atiprobe.h33
-rw-r--r--src/atiregs.h2718
-rw-r--r--src/atirgb514.c280
-rw-r--r--src/atirgb514.h38
-rw-r--r--src/atiscreen.c345
-rw-r--r--src/atiscreen.h34
-rw-r--r--src/atistruct.h421
-rw-r--r--src/atiutil.c114
-rw-r--r--src/atiutil.h70
-rw-r--r--src/ativalid.c235
-rw-r--r--src/ativalid.h33
-rw-r--r--src/ativersion.h58
-rw-r--r--src/ativga.c532
-rw-r--r--src/ativga.h45
-rw-r--r--src/ativgaio.c46
-rw-r--r--src/ativgaio.h56
-rw-r--r--src/atividmem.c381
-rw-r--r--src/atividmem.h75
-rw-r--r--src/atiwonder.c303
-rw-r--r--src/atiwonder.h42
-rw-r--r--src/atiwonderio.c86
-rw-r--r--src/atiwonderio.h48
-rw-r--r--src/atixv.c52
-rw-r--r--src/atixv.h35
-rw-r--r--src/r128.h554
-rw-r--r--src/r128_accel.c1806
-rw-r--r--src/r128_common.h170
-rw-r--r--src/r128_cursor.c263
-rw-r--r--src/r128_dga.c397
-rw-r--r--src/r128_dri.c1337
-rw-r--r--src/r128_dri.h102
-rw-r--r--src/r128_dripriv.h58
-rw-r--r--src/r128_driver.c3724
-rw-r--r--src/r128_misc.c87
-rw-r--r--src/r128_probe.c308
-rw-r--r--src/r128_probe.h78
-rw-r--r--src/r128_reg.h1510
-rw-r--r--src/r128_sarea.h201
-rw-r--r--src/r128_version.h60
-rw-r--r--src/r128_video.c1143
-rw-r--r--src/radeon.h750
-rw-r--r--src/radeon_accel.c607
-rw-r--r--src/radeon_accelfuncs.c1372
-rw-r--r--src/radeon_common.h432
-rw-r--r--src/radeon_cursor.c486
-rw-r--r--src/radeon_dga.c397
-rw-r--r--src/radeon_dri.c1861
-rw-r--r--src/radeon_dri.h107
-rw-r--r--src/radeon_dripriv.h64
-rw-r--r--src/radeon_driver.c5944
-rw-r--r--src/radeon_macros.h134
-rw-r--r--src/radeon_misc.c86
-rw-r--r--src/radeon_probe.c333
-rw-r--r--src/radeon_probe.h96
-rw-r--r--src/radeon_reg.h1998
-rw-r--r--src/radeon_sarea.h237
-rw-r--r--src/radeon_version.h63
-rw-r--r--src/radeon_video.c1586
112 files changed, 52379 insertions, 0 deletions
diff --git a/src/ati.c b/src/ati.c
new file mode 100644
index 0000000..3928b8b
--- /dev/null
+++ b/src/ati.c
@@ -0,0 +1,72 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ati.c,v 1.21 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*************************************************************************/
+
+/*
+ * Author: Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * This is the ATI driver for XFree86.
+ *
+ * John Donne once said "No man is an island", and I am most certainly not an
+ * exception. Contributions, intentional or not, to this and previous versions
+ * of this driver by the following are hereby acknowledged:
+ *
+ * Thomas Roell, Per Lindqvist, Doug Evans, Rik Faith, Arthur Tateishi,
+ * Alain Hebert, Ton van Rosmalen, David Chambers, William Shubert,
+ * ATI Technologies Incorporated, Robert Wolff, David Dawes, Mark Weaver,
+ * Hans Nasten, Kevin Martin, Frederic Rienthaler, Marc Bolduc, Reuben Sumner,
+ * Benjamin T. Yang, James Fast Kane, Randall Hopper, W. Marcus Miller,
+ * Henrik Harmsen, Christian Lupien, Precision Insight Incorporated,
+ * Mark Vojkovich, Huw D M Davies, Andrew C Aitchison, Ani Joshi,
+ * Kostas Gewrgiou, Jakub Jelinek, David S. Miller, A E Lawrence,
+ * Linus Torvalds, William Blew, Ignacio Garcia Etxebarria, Patrick Chase,
+ * Vladimir Dergachev
+ *
+ * ... and, many, many others from around the world.
+ *
+ * In addition, this work would not have been possible without the active
+ * support, both moral and otherwise, of the staff and management of Computing
+ * and Network Services at the University of Alberta, in Edmonton, Alberta,
+ * Canada.
+ *
+ * The driver is intended to support all ATI adapters since their VGA Wonder
+ * V3, including OEM counterparts.
+ */
+
+#include "atiident.h"
+#include "atioption.h"
+#include "atiprobe.h"
+#include "ativersion.h"
+
+/* The root of all evil... */
+DriverRec ATI =
+{
+ ATI_VERSION_CURRENT,
+ "ati",
+ ATIIdentify,
+ ATIProbe,
+ ATIAvailableOptions,
+ NULL,
+ 0
+};
diff --git a/src/ati.h b/src/ati.h
new file mode 100644
index 0000000..3861a9e
--- /dev/null
+++ b/src/ati.h
@@ -0,0 +1,37 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ati.h,v 1.9 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATI_H___
+#define ___ATI_H___ 1
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "xf86.h"
+
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+
+extern DriverRec ATI;
+
+#endif /* ___ATI_H___ */
diff --git a/src/atiaccel.c b/src/atiaccel.c
new file mode 100644
index 0000000..70b7e35
--- /dev/null
+++ b/src/atiaccel.c
@@ -0,0 +1,81 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.c,v 1.11 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiaccel.h"
+#include "atiadapter.h"
+#include "atimach64.h"
+#include "atistruct.h"
+
+/*
+ * ATIInitializeAcceleration --
+ *
+ * This function is called to initialise both the framebuffer manager and XAA
+ * on a screen.
+ */
+Bool
+ATIInitializeAcceleration
+(
+ ScreenPtr pScreen,
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ int maxScanlines = 32767, maxPixelArea, PixelArea;
+
+ if (pATI->OptionAccel)
+ {
+ if (!(pATI->pXAAInfo = XAACreateInfoRec()))
+ return FALSE;
+
+ switch (pATI->Adapter)
+ {
+ case ATI_ADAPTER_MACH64:
+ maxScanlines = ATIMach64AccelInit(pATI, pATI->pXAAInfo);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ if (!pATI->BankInfo.BankSize)
+
+#endif /* AVOID_CPIO */
+
+ {
+ maxPixelArea = maxScanlines * pScreenInfo->displayWidth;
+ PixelArea = pScreenInfo->videoRam * 1024 * 8 / pATI->bitsPerPixel;
+ if (PixelArea > maxPixelArea)
+ PixelArea = maxPixelArea;
+ xf86InitFBManagerArea(pScreen, PixelArea, 2);
+ }
+
+ if (!pATI->OptionAccel || XAAInit(pScreen, pATI->pXAAInfo))
+ return TRUE;
+
+ XAADestroyInfoRec(pATI->pXAAInfo);
+ pATI->pXAAInfo = NULL;
+ return FALSE;
+}
diff --git a/src/atiaccel.h b/src/atiaccel.h
new file mode 100644
index 0000000..df59ab0
--- /dev/null
+++ b/src/atiaccel.h
@@ -0,0 +1,36 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.h,v 1.4 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIACCEL_H___
+#define ___ATIACCEL_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIInitializeAcceleration FunctionPrototype((ScreenPtr,
+ ScrnInfoPtr,
+ ATIPtr));
+
+#endif /* ___ATIACCEL_H___ */
diff --git a/src/atiadapter.c b/src/atiadapter.c
new file mode 100644
index 0000000..897788b
--- /dev/null
+++ b/src/atiadapter.c
@@ -0,0 +1,54 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadapter.c,v 1.17 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiadapter.h"
+
+/*
+ * Adapter-related definitions.
+ */
+const char *ATIAdapterNames[] =
+{
+ "Unknown",
+
+#ifndef AVOID_CPIO
+
+ "ATI EGA Wonder800",
+ "ATI EGA Wonder800+",
+ "IBM VGA or compatible",
+ "ATI VGA Basic16",
+ "ATI VGA Wonder V3",
+ "ATI VGA Wonder V4",
+ "ATI VGA Wonder V5",
+ "ATI VGA Wonder+",
+ "ATI VGA Wonder XL or XL24",
+ "ATI VGA Wonder VLB or PCI",
+ "IBM 8514/A or compatible",
+ "ATI Mach8",
+ "ATI Mach32",
+
+#endif /* AVOID_CPIO */
+
+ "ATI Mach64",
+ "ATI Rage128",
+ "ATI Radeon"
+};
diff --git a/src/atiadapter.h b/src/atiadapter.h
new file mode 100644
index 0000000..8db366e
--- /dev/null
+++ b/src/atiadapter.h
@@ -0,0 +1,60 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadapter.h,v 1.10 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIADAPTER_H___
+#define ___ATIADAPTER_H___ 1
+
+/*
+ * Adapter-related definitions.
+ */
+typedef enum
+{
+ ATI_ADAPTER_NONE = 0,
+
+#ifndef AVOID_CPIO
+
+ ATI_ADAPTER_EGA,
+ ATI_ADAPTER_EGA_PLUS,
+ ATI_ADAPTER_VGA,
+ ATI_ADAPTER_BASIC,
+ ATI_ADAPTER_V3,
+ ATI_ADAPTER_V4,
+ ATI_ADAPTER_V5,
+ ATI_ADAPTER_PLUS,
+ ATI_ADAPTER_XL,
+ ATI_ADAPTER_NONISA,
+ ATI_ADAPTER_8514A,
+ ATI_ADAPTER_MACH8,
+ ATI_ADAPTER_MACH32,
+
+#endif /* AVOID_CPIO */
+
+ ATI_ADAPTER_MACH64,
+ ATI_ADAPTER_RAGE128,
+ ATI_ADAPTER_RADEON,
+ ATI_ADAPTER_MAX /* Must be last */
+} ATIAdapterType;
+
+extern const char *ATIAdapterNames[];
+
+#endif /* ___ATIADAPTER_H___ */
diff --git a/src/atiadjust.c b/src/atiadjust.c
new file mode 100644
index 0000000..df2ac64
--- /dev/null
+++ b/src/atiadjust.c
@@ -0,0 +1,224 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadjust.c,v 1.14 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadjust.h"
+#include "atichip.h"
+#include "aticrtc.h"
+#include "atilock.h"
+#include "atimach64io.h"
+#include "atiwonderio.h"
+
+/*
+ * The display start address is expressed in units of 32-bit (VGA) or 64-bit
+ * (accelerator) words where all planar modes are considered as 4bpp modes.
+ * These functions ensure the start address does not exceed architectural
+ * limits. Also, to avoid colour changes while panning, these 32-bit or 64-bit
+ * boundaries may not fall within a pixel.
+ */
+
+/*
+ * ATIAjustPreInit --
+ *
+ * This function calculates values needed to speed up the setting of the
+ * display start address.
+ */
+void
+ATIAdjustPreInit
+(
+ ATIPtr pATI
+)
+{
+ unsigned long MaxBase;
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->CPIO_VGAWonder) &&
+ (pATI->Chip <= ATI_CHIP_18800_1) &&
+ (pATI->VideoRAM == 256) &&
+ (pATI->depth >= 8))
+ {
+ /* Strange, to say the least ... */
+ pATI->AdjustDepth = (pATI->bitsPerPixel + 3) >> 2;
+ pATI->AdjustMask = (unsigned long)(-32);
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->AdjustDepth = (pATI->bitsPerPixel + 7) >> 3;
+
+ pATI->AdjustMask = 64;
+ while (pATI->AdjustMask % (unsigned long)(pATI->AdjustDepth))
+ pATI->AdjustMask += 64;
+ pATI->AdjustMask =
+ ~(((pATI->AdjustMask / (unsigned long)(pATI->AdjustDepth)) >> 3) -
+ 1);
+ }
+
+ switch (pATI->NewHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ pATI->AdjustMaxBase = MaxBits(CRTC_OFFSET_VGA) << 2;
+ if (pATI->depth <= 4)
+ pATI->AdjustMaxBase <<= 1;
+ }
+ else if (!pATI->CPIO_VGAWonder)
+ pATI->AdjustMaxBase = 0xFFFFU << 3;
+ else if (pATI->Chip <= ATI_CHIP_28800_6)
+ pATI->AdjustMaxBase = 0x03FFFFU << 3;
+ else /* Mach32 & Mach64 */
+ pATI->AdjustMaxBase = 0x0FFFFFU << 3;
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ pATI->AdjustMaxBase = MaxBits(CRTC_OFFSET) << 3;
+ break;
+
+ default:
+ pATI->AdjustMaxBase = 0;
+ break;
+ }
+
+ MaxBase = (pATI->AdjustMaxBase / (unsigned long)pATI->AdjustDepth) |
+ ~pATI->AdjustMask;
+
+ pATI->AdjustMaxX = MaxBase % pATI->displayWidth;
+ pATI->AdjustMaxY = MaxBase / pATI->displayWidth;
+}
+
+/*
+ * ATIAdjustFrame --
+ *
+ * This function is used to initialise the SVGA Start Address - the first
+ * displayed location in video memory. This is used to implement the virtual
+ * window.
+ */
+void
+ATIAdjustFrame
+(
+ int scrnIndex,
+ int x,
+ int y,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[scrnIndex];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ int Base, xy;
+
+ /*
+ * Assume the caller has already done its homework in ensuring the physical
+ * screen is still contained in the virtual resolution.
+ */
+ if (y >= pATI->AdjustMaxY)
+ {
+ y = pATI->AdjustMaxY;
+ if (x > pATI->AdjustMaxX)
+ y--;
+ }
+
+ Base = ((((y * pATI->displayWidth) + x) & pATI->AdjustMask) *
+ pATI->AdjustDepth) >> 3;
+
+ if (!pATI->currentMode)
+ {
+ /*
+ * Not in DGA. This reverse-calculates pScreenInfo->frame[XY][01] so
+ * that the cursor does not move on mode switches.
+ */
+ xy = (Base << 3) / pATI->AdjustDepth;
+ pScreenInfo->frameX0 = xy % pATI->displayWidth;
+ pScreenInfo->frameY0 = xy / pATI->displayWidth;
+ pScreenInfo->frameX1 =
+ pScreenInfo->frameX0 + pScreenInfo->currentMode->HDisplay - 1;
+ pScreenInfo->frameY1 =
+ pScreenInfo->frameY0 + pScreenInfo->currentMode->VDisplay - 1;
+ }
+
+ /* Unlock registers */
+ ATIUnlock(pATI);
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->NewHW.crtc == ATI_CRTC_VGA) && (pATI->Chip < ATI_CHIP_264CT))
+ {
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x0CU, GetByte(Base, 1));
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x0DU, GetByte(Base, 0));
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ if (pATI->Chip <= ATI_CHIP_18800_1)
+ ATIModifyExtReg(pATI, 0xB0U, -1, 0x3FU, Base >> 10);
+ else
+ {
+ ATIModifyExtReg(pATI, 0xB0U, -1, 0xBFU, Base >> 10);
+ ATIModifyExtReg(pATI, 0xA3U, -1, 0xEFU, Base >> 13);
+
+ /*
+ * I don't know if this also applies to Mach64's, but give it a
+ * shot...
+ */
+ if (pATI->Chip >= ATI_CHIP_68800)
+ ATIModifyExtReg(pATI, 0xADU, -1, 0xF3U, Base >> 16);
+ }
+ }
+ }
+ else
+ /*
+ * On integrated controllers, there is only one set of CRTC control bits,
+ * many of which are simultaneously accessible through both VGA and
+ * accelerator I/O ports. Given VGA's architectural limitations, setting
+ * the CRTC's offset register to more than 256k needs to be done through
+ * the accelerator port.
+ */
+ if (pATI->depth <= 4)
+ {
+ outr(CRTC_OFF_PITCH, SetBits(pATI->displayWidth >> 4, CRTC_PITCH) |
+ SetBits(Base, CRTC_OFFSET));
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ Base <<= 1; /* LSBit must be zero */
+
+#endif /* AVOID_CPIO */
+
+ outr(CRTC_OFF_PITCH, SetBits(pATI->displayWidth >> 3, CRTC_PITCH) |
+ SetBits(Base, CRTC_OFFSET));
+ }
+}
diff --git a/src/atiadjust.h b/src/atiadjust.h
new file mode 100644
index 0000000..0ac15ae
--- /dev/null
+++ b/src/atiadjust.h
@@ -0,0 +1,33 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadjust.h,v 1.8 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIADJUST_H___
+#define ___ATIADJUST_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+extern void ATIAdjustPreInit FunctionPrototype((ATIPtr));
+extern void ATIAdjustFrame FunctionPrototype((int, int, int, int));
+
+#endif /* ___ATIADJUST_H___ */
diff --git a/src/atibank.c b/src/atibank.c
new file mode 100644
index 0000000..82d591a
--- /dev/null
+++ b/src/atibank.c
@@ -0,0 +1,409 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atibank.c,v 1.12 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atibank.h"
+#include "atimach64io.h"
+#include "atiwonderio.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATI VGA Wonder V3 adapters use an ATI 18800 chip and are single-banked.
+ * Bank selection is done with bits 0x1E of ATI extended VGA register index
+ * 0xB2.
+ */
+
+/*
+ * ATIV3SetBank --
+ *
+ * Set an ATI 18800's bank number.
+ */
+void
+ATIV3SetBank
+(
+ ATIPtr pATI,
+ unsigned int iBank
+)
+{
+ ATIModifyExtReg(pATI, 0xB2U, -1, (CARD8)(~0x1EU), SetBits(iBank, 0x1EU));
+}
+
+/*
+ * ATIV3SetReadWrite --
+ *
+ * Set an ATI 18800's bank number.
+ */
+int
+ATIV3SetReadWrite
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+
+ ATIModifyExtReg(pATI, 0xB2U, -1, (CARD8)(~0x1EU), SetBits(iBank, 0x1EU));
+ return 0;
+}
+
+/*
+ * ATI VGA Wonder V4 and V5 adapters use an ATI 18800-1 chip. Bank selection
+ * is done with ATI extended VGA register index 0xB2. The format is:
+ *
+ * 0xE0 - Read bank select bits 0x07
+ * 0x1E - Write bank select bits 0x0F
+ * 0x01 - Read bank select bit 0x08.
+ */
+
+/*
+ * ATIV4V5SetBank --
+ *
+ * Set an ATI 18800-1's read and write bank numbers.
+ */
+void
+ATIV4V5SetBank
+(
+ ATIPtr pATI,
+ unsigned int iBank
+)
+{
+ pATI->B2Reg = SetBits(iBank, 0x1EU) | SetBits(iBank, 0xE0U) |
+ SetBits(GetBits(iBank, 0x08U), 0x01U);
+ ATIPutExtReg(0xB2U, pATI->B2Reg);
+}
+
+/*
+ * ATIV4V5SetRead --
+ *
+ * Set an ATI 18800-1's read bank number.
+ */
+int
+ATIV4V5SetRead
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+ CARD8 B2Reg = (pATI->B2Reg & 0x1EU) | SetBits(iBank, 0xE0U) |
+ SetBits(GetBits(iBank, 0x08U), 0x01U);
+
+ if (B2Reg != pATI->B2Reg)
+ {
+ ATIPutExtReg(0xB2U, B2Reg);
+ pATI->B2Reg = B2Reg;
+ }
+
+ return 0;
+}
+
+/*
+ * ATIV4V5SetWrite --
+ *
+ * Set an ATI 18800-1's write bank number.
+ */
+int
+ATIV4V5SetWrite
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+ CARD8 B2Reg = (pATI->B2Reg & 0xE1U) | SetBits(iBank, 0x1EU);
+
+ if (B2Reg != pATI->B2Reg)
+ {
+ ATIPutExtReg(0xB2U, B2Reg);
+ pATI->B2Reg = B2Reg;
+ }
+ return 0;
+}
+
+/*
+ * ATIV4V5SetReadWrite --
+ *
+ * Set an ATI 18800-1's read and write bank numbers.
+ */
+int
+ATIV4V5SetReadWrite
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIV4V5SetBank(ATIPTR(XF86SCRNINFO(pScreen)), iBank);
+ return 0;
+}
+
+/*
+ * In addition to ATI extended register index 0xB2, 28800's, 68800's and
+ * 88800's define banking bits in bits 0x0F of ATI extended VGA register index
+ * 0xAE. These are only needed for adapters with more than 1MB of video
+ * memory, and it is questionable whether or not they are actually implemented
+ * by 28800's and 88800's. ATI extended VGA register index 0xAE is defined as
+ * follows:
+ *
+ * 0xF0 - reserved
+ * 0x0C - read bank select bits 0x30
+ * 0x03 - write bank select bits 0x30
+ */
+
+/*
+ * ATIx8800SetBank --
+ *
+ * Set an ATI 28800's, 68800's or 88800's read and write bank numbers.
+ */
+void
+ATIx8800SetBank
+(
+ ATIPtr pATI,
+ unsigned int iBank
+)
+{
+ ATIV4V5SetBank(pATI, iBank);
+ iBank = GetBits(iBank, 0x30U);
+ ATIModifyExtReg(pATI, 0xAEU, -1, (CARD8)(~0x0FU),
+ SetBits(iBank, 0x03U) | SetBits(iBank, 0x0CU));
+}
+
+/*
+ * ATIx8800SetRead --
+ *
+ * Set an ATI 28800's, 68800's or 88800's read bank numbers.
+ */
+int
+ATIx8800SetRead
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ (void)ATIV4V5SetRead(pScreen, iBank);
+ ATIModifyExtReg(ATIPTR(XF86SCRNINFO(pScreen)), 0xAEU, -1, (CARD8)(~0x0CU),
+ SetBits(GetBits(iBank, 0x30U), 0x0CU));
+ return 0;
+}
+
+/*
+ * ATIx8800SetWrite --
+ *
+ * Set an ATI 28800's, 68800's or 88800's write bank numbers.
+ */
+int
+ATIx8800SetWrite
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ (void)ATIV4V5SetWrite(pScreen, iBank);
+ ATIModifyExtReg(ATIPTR(XF86SCRNINFO(pScreen)), 0xAEU, -1, (CARD8)(~0x03U),
+ SetBits(GetBits(iBank, 0x30U), 0x03U));
+ return 0;
+}
+
+/*
+ * ATIx8800SetReadWrite --
+ *
+ * Set an ATI 28800's, 68800's or 88800's read and write bank numbers.
+ */
+int
+ATIx8800SetReadWrite
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIx8800SetBank(ATIPTR(XF86SCRNINFO(pScreen)), iBank);
+ return 0;
+}
+
+/*
+ * Functions to simulate a banked VGA aperture using a Mach64's small dual
+ * paged apertures. There are two sets of these: one for packed modes, the
+ * other for planar modes.
+ */
+
+static CARD32
+ATIMach64MassagePackedBankNumber
+(
+ CARD8 iBank
+)
+{
+ iBank <<= 1;
+ return ((iBank + 1) << 16) | iBank;
+}
+
+/*
+ * ATIMach64SetBankPacked --
+ *
+ * Set read and write bank numbers for small dual paged apertures.
+ */
+void
+ATIMach64SetBankPacked
+(
+ ATIPtr pATI,
+ unsigned int iBank
+)
+{
+ CARD32 tmp = ATIMach64MassagePackedBankNumber(iBank);
+
+ outr(MEM_VGA_RP_SEL, tmp);
+ outr(MEM_VGA_WP_SEL, tmp);
+}
+
+/*
+ * ATIMach64SetReadPacked --
+ *
+ * Set read bank number for small dual paged apertures.
+ */
+int
+ATIMach64SetReadPacked
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+
+ outr(MEM_VGA_RP_SEL, ATIMach64MassagePackedBankNumber(iBank));
+ return 0;
+}
+
+/*
+ * ATIMach64SetWritePacked --
+ *
+ * Set write bank number for small dual paged apertures.
+ */
+int
+ATIMach64SetWritePacked
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+
+ outr(MEM_VGA_WP_SEL, ATIMach64MassagePackedBankNumber(iBank));
+ return 0;
+}
+
+/*
+ * ATIMach64SetReadWritePacked --
+ *
+ * Set read and write bank numbers for small dual paged apertures.
+ */
+int
+ATIMach64SetReadWritePacked
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIMach64SetBankPacked(ATIPTR(XF86SCRNINFO(pScreen)), iBank);
+ return 0;
+}
+
+static CARD32
+ATIMach64MassagePlanarBankNumber
+(
+ CARD8 iBank
+)
+{
+ iBank <<= 3;
+ return ((iBank + 4) << 16) | iBank;
+}
+
+/*
+ * ATIMach64SetBankPlanar --
+ *
+ * Set read and write bank numbers for small dual paged apertures.
+ */
+void
+ATIMach64SetBankPlanar
+(
+ ATIPtr pATI,
+ unsigned int iBank
+)
+{
+ CARD32 tmp = ATIMach64MassagePlanarBankNumber(iBank);
+
+ outr(MEM_VGA_RP_SEL, tmp);
+ outr(MEM_VGA_WP_SEL, tmp);
+}
+
+/*
+ * ATIMach64SetReadPlanar --
+ *
+ * Set read bank number for small dual paged apertures.
+ */
+int
+ATIMach64SetReadPlanar
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+
+ outr(MEM_VGA_RP_SEL, ATIMach64MassagePlanarBankNumber(iBank));
+ return 0;
+}
+
+/*
+ * ATIMach64SetWritePlanar --
+ *
+ * Set write bank number for small dual paged apertures.
+ */
+int
+ATIMach64SetWritePlanar
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIPtr pATI = ATIPTR(XF86SCRNINFO(pScreen));
+
+ outr(MEM_VGA_WP_SEL, ATIMach64MassagePlanarBankNumber(iBank));
+ return 0;
+}
+
+/*
+ * ATIMach64SetReadWritePlanar --
+ *
+ * Set read and write bank numbers for small dual paged apertures.
+ */
+int
+ATIMach64SetReadWritePlanar
+(
+ ScreenPtr pScreen,
+ unsigned int iBank
+)
+{
+ ATIMach64SetBankPlanar(ATIPTR(XF86SCRNINFO(pScreen)), iBank);
+ return 0;
+}
+
+#endif /* AVOID_CPIO */
diff --git a/src/atibank.h b/src/atibank.h
new file mode 100644
index 0000000..43a91ac
--- /dev/null
+++ b/src/atibank.h
@@ -0,0 +1,88 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atibank.h,v 1.8 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIBANK_H___
+#define ___ATIBANK_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "mibank.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * Banking definitions.
+ */
+
+/*
+ * Bank selection function for VGA Wonder V3 adapters (which are
+ * single-banked).
+ */
+#define ATIV3SetRead ATIV3SetReadWrite
+#define ATIV3SetWrite ATIV3SetReadWrite
+extern miBankProc ATIV3SetReadWrite;
+
+/*
+ * Bank selection functions for VGA Wonder V4 and V5 adapters.
+ */
+extern miBankProc ATIV4V5SetRead,
+ ATIV4V5SetWrite,
+ ATIV4V5SetReadWrite;
+
+/*
+ * Bank selection functions for 28800-x, 68800-x and 88800 based adapters.
+ */
+extern miBankProc ATIx8800SetRead,
+ ATIx8800SetWrite,
+ ATIx8800SetReadWrite;
+
+/*
+ * Bank selection functions used to simulate a banked VGA aperture with a
+ * Mach64's small dual paged apertures. There are two sets of these: one for
+ * packed modes, and one for planar modes.
+ */
+extern miBankProc ATIMach64SetReadPacked,
+ ATIMach64SetWritePacked,
+ ATIMach64SetReadWritePacked;
+extern miBankProc ATIMach64SetReadPlanar,
+ ATIMach64SetWritePlanar,
+ ATIMach64SetReadWritePlanar;
+
+/*
+ * The CRT save/restore code also needs a separate banking interface that can
+ * used before ATIScreenInit() is called.
+ */
+
+typedef void ATIBankProc FunctionPrototype((ATIPtr, unsigned int));
+typedef ATIBankProc *ATIBankProcPtr;
+
+extern ATIBankProc ATIV3SetBank,
+ ATIV4V5SetBank,
+ ATIx8800SetBank,
+ ATIMach64SetBankPacked,
+ ATIMach64SetBankPlanar;
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIBANK_H___ */
diff --git a/src/atibus.c b/src/atibus.c
new file mode 100644
index 0000000..c06c696
--- /dev/null
+++ b/src/atibus.c
@@ -0,0 +1,183 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atibus.c,v 1.18 2003/01/22 21:44:10 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atibus.h"
+#include "atichip.h"
+#include "atiio.h"
+#include "atistruct.h"
+#include "ativersion.h"
+
+/*
+ * Definitions related to an adapter's system bus interface.
+ */
+
+const char *ATIBusNames[] =
+{
+ "16-Bit ISA",
+ "EISA",
+ "16-Bit MicroChannel",
+ "32-Bit MicroChannel",
+ "386SX Local Bus",
+ "386DX Local Bus",
+ "VESA Local Bus",
+ "PCI",
+ "AGP"
+};
+
+/*
+ * ATIClaimResources --
+ *
+ * This function registers most of the bus resources used by an adapter. The
+ * exceptions are PCI-configured resources and non-PCI non-AGP linear
+ * apertures, both of which are registered by ATIPreInit(). This function also
+ * attempts to register unshareable resources for inactive PCI adapters,
+ * whether or not they are relocatable.
+ */
+static void
+ATIClaimResources
+(
+ ATIPtr pATI,
+ Bool Active
+)
+{
+ resPtr pResources;
+
+#ifndef AVOID_CPIO
+
+ resRange Resources[2] = {{0, 0, 0}, _END};
+
+ /* Claim VGA and VGAWonder resources */
+ if ((pATI->VGAAdapter != ATI_ADAPTER_NONE) && (Active || !pATI->SharedVGA))
+ {
+ /*
+ * 18800-x's are the only ATI controllers that decode all ISA aliases
+ * of VGA and VGA Wonder I/O ports. Other x8800's do not decode >any<
+ * VGA aliases, but do decode VGA Wonder aliases whose most significant
+ * nibble is zero.
+ */
+ xf86ClaimFixedResources(
+ (pATI->Chip <= ATI_CHIP_18800_1) ?
+ (pATI->SharedVGA ? resVgaSparseShared : resVgaSparseExclusive) :
+ (pATI->SharedVGA ? resVgaShared : resVgaExclusive),
+ pATI->iEntity);
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ if (pATI->SharedVGA)
+ Resources[0].type = ResShrIoSparse | ResBus;
+ else
+ Resources[0].type = ResExcIoSparse | ResBus;
+ Resources[0].rBase = pATI->CPIO_VGAWonder;
+ if (pATI->Chip <= ATI_CHIP_18800_1)
+ Resources[0].rMask = 0x03FEU;
+ else
+ Resources[0].rMask = 0xF3FEU;
+
+ xf86ClaimFixedResources(Resources, pATI->iEntity);
+
+ (void)memcpy(pATI->VGAWonderResources,
+ Resources, SizeOf(Resources));
+ }
+ }
+
+ if (!Active && pATI->SharedAccelerator)
+ return;
+
+ /* Claim 8514/A resources */
+ if (pATI->ChipHasSUBSYS_CNTL)
+ xf86ClaimFixedResources(
+ pATI->SharedAccelerator ? res8514Shared : res8514Exclusive,
+ pATI->iEntity);
+
+ /* Claim Mach64 sparse I/O resources */
+ if ((pATI->Adapter == ATI_ADAPTER_MACH64) &&
+ (pATI->CPIODecoding == SPARSE_IO))
+ {
+ if (pATI->SharedAccelerator)
+ Resources[0].type = ResShrIoSparse | ResBus;
+ else
+ Resources[0].type = ResExcIoSparse | ResBus;
+ Resources[0].rBase = pATI->CPIOBase;
+ Resources[0].rMask = 0x03FCU;
+
+ xf86ClaimFixedResources(Resources, pATI->iEntity);
+ }
+
+ if (Active)
+ return;
+
+#else /* AVOID_CPIO */
+
+ if (pATI->SharedAccelerator)
+ return;
+
+#endif /* AVOID_CPIO */
+
+ /* Register unshared relocatable resources for inactive adapters */
+ do
+ {
+ pResources = xf86RegisterResources(pATI->iEntity, NULL, ResExclusive);
+ if (!pResources)
+ return;
+
+ pResources = xf86ReallocatePciResources(pATI->iEntity, pResources);
+ } while (!pResources);
+
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Unable to register the following resources for inactive"
+ " adapter:\n");
+ xf86PrintResList(1, pResources);
+ xf86FreeResList(pResources);
+}
+
+/*
+ * ATIClaimBusSlot --
+ *
+ * Claim an adapter and register its resources.
+ */
+int
+ATIClaimBusSlot
+(
+ DriverPtr pDriver,
+ int Chipset,
+ GDevPtr pGDev,
+ Bool Active,
+ ATIPtr pATI
+)
+{
+ pciVideoPtr pVideo = pATI->PCIInfo;
+
+ if (pVideo)
+ pATI->iEntity =
+ xf86ClaimPciSlot(pVideo->bus, pVideo->device, pVideo->func,
+ pDriver, Chipset, pGDev, Active);
+ else
+ pATI->iEntity = xf86ClaimIsaSlot(pDriver, Chipset, pGDev, Active);
+
+ if (pATI->iEntity >= 0)
+ ATIClaimResources(pATI, Active);
+
+ return pATI->iEntity;
+}
diff --git a/src/atibus.h b/src/atibus.h
new file mode 100644
index 0000000..c5f35e0
--- /dev/null
+++ b/src/atibus.h
@@ -0,0 +1,59 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atibus.h,v 1.11 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIBUS_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error missing #include "ati.h" before #include "atibus.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIBUS_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+/*
+ * Definitions related to an adapter's system bus interface.
+ */
+typedef enum
+{
+ ATI_BUS_ISA = 0,
+ ATI_BUS_EISA,
+ ATI_BUS_MCA16,
+ ATI_BUS_MCA32,
+ ATI_BUS_SXLB,
+ ATI_BUS_DXLB,
+ ATI_BUS_VLB,
+ ATI_BUS_PCI,
+ ATI_BUS_AGP
+} ATIBusType;
+
+extern const char *ATIBusNames[];
+
+extern int ATIClaimBusSlot FunctionPrototype((DriverPtr, int, GDevPtr, Bool,
+ ATIPtr));
+
+#endif /* ___ATIBUS_H___ */
diff --git a/src/atichip.c b/src/atichip.c
new file mode 100644
index 0000000..c27ca1f
--- /dev/null
+++ b/src/atichip.c
@@ -0,0 +1,688 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.33 2003/02/19 15:07:46 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atibus.h"
+#include "atichip.h"
+#include "atimach64io.h"
+#include "ativersion.h"
+
+/*
+ * Chip-related definitions.
+ */
+const char *ATIChipNames[] =
+{
+ "Unknown",
+
+#ifndef AVOID_CPIO
+
+ "IBM VGA or compatible",
+ "ATI 18800",
+ "ATI 18800-1",
+ "ATI 28800-2",
+ "ATI 28800-4",
+ "ATI 28800-5",
+ "ATI 28800-6",
+ "IBM 8514/A",
+ "Chips & Technologies 82C480",
+ "ATI 38800-1",
+ "ATI 68800",
+ "ATI 68800-3",
+ "ATI 68800-6",
+ "ATI 68800LX",
+ "ATI 68800AX",
+
+#endif /* AVOID_CPIO */
+
+ "ATI 88800GX-C",
+ "ATI 88800GX-D",
+ "ATI 88800GX-E",
+ "ATI 88800GX-F",
+ "ATI 88800GX",
+ "ATI 88800CX",
+ "ATI 264CT",
+ "ATI 264ET",
+ "ATI 264VT",
+ "ATI 3D Rage",
+ "ATI 264VT-B",
+ "ATI 3D Rage II",
+ "ATI 264VT3",
+ "ATI 3D Rage II+DVD",
+ "ATI 3D Rage LT",
+ "ATI 264VT4",
+ "ATI 3D Rage IIc",
+ "ATI 3D Rage Pro",
+ "ATI 3D Rage LT Pro",
+ "ATI 3D Rage XL or XC",
+ "ATI 3D Rage Mobility",
+ "ATI unknown Mach64",
+ "ATI Rage 128 GL",
+ "ATI Rage 128 VR",
+ "ATI Rage 128 Pro GL",
+ "ATI Rage 128 Pro VR",
+ "ATI Rage 128 Pro ULTRA",
+ "ATI Rage 128 Mobility M3",
+ "ATI Rage 128 Mobility M4",
+ "ATI unknown Rage 128"
+ "ATI Radeon",
+ "ATI Radeon VE",
+ "ATI Radeon Mobility M6",
+ "ATI Radeon Mobility M7",
+ "ATI Radeon 8500",
+ "ATI Radeon 7500",
+ "ATI Radeon 9000",
+ "ATI Radeon Mobility M9",
+ "ATI Radeon 9700",
+ "ATI Rage HDTV"
+};
+
+const char *ATIFoundryNames[] =
+ { "SGS", "NEC", "KCS", "UMC", "TSMC", "5", "6", "UMC" };
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIMach32ChipID --
+ *
+ * Set variables whose value is dependent upon an 68800's CHIP_ID register.
+ */
+void
+ATIMach32ChipID
+(
+ ATIPtr pATI
+)
+{
+ CARD16 IOValue = inw(CHIP_ID);
+ pATI->ChipType = GetBits(IOValue, CHIP_CODE_0 | CHIP_CODE_1);
+ pATI->ChipClass = GetBits(IOValue, CHIP_CLASS);
+ pATI->ChipRevision = GetBits(IOValue, CHIP_REV);
+ pATI->ChipRev = pATI->ChipRevision;
+ if (IOValue == 0xFFFFU)
+ IOValue = 0;
+ switch (GetBits(IOValue, CHIP_CODE_0 | CHIP_CODE_1))
+ {
+ case OldChipID('A', 'A'):
+ pATI->Chip = ATI_CHIP_68800_3;
+ break;
+
+ case OldChipID('X', 'X'):
+ pATI->Chip = ATI_CHIP_68800_6;
+ break;
+
+ case OldChipID('L', 'X'):
+ pATI->Chip = ATI_CHIP_68800LX;
+ break;
+
+ case OldChipID('A', 'X'):
+ pATI->Chip = ATI_CHIP_68800AX;
+ break;
+
+ default:
+ pATI->Chip = ATI_CHIP_68800;
+ break;
+ }
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIMach64ChipID --
+ *
+ * Set variables whose value is dependent upon a Mach64's CONFIG_CHIP_ID
+ * register.
+ */
+void
+ATIMach64ChipID
+(
+ ATIPtr pATI,
+ const CARD16 ExpectedChipType
+)
+{
+ pATI->config_chip_id = inr(CONFIG_CHIP_ID);
+ pATI->ChipType = GetBits(pATI->config_chip_id, 0xFFFFU);
+ pATI->ChipClass = GetBits(pATI->config_chip_id, CFG_CHIP_CLASS);
+ pATI->ChipRevision = GetBits(pATI->config_chip_id, CFG_CHIP_REV);
+ pATI->ChipVersion = GetBits(pATI->config_chip_id, CFG_CHIP_VERSION);
+ pATI->ChipFoundry = GetBits(pATI->config_chip_id, CFG_CHIP_FOUNDRY);
+ pATI->ChipRev = pATI->ChipRevision;
+ switch (pATI->ChipType)
+ {
+ case OldChipID('G', 'X'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'X'):
+ switch (pATI->ChipRevision)
+ {
+ case 0x00U:
+ pATI->Chip = ATI_CHIP_88800GXC;
+ break;
+
+ case 0x01U:
+ pATI->Chip = ATI_CHIP_88800GXD;
+ break;
+
+ case 0x02U:
+ pATI->Chip = ATI_CHIP_88800GXE;
+ break;
+
+ case 0x03U:
+ pATI->Chip = ATI_CHIP_88800GXF;
+ break;
+
+ default:
+ pATI->Chip = ATI_CHIP_88800GX;
+ break;
+ }
+ break;
+
+ case OldChipID('C', 'X'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('C', 'X'):
+ pATI->Chip = ATI_CHIP_88800CX;
+ break;
+
+ case OldChipID('C', 'T'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('C', 'T'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264CT;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('E', 'T'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('E', 'T'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264ET;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('V', 'T'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('V', 'T'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264VT;
+ pATI->BusType = ATI_BUS_PCI;
+ /* Some early GT's are detected as VT's */
+ if (ExpectedChipType && (pATI->ChipType != ExpectedChipType))
+ {
+ if (ExpectedChipType == NewChipID('G', 'T'))
+ pATI->Chip = ATI_CHIP_264GT;
+ else
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Mach64 chip type probe discrepancy"
+ " detected: PCI=0x%04X; CHIP_ID=0x%04X.\n",
+ ExpectedChipType, pATI->ChipType);
+ }
+ else if (pATI->ChipVersion)
+ pATI->Chip = ATI_CHIP_264VTB;
+ break;
+
+ case OldChipID('G', 'T'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'T'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->BusType = ATI_BUS_PCI;
+ if (!pATI->ChipVersion)
+ pATI->Chip = ATI_CHIP_264GT;
+ else
+ pATI->Chip = ATI_CHIP_264GTB;
+ break;
+
+ case OldChipID('V', 'U'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('V', 'U'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264VT3;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('G', 'U'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'U'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264GTDVD;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('L', 'G'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('L', 'G'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264LT;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('V', 'V'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('V', 'V'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264VT4;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('G', 'V'):
+ case OldChipID('G', 'Y'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'V'):
+ case NewChipID('G', 'Y'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264GT2C;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('G', 'W'):
+ case OldChipID('G', 'Z'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'W'):
+ case NewChipID('G', 'Z'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264GT2C;
+ pATI->BusType = ATI_BUS_AGP;
+ break;
+
+ case OldChipID('G', 'I'):
+ case OldChipID('G', 'P'):
+ case OldChipID('G', 'Q'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'I'):
+ case NewChipID('G', 'P'):
+ case NewChipID('G', 'Q'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264GTPRO;
+ pATI->BusType = ATI_BUS_PCI;
+ break;
+
+ case OldChipID('G', 'B'):
+ case OldChipID('G', 'D'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'B'):
+ case NewChipID('G', 'D'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264GTPRO;
+ pATI->BusType = ATI_BUS_AGP;
+ break;
+
+ case OldChipID('L', 'I'):
+ case OldChipID('L', 'P'):
+ case OldChipID('L', 'Q'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('L', 'I'):
+ case NewChipID('L', 'P'):
+ case NewChipID('L', 'Q'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264LTPRO;
+ pATI->BusType = ATI_BUS_PCI;
+ pATI->LCDVBlendFIFOSize = 800;
+ break;
+
+ case OldChipID('L', 'B'):
+ case OldChipID('L', 'D'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('L', 'B'):
+ case NewChipID('L', 'D'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264LTPRO;
+ pATI->BusType = ATI_BUS_AGP;
+ pATI->LCDVBlendFIFOSize = 800;
+ break;
+
+ case OldChipID('G', 'L'):
+ case OldChipID('G', 'O'):
+ case OldChipID('G', 'R'):
+ case OldChipID('G', 'S'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'L'):
+ case NewChipID('G', 'O'):
+ case NewChipID('G', 'R'):
+ case NewChipID('G', 'S'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264XL;
+ pATI->BusType = ATI_BUS_PCI;
+ pATI->LCDVBlendFIFOSize = 1024;
+ break;
+
+ case OldChipID('G', 'M'):
+ case OldChipID('G', 'N'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('G', 'M'):
+ case NewChipID('G', 'N'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_264XL;
+ pATI->BusType = ATI_BUS_AGP;
+ pATI->LCDVBlendFIFOSize = 1024;
+ break;
+
+ case OldChipID('L', 'R'):
+ case OldChipID('L', 'S'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('L', 'R'):
+ case NewChipID('L', 'S'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_MOBILITY;
+ pATI->BusType = ATI_BUS_PCI;
+ pATI->LCDVBlendFIFOSize = 1024;
+ break;
+
+ case OldChipID('L', 'M'):
+ case OldChipID('L', 'N'):
+ pATI->ChipType = OldToNewChipID(pATI->ChipType);
+ case NewChipID('L', 'M'):
+ case NewChipID('L', 'N'):
+ pATI->ChipRevision =
+ GetBits(pATI->config_chip_id, CFG_CHIP_REVISION);
+ pATI->Chip = ATI_CHIP_MOBILITY;
+ pATI->BusType = ATI_BUS_AGP;
+ pATI->LCDVBlendFIFOSize = 1024;
+ break;
+
+ default:
+ pATI->Chip = ATI_CHIP_Mach64;
+ break;
+ }
+}
+
+/*
+ * ATIChipID --
+ *
+ * This returns the ATI_CHIP_* value (generally) associated with a particular
+ * ChipID/ChipRev combination.
+ */
+ATIChipType
+ATIChipID
+(
+ const CARD16 ChipID,
+ const CARD8 ChipRev
+)
+{
+ switch (ChipID)
+ {
+
+#ifndef AVOID_CPIO
+
+ case OldChipID('A', 'A'): case NewChipID('A', 'A'):
+ return ATI_CHIP_68800_3;
+
+ case OldChipID('X', 'X'): case NewChipID('X', 'X'):
+ return ATI_CHIP_68800_6;
+
+ case OldChipID('L', 'X'):
+ return ATI_CHIP_68800LX;
+
+ case OldChipID('A', 'X'): case NewChipID('A', 'X'):
+ return ATI_CHIP_68800AX;
+
+#endif /* AVOID_CPIO */
+
+ case OldChipID('G', 'X'): case NewChipID('G', 'X'):
+ switch (ChipRev)
+ {
+ case 0x00U:
+ return ATI_CHIP_88800GXC;
+
+ case 0x01U:
+ return ATI_CHIP_88800GXD;
+
+ case 0x02U:
+ return ATI_CHIP_88800GXE;
+
+ case 0x03U:
+ return ATI_CHIP_88800GXF;
+
+ default:
+ return ATI_CHIP_88800GX;
+ }
+
+ case OldChipID('C', 'X'): case NewChipID('C', 'X'):
+ return ATI_CHIP_88800CX;
+
+ case OldChipID('C', 'T'): case NewChipID('C', 'T'):
+ return ATI_CHIP_264CT;
+
+ case OldChipID('E', 'T'): case NewChipID('E', 'T'):
+ return ATI_CHIP_264ET;
+
+ case OldChipID('V', 'T'): case NewChipID('V', 'T'):
+ /* For simplicity, ignore ChipID discrepancy that can occur here */
+ if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV)))
+ return ATI_CHIP_264VT;
+ return ATI_CHIP_264VTB;
+
+ case OldChipID('G', 'T'): case NewChipID('G', 'T'):
+ if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV)))
+ return ATI_CHIP_264GT;
+ return ATI_CHIP_264GTB;
+
+ case OldChipID('V', 'U'): case NewChipID('V', 'U'):
+ return ATI_CHIP_264VT3;
+
+ case OldChipID('G', 'U'): case NewChipID('G', 'U'):
+ return ATI_CHIP_264GTDVD;
+
+ case OldChipID('L', 'G'): case NewChipID('L', 'G'):
+ return ATI_CHIP_264LT;
+
+ case OldChipID('V', 'V'): case NewChipID('V', 'V'):
+ return ATI_CHIP_264VT4;
+
+ case OldChipID('G', 'V'): case NewChipID('G', 'V'):
+ case OldChipID('G', 'W'): case NewChipID('G', 'W'):
+ case OldChipID('G', 'Y'): case NewChipID('G', 'Y'):
+ case OldChipID('G', 'Z'): case NewChipID('G', 'Z'):
+ return ATI_CHIP_264GT2C;
+
+ case OldChipID('G', 'B'): case NewChipID('G', 'B'):
+ case OldChipID('G', 'D'): case NewChipID('G', 'D'):
+ case OldChipID('G', 'I'): case NewChipID('G', 'I'):
+ case OldChipID('G', 'P'): case NewChipID('G', 'P'):
+ case OldChipID('G', 'Q'): case NewChipID('G', 'Q'):
+ return ATI_CHIP_264GTPRO;
+
+ case OldChipID('L', 'B'): case NewChipID('L', 'B'):
+ case OldChipID('L', 'D'): case NewChipID('L', 'D'):
+ case OldChipID('L', 'I'): case NewChipID('L', 'I'):
+ case OldChipID('L', 'P'): case NewChipID('L', 'P'):
+ case OldChipID('L', 'Q'): case NewChipID('L', 'Q'):
+ return ATI_CHIP_264LTPRO;
+
+ case OldChipID('G', 'L'): case NewChipID('G', 'L'):
+ case OldChipID('G', 'M'): case NewChipID('G', 'M'):
+ case OldChipID('G', 'N'): case NewChipID('G', 'N'):
+ case OldChipID('G', 'O'): case NewChipID('G', 'O'):
+ case OldChipID('G', 'R'): case NewChipID('G', 'R'):
+ case OldChipID('G', 'S'): case NewChipID('G', 'S'):
+ return ATI_CHIP_264XL;
+
+ case OldChipID('L', 'M'): case NewChipID('L', 'M'):
+ case OldChipID('L', 'N'): case NewChipID('L', 'N'):
+ case OldChipID('L', 'R'): case NewChipID('L', 'R'):
+ case OldChipID('L', 'S'): case NewChipID('L', 'S'):
+ return ATI_CHIP_MOBILITY;
+
+ case NewChipID('R', 'E'):
+ case NewChipID('R', 'F'):
+ case NewChipID('R', 'G'):
+ case NewChipID('S', 'K'):
+ case NewChipID('S', 'L'):
+ case NewChipID('S', 'M'):
+ /* "SN" is listed as ATI_CHIP_RAGE128_4X in ATI docs */
+ case NewChipID('S', 'N'):
+ return ATI_CHIP_RAGE128GL;
+
+ case NewChipID('R', 'K'):
+ case NewChipID('R', 'L'):
+ /*
+ * ATI documentation lists SE/SF/SG under both ATI_CHIP_RAGE128VR
+ * and ATI_CHIP_RAGE128_4X, and lists SH/SK/SL under Rage 128 4X only.
+ * I'm stuffing them here for now until this can be clarified as ATI
+ * documentation doesn't mention their details. <mharris@redhat.com>
+ */
+ case NewChipID('S', 'E'):
+ case NewChipID('S', 'F'):
+ case NewChipID('S', 'G'):
+ case NewChipID('S', 'H'):
+ return ATI_CHIP_RAGE128VR;
+
+ /* case NewChipID('S', 'H'): */
+ /* case NewChipID('S', 'K'): */
+ /* case NewChipID('S', 'L'): */
+ /* case NewChipID('S', 'N'): */
+ /* return ATI_CHIP_RAGE128_4X; */
+
+ case NewChipID('P', 'A'):
+ case NewChipID('P', 'B'):
+ case NewChipID('P', 'C'):
+ case NewChipID('P', 'D'):
+ case NewChipID('P', 'E'):
+ case NewChipID('P', 'F'):
+ return ATI_CHIP_RAGE128PROGL;
+
+ case NewChipID('P', 'G'):
+ case NewChipID('P', 'H'):
+ case NewChipID('P', 'I'):
+ case NewChipID('P', 'J'):
+ case NewChipID('P', 'K'):
+ case NewChipID('P', 'L'):
+ case NewChipID('P', 'M'):
+ case NewChipID('P', 'N'):
+ case NewChipID('P', 'O'):
+ case NewChipID('P', 'P'):
+ case NewChipID('P', 'Q'):
+ case NewChipID('P', 'R'):
+ case NewChipID('P', 'S'):
+ case NewChipID('P', 'T'):
+ case NewChipID('P', 'U'):
+ case NewChipID('P', 'V'):
+ case NewChipID('P', 'W'):
+ case NewChipID('P', 'X'):
+ return ATI_CHIP_RAGE128PROVR;
+
+ case NewChipID('T', 'F'):
+ case NewChipID('T', 'L'):
+ case NewChipID('T', 'R'):
+ case NewChipID('T', 'S'):
+ case NewChipID('T', 'T'):
+ case NewChipID('T', 'U'):
+ return ATI_CHIP_RAGE128PROULTRA;
+
+ case NewChipID('L', 'E'):
+ case NewChipID('L', 'F'):
+ /*
+ * "LK" and "LL" are not in any ATI documentation I can find
+ * - mharris
+ */
+ case NewChipID('L', 'K'):
+ case NewChipID('L', 'L'):
+ return ATI_CHIP_RAGE128MOBILITY3;
+
+ case NewChipID('M', 'F'):
+ case NewChipID('M', 'L'):
+ return ATI_CHIP_RAGE128MOBILITY4;
+
+ case NewChipID('Q', 'D'):
+ case NewChipID('Q', 'E'):
+ case NewChipID('Q', 'F'):
+ case NewChipID('Q', 'G'):
+ return ATI_CHIP_RADEON;
+
+ case NewChipID('Q', 'Y'):
+ case NewChipID('Q', 'Z'):
+ return ATI_CHIP_RADEONVE;
+
+ case NewChipID('L', 'Y'):
+ case NewChipID('L', 'Z'):
+ return ATI_CHIP_RADEONMOBILITY6;
+
+ case NewChipID('L', 'W'):
+ case NewChipID('L', 'X'):
+ return ATI_CHIP_RADEONMOBILITY7;
+
+ case NewChipID('Q', 'H'):
+ case NewChipID('Q', 'I'):
+ case NewChipID('Q', 'J'):
+ case NewChipID('Q', 'K'):
+ case NewChipID('Q', 'L'):
+ case NewChipID('Q', 'M'):
+ case NewChipID('Q', 'N'):
+ case NewChipID('Q', 'O'):
+ case NewChipID('Q', 'h'):
+ case NewChipID('Q', 'i'):
+ case NewChipID('Q', 'j'):
+ case NewChipID('Q', 'k'):
+ case NewChipID('Q', 'l'):
+ case NewChipID('B', 'B'):
+ return ATI_CHIP_R200;
+
+ case NewChipID('Q', 'W'):
+ case NewChipID('Q', 'X'):
+ return ATI_CHIP_RV200;
+
+ case NewChipID('I', 'd'):
+ case NewChipID('I', 'e'):
+ case NewChipID('I', 'f'):
+ case NewChipID('I', 'g'):
+ return ATI_CHIP_RV250;
+
+ case NewChipID('L', 'd'):
+ case NewChipID('L', 'e'):
+ case NewChipID('L', 'f'):
+ case NewChipID('L', 'g'):
+ return ATI_CHIP_RADEONMOBILITY9;
+
+ case NewChipID('A', 'D'):
+ case NewChipID('A', 'E'):
+ case NewChipID('A', 'F'):
+ case NewChipID('A', 'G'):
+ case NewChipID('N', 'D'):
+ case NewChipID('N', 'E'):
+ case NewChipID('N', 'F'):
+ case NewChipID('N', 'G'):
+ return ATI_CHIP_R300;
+
+ case NewChipID('H', 'D'):
+ return ATI_CHIP_HDTV;
+
+ default:
+ /*
+ * I'd say it's a Rage128 or a Radeon here, except that I don't
+ * support them.
+ */
+ return ATI_CHIP_Mach64;
+ }
+}
diff --git a/src/atichip.h b/src/atichip.h
new file mode 100644
index 0000000..ce911c5
--- /dev/null
+++ b/src/atichip.h
@@ -0,0 +1,144 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.22 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICHIP_H___
+#define ___ATICHIP_H___ 1
+
+#include "atipriv.h"
+#include "atiregs.h"
+
+#include "Xmd.h"
+
+/*
+ * Chip-related definitions.
+ */
+typedef enum
+{
+ ATI_CHIP_NONE = 0,
+
+#ifndef AVOID_CPIO
+
+ ATI_CHIP_VGA, /* Generic VGA */
+ ATI_CHIP_18800,
+ ATI_CHIP_18800_1,
+ ATI_CHIP_28800_2,
+ ATI_CHIP_28800_4,
+ ATI_CHIP_28800_5,
+ ATI_CHIP_28800_6,
+ ATI_CHIP_8514A, /* 8514/A */
+ ATI_CHIP_CT480, /* 8514/A clone */
+ ATI_CHIP_38800_1, /* Mach8 */
+ ATI_CHIP_68800, /* Mach32 */
+ ATI_CHIP_68800_3, /* Mach32 */
+ ATI_CHIP_68800_6, /* Mach32 */
+ ATI_CHIP_68800LX, /* Mach32 */
+ ATI_CHIP_68800AX, /* Mach32 */
+
+#endif /* AVOID_CPIO */
+
+ ATI_CHIP_88800GXC, /* Mach64 */
+ ATI_CHIP_88800GXD, /* Mach64 */
+ ATI_CHIP_88800GXE, /* Mach64 */
+ ATI_CHIP_88800GXF, /* Mach64 */
+ ATI_CHIP_88800GX, /* Mach64 */
+ ATI_CHIP_88800CX, /* Mach64 */
+ ATI_CHIP_264CT, /* Mach64 */
+ ATI_CHIP_264ET, /* Mach64 */
+ ATI_CHIP_264VT, /* Mach64 */
+ ATI_CHIP_264GT, /* Mach64 */
+ ATI_CHIP_264VTB, /* Mach64 */
+ ATI_CHIP_264GTB, /* Mach64 */
+ ATI_CHIP_264VT3, /* Mach64 */
+ ATI_CHIP_264GTDVD, /* Mach64 */
+ ATI_CHIP_264LT, /* Mach64 */
+ ATI_CHIP_264VT4, /* Mach64 */
+ ATI_CHIP_264GT2C, /* Mach64 */
+ ATI_CHIP_264GTPRO, /* Mach64 */
+ ATI_CHIP_264LTPRO, /* Mach64 */
+ ATI_CHIP_264XL, /* Mach64 */
+ ATI_CHIP_MOBILITY, /* Mach64 */
+ ATI_CHIP_Mach64, /* Mach64 */
+ ATI_CHIP_RAGE128GL, /* Rage128 */
+ ATI_CHIP_RAGE128VR, /* Rage128 */
+ ATI_CHIP_RAGE128PROGL, /* Rage128 */
+ ATI_CHIP_RAGE128PROVR, /* Rage128 */
+ ATI_CHIP_RAGE128PROULTRA, /* Rage128 */
+ ATI_CHIP_RAGE128MOBILITY3, /* Rage128 */
+ ATI_CHIP_RAGE128MOBILITY4, /* Rage128 */
+ ATI_CHIP_Rage128, /* Rage128 */
+ ATI_CHIP_RADEON, /* Radeon */
+ ATI_CHIP_RADEONVE, /* Radeon VE */
+ ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */
+ ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */
+ ATI_CHIP_R200, /* R200 */
+ ATI_CHIP_RV200, /* RV200 */
+ ATI_CHIP_RV250, /* RV250 */
+ ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */
+ ATI_CHIP_R300, /* R300 */
+ ATI_CHIP_HDTV /* HDTV */
+} ATIChipType;
+
+extern const char *ATIChipNames[];
+
+/*
+ * Foundry codes for 264xT's.
+ */
+typedef enum
+{
+ ATI_FOUNDRY_SGS, /* SGS-Thompson */
+ ATI_FOUNDRY_NEC, /* NEC */
+ ATI_FOUNDRY_KSC, /* KSC (?) */
+ ATI_FOUNDRY_UMC, /* United Microelectronics Corporation */
+ ATI_FOUNDRY_TSMC, /* Taiwan Semiconductor Manufacturing Company */
+ ATI_FOUNDRY_5,
+ ATI_FOUNDRY_6,
+ ATI_FOUNDRY_UMCA /* UMC alternate */
+} ATIFoundryType;
+
+extern const char *ATIFoundryNames[];
+
+#ifndef AVOID_CPIO
+
+extern void ATIMach32ChipID FunctionPrototype((ATIPtr));
+
+#endif /* AVOID_CPIO */
+
+extern void ATIMach64ChipID FunctionPrototype((ATIPtr, const CARD16));
+extern ATIChipType ATIChipID FunctionPrototype((const CARD16,
+ const CARD8));
+
+#define OldChipID(_1, _0) \
+ (SetBits(_0 - 'A', CHIP_CODE_0) | SetBits(_1 - 'A', CHIP_CODE_1))
+
+#define NewChipID(_1, _0) \
+ (SetBits(_0, CFG_CHIP_TYPE0) | SetBits(_1, CFG_CHIP_TYPE1))
+
+#define OldToNewChipID(_ChipID) \
+ (SetBits(GetBits(_ChipID, CHIP_CODE_0) + 'A', CFG_CHIP_TYPE0) | \
+ SetBits(GetBits(_ChipID, CHIP_CODE_1) + 'A', CFG_CHIP_TYPE1))
+
+#define NewToOldChipID(_ChipID) \
+ (SetBits(GetBits(_ChipID, CFG_CHIP_TYPE0) - 'A', CHIP_CODE_0) | \
+ (SetBits(GetBits(_ChipID, CFG_CHIP_TYPE1) - 'A', CHIP_CODE_1))
+
+#endif /* ___ATICHIP_H___ */
diff --git a/src/aticlock.c b/src/aticlock.c
new file mode 100644
index 0000000..0fc3d6b
--- /dev/null
+++ b/src/aticlock.c
@@ -0,0 +1,1586 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticlock.c,v 1.20 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Adapters prior to V5 use 4 crystals. Adapters V5 and later use a clock
+ * generator chip. V3 and V4 adapters differ when it comes to choosing clock
+ * frequencies.
+ *
+ * VGA Wonder V3/V4 Adapter Clock Frequencies
+ * R E G I S T E R S
+ * 1CE(*) 3C2 3C2 Frequency
+ * B2h/BEh
+ * Bit 6/4 Bit 3 Bit 2 (MHz)
+ * ------- ------- ------- -------
+ * 0 0 0 50.000
+ * 0 0 1 56.644
+ * 0 1 0 Spare 1
+ * 0 1 1 44.900
+ * 1 0 0 44.900
+ * 1 0 1 50.000
+ * 1 1 0 Spare 2
+ * 1 1 1 36.000
+ *
+ * (*): V3 uses index B2h, bit 6; V4 uses index BEh, bit 4
+ *
+ * V5, PLUS, XL and XL24 usually have an ATI 18810 clock generator chip, but
+ * some have an ATI 18811-0, and it's quite conceivable that some exist with
+ * ATI 18811-1's or ATI 18811-2's. Mach32 adapters are known to use any one of
+ * these clock generators. Mach32 adapters also use a different dot clock
+ * ordering. ATI says there is no reliable way for the driver to determine
+ * which clock generator is on the adapter, but this driver will do its best to
+ * do so anyway.
+ *
+ * VGA Wonder V5/PLUS/XL/XL24 Clock Frequencies
+ * R E G I S T E R S
+ * 1CE 1CE 3C2 3C2 Frequency
+ * B9h BEh (MHz) 18811-0 18811-1
+ * Bit 1 Bit 4 Bit 3 Bit 2 18810 18812-0 18811-2 (*5)
+ * ------- ------- ------- ------- ------- ------- ------- -------
+ * 0 0 0 0 30.240 30.240 135.000 75.000
+ * 0 0 0 1 32.000 32.000 32.000 77.500
+ * 0 0 1 0 37.500 110.000 110.000 80.000
+ * 0 0 1 1 39.000 80.000 80.000 90.000
+ * 0 1 0 0 42.954 42.954 100.000 25.175
+ * 0 1 0 1 48.771 48.771 126.000 28.322
+ * 0 1 1 0 (*1) 92.400 92.400 31.500
+ * 0 1 1 1 36.000 36.000 36.000 36.000
+ * 1 0 0 0 40.000 39.910 39.910 100.000
+ * 1 0 0 1 (*4) 44.900 44.900 110.000
+ * 1 0 1 0 75.000 75.000 75.000 126.000
+ * 1 0 1 1 65.000 65.000 65.000 135.000
+ * 1 1 0 0 50.350 50.350 50.350 40.000
+ * 1 1 0 1 56.640 56.640 56.640 44.900
+ * 1 1 1 0 (*2) (*3) (*3) 50.000
+ * 1 1 1 1 44.900 44.900 44.900 65.000
+ *
+ * (*1) External 0 (supposedly 16.657 Mhz)
+ * (*2) External 1 (supposedly 28.322 MHz)
+ * (*3) This setting doesn't seem to generate anything
+ * (*4) This setting is documented to be 56.644 MHz, but something close to 82
+ * MHz has also been encountered.
+ * (*5) This setting is for Dell OmniPlex 590 systems, with a 68800AX on the
+ * motherboard, along with an AT&T21C498 DAC (which is reported as an
+ * STG1700) and ICS2494AM clock generator (a.k.a. ATI 18811-?).
+ *
+ * Mach32 Clock Frequencies
+ * R E G I S T E R S
+ * 1CE 1CE 3C2 3C2 Frequency
+ * B9h BEh (MHz) 18811-0 18811-1
+ * Bit 1 Bit 4 Bit 3 Bit 2 18810 18812-0 18811-2 (*5)
+ * ------- ------- ------- ------- ------- ------- ------- -------
+ * 0 0 0 0 42.954 42.954 100.000 25.175
+ * 0 0 0 1 48.771 48.771 126.000 28.322
+ * 0 0 1 0 (*1) 92.400 92.400 31.500
+ * 0 0 1 1 36.000 36.000 36.000 36.000
+ * 0 1 0 0 30.240 30.240 135.000 75.000
+ * 0 1 0 1 32.000 32.000 32.000 77.500
+ * 0 1 1 0 37.500 110.000 110.000 80.000
+ * 0 1 1 1 39.000 80.000 80.000 90.000
+ * 1 0 0 0 50.350 50.350 50.350 40.000
+ * 1 0 0 1 56.640 56.640 56.640 44.900
+ * 1 0 1 0 (*2) (*3) (*3) 50.000
+ * 1 0 1 1 44.900 44.900 44.900 65.000
+ * 1 1 0 0 40.000 39.910 39.910 100.000
+ * 1 1 0 1 (*4) 44.900 44.900 110.000
+ * 1 1 1 0 75.000 75.000 75.000 126.000
+ * 1 1 1 1 65.000 65.000 65.000 135.000
+ *
+ * (*1) External 0 (supposedly 16.657 Mhz)
+ * (*2) External 1 (supposedly 28.322 MHz)
+ * (*3) This setting doesn't seem to generate anything
+ * (*4) This setting is documented to be 56.644 MHz, but something close to 82
+ * MHz has also been encountered.
+ * (*5) This setting is for Dell OmniPlex 590 systems, with a 68800AX on the
+ * motherboard, along with an AT&T21C498 DAC (which is reported as an
+ * STG1700) and ICS2494AM clock generator (a.k.a. ATI 18811-?).
+ *
+ * Note that, to reduce confusion, this driver masks out the different clock
+ * ordering.
+ *
+ * For all adapters, these frequencies can be divided by 1 or 2. For all
+ * adapters, except Mach32's and Mach64's, frequencies can also be divided by 3
+ * or 4.
+ *
+ * Register 1CE, index B8h
+ * Bit 7 Bit 6
+ * ------- -------
+ * 0 0 Divide by 1
+ * 0 1 Divide by 2
+ * 1 0 Divide by 3
+ * 1 1 Divide by 4
+ *
+ * With respect to clocks, Mach64's are entirely different animals.
+ *
+ * The oldest Mach64's use one of the non-programmable clock generators
+ * described above. In this case, the driver will handle clocks in much the
+ * same way as it would for a Mach32.
+ *
+ * All other Mach64 adapters use a programmable clock generator. BIOS
+ * initialisation programmes an initial set of frequencies. Two of these are
+ * reserved to allow for the setting of modes that do not use a frequency from
+ * this initial set. One of these reserved slots is used by the BIOS mode set
+ * routine, the other by the particular accelerated driver used (MS-Windows,
+ * AutoCAD, etc.). The slots reserved in this way are dependent on the
+ * particular clock generator used by the adapter.
+ *
+ * If the driver does not support the adapter's clock generator, it will try to
+ * match the (probed or specified) clocks to one of the following sets.
+ *
+ * Mach64 Clock Frequencies for unsupported programmable clock generators
+ * R E G I S T E R S
+ * 1CE 1CE 3C2 3C2 Frequency
+ * B9h BEh (MHz)
+ * Bit 1 Bit 4 Bit 3 Bit 2 Set 1 Set 2 Set 3
+ * ------- ------- ------- ------- ------- ------- -------
+ * 0 0 0 0 50.350 25.180 25.180
+ * 0 0 0 1 56.640 28.320 28.320
+ * 0 0 1 0 63.000 31.500 0.000
+ * 0 0 1 1 72.000 36.000 0.000
+ * 0 1 0 0 0.000 0.000 0.000
+ * 0 1 0 1 110.000 110.000 0.000
+ * 0 1 1 0 126.000 126.000 0.000
+ * 0 1 1 1 135.000 135.000 0.000
+ * 1 0 0 0 40.000 40.000 0.000
+ * 1 0 0 1 44.900 44.900 0.000
+ * 1 0 1 0 49.500 49.500 0.000
+ * 1 0 1 1 50.000 50.000 0.000
+ * 1 1 0 0 0.000 0.000 0.000
+ * 1 1 0 1 80.000 80.000 0.000
+ * 1 1 1 0 75.000 75.000 0.000
+ * 1 1 1 1 65.000 65.000 0.000
+ *
+ * The driver will never select a setting of 0.000 MHz. The above comments on
+ * clock ordering and clock divider apply here also.
+ *
+ * For all supported programmable clock generators, the driver will ignore any
+ * XF86Config clock line and programme, as needed, the clock number reserved by
+ * the BIOS for accelerated drivers. The driver's mode initialisation routine
+ * finds integers N, M and D such that
+ *
+ * N
+ * R * ------- MHz
+ * M * D
+ *
+ * best approximates the mode's clock frequency, where R is the crystal-
+ * generated reference frequency (usually 14.318 MHz). D is a power of 2
+ * except for those integrated controllers that also offer odd dividers.
+ * Different clock generators have different restrictions on the value N, M and
+ * D can assume. The driver contains an internal table to record these
+ * restrictions (among other things). The resulting values of N, M and D are
+ * then encoded in a generator-specific way and used to programme the clock.
+ * The Mach64's clock divider is not used in this case.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "atidac.h"
+#include "atidsp.h"
+#include "atimach64io.h"
+#include "atimode.h"
+#include "atiwonderio.h"
+
+/*
+ * Definitions related to non-programmable clock generators.
+ */
+const char *ATIClockNames[] =
+{
+ "unknown",
+ "IBM VGA compatible",
+ "crystals",
+ "ATI 18810 or similar",
+ "ATI 18811-0 or similar",
+ "ATI 18811-1 or similar",
+ "ICS 2494-AM or similar",
+ "Programmable (BIOS setting 1)",
+ "Programmable (BIOS setting 2)",
+ "Programmable (BIOS setting 3)"
+};
+
+/*
+ * Definitions related to programmable clock generators.
+ */
+static CARD16 ATIPostDividers[] = {1, 2, 4, 8, 16, 32, 64, 128},
+ ATI264xTPostDividers[] = {1, 2, 4, 8, 3, 0, 6, 12};
+ClockRec ATIClockDescriptors[] =
+{
+ {
+ 0, 0, 0, 1, 1,
+ 1, 1, 0,
+ 0, NULL,
+ "Non-programmable"
+ },
+ {
+ 257, 512, 257, 1, 1,
+ 46, 46, 0,
+ 4, ATIPostDividers,
+ "ATI 18818 or ICS 2595 or similar"
+ },
+ {
+ 2, 129, 2, 1, 1,
+ 8, 14, 2,
+ 8, ATIPostDividers,
+ "SGS-Thompson 1703 or similar"
+ },
+ {
+ 16, 263, 8, 8, 9,
+ 4, 12, 2,
+ 4, ATIPostDividers,
+ "Chrontel 8398 or similar"
+ },
+ {
+ 2, 255, 0, 1, 1,
+ 45, 45, 0,
+ 4, ATI264xTPostDividers,
+ "Internal"
+ },
+ {
+ 2, 257, 2, 1, 1,
+ 2, 32, 2,
+ 4, ATIPostDividers,
+ "AT&T 20C408 or similar"
+ },
+ {
+ 65, 128, 65, 1, 1,
+ 2, 14, 0,
+ 4, ATIPostDividers,
+ "IBM RGB 514 or similar"
+ }
+};
+
+/*
+ * XF86Config clocks line that start with the following will either be rejected
+ * for ATI adapters, or accepted for non-ATI adapters.
+ */
+static const int
+ATIVGAClocks[] =
+{
+ 25175, 28322,
+ -1
+};
+
+/*
+ * The driver will attempt to match fixed clocks to one of the following
+ * specifications.
+ */
+static const int
+ATICrystalFrequencies[] =
+{
+ 50000, 56644, 0, 44900, 44900, 50000, 0, 36000,
+ -1
+},
+ATI18810Frequencies[] =
+{
+ 30240, 32000, 37500, 39000, 42954, 48771, 0, 36000,
+ 40000, 0, 75000, 65000, 50350, 56640, 0, 44900
+},
+ATI188110Frequencies[] =
+{
+ 30240, 32000, 110000, 80000, 42954, 48771, 92400, 36000,
+ 39910, 44900, 75000, 65000, 50350, 56640, 0, 44900
+},
+ATI188111Frequencies[] =
+{
+ 135000, 32000, 110000, 80000, 100000, 126000, 92400, 36000,
+ 39910, 44900, 75000, 65000, 50350, 56640, 0, 44900
+},
+ATI2494AMFrequencies[] =
+{
+ 75000, 77500, 80000, 90000, 25175, 28322, 31500, 36000,
+ 100000, 110000, 126000, 135000, 40000, 44900, 50000, 65000
+},
+ATIMach64AFrequencies[] =
+{
+ 0, 110000, 126000, 135000, 50350, 56640, 63000, 72000,
+ 0, 80000, 75000, 65000, 40000, 44900, 49500, 50000
+},
+ATIMach64BFrequencies[] =
+{
+ 0, 110000, 126000, 135000, 25180, 28320, 31500, 36000,
+ 0, 80000, 75000, 65000, 40000, 44900, 49500, 50000
+},
+ATIMach64CFrequencies[] =
+{
+ 0, 0, 0, 0, 25180, 28320, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+},
+*SpecificationClockLine[] =
+{
+ NULL,
+ ATIVGAClocks,
+ ATICrystalFrequencies,
+ ATI18810Frequencies,
+ ATI188110Frequencies,
+ ATI188111Frequencies,
+ ATI2494AMFrequencies,
+ ATIMach64AFrequencies,
+ ATIMach64BFrequencies,
+ ATIMach64CFrequencies,
+ NULL
+};
+
+/*
+ * The driver will reject XF86Config clocks lines that start with, or are an
+ * initial subset of, one of the following.
+ */
+static const int
+ATIPre_2_1_1_Clocks_A[] = /* Based on 18810 */
+{
+ 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640,
+ 30240, 32000, 37500, 39000, 40000, 0, 75000, 65000,
+ -1
+},
+ATIPre_2_1_1_Clocks_B[] = /* Based on 18811-0 */
+{
+ 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640,
+ 30240, 32000, 110000, 80000, 39910, 44900, 75000, 65000,
+ -1
+},
+ATIPre_2_1_1_Clocks_C[] = /* Based on 18811-1 (or -2) */
+{
+ 18000, 22450, 25175, 28320, 36000, 44900, 50350, 56640,
+ 135000, 32000, 110000, 80000, 39910, 44900, 75000, 65000,
+ -1
+},
+ATIPre_2_1_1_Clocks_D[] = /* Based on ICS 2494AM */
+{
+ 18000, 32500, 20000, 22450, 36000, 65000, 40000, 44900,
+ 75000, 77500, 80000, 90000, 100000, 110000, 126000, 135000,
+ -1
+},
+ATIPre_2_1_1_Clocks_E[] = /* Based on programmable setting 1 */
+{
+ 36000, 25000, 20000, 22450, 72000, 50000, 40000, 44900,
+ 0, 110000, 126000, 135000, 0, 80000, 75000, 65000,
+ -1
+},
+ATIPre_2_1_1_Clocks_F[] = /* Based on programmable setting 2 */
+{
+ 18000, 25000, 20000, 22450, 36000, 50000, 40000, 44900,
+ 0, 110000, 126000, 135000, 0, 80000, 75000, 65000,
+ -1
+},
+*InvalidClockLine[] =
+{
+ NULL,
+ ATIVGAClocks,
+ ATIPre_2_1_1_Clocks_A,
+ ATIPre_2_1_1_Clocks_B,
+ ATIPre_2_1_1_Clocks_C,
+ ATIPre_2_1_1_Clocks_D,
+ ATIPre_2_1_1_Clocks_E,
+ ATIPre_2_1_1_Clocks_F,
+ NULL
+};
+
+/*
+ * Clock maps.
+ */
+static const CARD8 ClockMaps[][4] =
+{
+ /* Null map */
+ { 0, 1, 2, 3},
+ /* VGA Wonder map <-> Mach{8,32,64} */
+ { 1, 0, 3, 2},
+ /* VGA Wonder map <-> Accelerator */
+ { 0, 2, 1, 3},
+ /* VGA -> Accelerator map */
+ { 2, 0, 3, 1},
+ /* Accelerator -> VGA map */
+ { 1, 3, 0, 2}
+};
+#define ATIVGAWonderClockMap ClockMaps[0]
+#define ATIVGAWonderClockUnmap ATIVGAWonderClockMap
+#define ATIMachVGAClockMap ClockMaps[1]
+#define ATIMachVGAClockUnmap ATIMachVGAClockMap
+#define ATIVGAProgrammableClockMap ClockMaps[2]
+#define ATIVGAProgrammableClockUnmap ATIVGAProgrammableClockMap
+#define ATIAcceleratorClockMap ClockMaps[3]
+#define ATIAcceleratorClockUnmap ClockMaps[4]
+#define ATIProgrammableClockMap ClockMaps[0]
+#define ATIProgrammableClockUnmap ATIProgrammableClockMap
+#define MapClockIndex(_ClockMap, _Index) \
+ (SetBits((_ClockMap)[GetBits(_Index, 0x0CU)], 0x0CU) | \
+ ((_Index) & ~0x0CU))
+
+/*
+ * ATIMatchClockLine --
+ *
+ * This function tries to match the XF86Config clocks to one of an array of
+ * clock lines. It returns a clock line number or 0.
+ */
+static int
+ATIMatchClockLine
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ const int **ClockLine,
+ const unsigned short int NumberOfClocks,
+ const int CalibrationClockNumber,
+ const int ClockMap
+)
+{
+ int ClockChip = 0, ClockChipIndex = 0;
+ int NumberOfMatchingClocks = 0;
+ int MinimumGap = CLOCK_TOLERANCE + 1;
+
+ /* For ATI adapters, reject generic VGA clocks */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter != ATI_ADAPTER_VGA)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (ClockLine == SpecificationClockLine)
+ ClockChipIndex++;
+ }
+
+ /* If checking for XF86Config clock order, skip crystals */
+ if (ClockMap)
+ ClockChipIndex++;
+
+ for (; ClockLine[++ClockChipIndex]; )
+ {
+ int MaximumGap = 0, ClockCount = 0, ClockIndex = 0;
+
+#ifndef AVOID_CPIO
+
+ /* Only Mach64's and later can have programmable clocks */
+ if ((ClockChipIndex >= ATI_CLOCK_MACH64A) &&
+ (pATI->Adapter < ATI_ADAPTER_MACH64))
+ break;
+
+#endif /* AVOID_CPIO */
+
+ for (; ClockIndex < NumberOfClocks; ClockIndex++)
+ {
+ int Gap, XF86ConfigClock, SpecificationClock;
+
+ SpecificationClock = ClockLine[ClockChipIndex]
+ [MapClockIndex(ClockMaps[ClockMap], ClockIndex)];
+ if (SpecificationClock < 0)
+ break;
+ if (!SpecificationClock)
+ continue;
+
+ XF86ConfigClock = pScreenInfo->clock[ClockIndex];
+ if (!XF86ConfigClock)
+ continue;
+
+ Gap = abs(XF86ConfigClock - SpecificationClock);
+ if (Gap >= MinimumGap)
+ goto SkipThisClockGenerator;
+ if (!Gap)
+ {
+ if (ClockIndex == CalibrationClockNumber)
+ continue;
+ }
+ else if (Gap > MaximumGap)
+ MaximumGap = Gap;
+ ClockCount++;
+ }
+
+ if (ClockCount <= NumberOfMatchingClocks)
+ continue;
+ NumberOfMatchingClocks = ClockCount;
+ ClockChip = ClockChipIndex;
+ if (!(MinimumGap = MaximumGap))
+ break;
+
+SkipThisClockGenerator:;
+
+#ifndef AVOID_CPIO
+
+ /* For non-ATI adapters, only normalise standard VGA clocks */
+ if (pATI->Adapter == ATI_ADAPTER_VGA)
+ break;
+
+#endif /* AVOID_CPIO */
+
+ }
+
+ return ClockChip;
+}
+
+/*
+ * ATIClockPreInit --
+ *
+ * This function is called by ATIPreInit() and handles the XF86Config clocks
+ * line (or lack thereof).
+ */
+void
+ATIClockPreInit
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ GDevPtr pGDev,
+ ClockRangePtr pRange
+)
+{
+ double ScaleFactor;
+ unsigned short int NumberOfUndividedClocks;
+ unsigned short int NumberOfDividers, NumberOfClocks;
+ int CalibrationClockNumber, CalibrationClockValue;
+ int ClockIndex, SpecificationClock, ClockMap = 0, Index;
+ CARD8 CanDisableInterrupts;
+
+#ifndef AVOID_CPIO
+
+ CARD8 genmo;
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Decide what to do about the XF86Config clocks for programmable clock
+ * generators.
+ */
+ if (pATI->ProgrammableClock != ATI_CLOCK_FIXED)
+ {
+ /* Check for those that are not (yet) handled */
+ if ((pATI->ProgrammableClock == ATI_CLOCK_UNKNOWN) ||
+ (pATI->ProgrammableClock > NumberOf(ATIClockDescriptors)))
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
+ "Unknown programmable clock generator type (0x%02X)"
+ " detected.\n", pATI->ProgrammableClock);
+ else if (pATI->ClockDescriptor.MaxN <= 0)
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
+ "Unsupported programmable clock generator detected: %s.\n",
+ pATI->ClockDescriptor.ClockName);
+ else
+ {
+ /*
+ * Recognise supported clock generators. This involves telling the
+ * rest of the server about it and (re-)initializing the XF86Config
+ * clocks line.
+ */
+ pRange->clockIndex = -1;
+ pScreenInfo->progClock = TRUE;
+
+ /* Set internal clock ordering */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ {
+ pATI->NewHW.ClockMap = ATIVGAProgrammableClockMap;
+ pATI->NewHW.ClockUnmap = ATIVGAProgrammableClockUnmap;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->NewHW.ClockMap = ATIProgrammableClockMap;
+ pATI->NewHW.ClockUnmap = ATIProgrammableClockUnmap;
+ }
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s programmable clock generator detected.\n",
+ pATI->ClockDescriptor.ClockName);
+ if (pATI->ReferenceDenominator == 1)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "Reference clock %.3f MHz.\n",
+ (double)pATI->ReferenceNumerator / 1000.0);
+ else
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "Reference clock %.6g/%d (%.3f) MHz.\n",
+ (double)pATI->ReferenceNumerator / 1000.0,
+ pATI->ReferenceDenominator,
+ (double)pATI->ReferenceNumerator /
+ ((double)pATI->ReferenceDenominator * 1000.0));
+
+ /* Clobber XF86Config clocks line */
+ if (pGDev->numclocks)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "XF86Config clocks specification ignored.\n");
+
+ if (pATI->ProgrammableClock == ATI_CLOCK_CH8398)
+ { /* First two are fixed */
+ pScreenInfo->numClocks = 2;
+ pScreenInfo->clock[0] = 25175;
+ pScreenInfo->clock[1] = 28322;
+ }
+ else if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
+ /*
+ * The integrated PLL generates clocks as if the reference
+ * frequency were doubled.
+ */
+ pATI->ReferenceNumerator <<= 1;
+
+ return; /* ... to ATIPreInit() */
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ /* Set default clock maps */
+ pATI->NewHW.ClockMap = ATIVGAWonderClockMap;
+ pATI->NewHW.ClockUnmap = ATIVGAWonderClockUnmap;
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Determine the number of clock values the adapter should be able to
+ * generate and the dot clock to use for probe calibration.
+ */
+ProbeClocks:
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter == ATI_ADAPTER_VGA)
+ {
+ NumberOfDividers = 1;
+ NumberOfUndividedClocks = 4;
+ CalibrationClockNumber = 1;
+ CalibrationClockValue = 28322;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+
+#ifndef AVOID_CPIO
+
+ NumberOfDividers = 4;
+ if ((pATI->Chip <= ATI_CHIP_18800) ||
+ (pATI->Adapter == ATI_ADAPTER_V4))
+ {
+ NumberOfUndividedClocks = 8;
+ /* Actually, any undivided clock will do */
+ CalibrationClockNumber = 1;
+ CalibrationClockValue = 56644;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ NumberOfUndividedClocks = 16;
+
+#ifndef AVOID_CPIO
+
+ CalibrationClockNumber = 7;
+ CalibrationClockValue = 36000;
+ if (pATI->Chip >= ATI_CHIP_68800)
+
+#endif /* AVOID_CPIO */
+
+ {
+ NumberOfDividers = 2;
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ NumberOfDividers = 1;
+ NumberOfUndividedClocks = 4;
+ CalibrationClockNumber = 1;
+ CalibrationClockValue = 28322;
+ }
+ else
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH64)
+
+#endif /* AVOID_CPIO */
+
+ {
+ CalibrationClockNumber = 10 /* or 11 */;
+ CalibrationClockValue = 75000 /* or 65000 */;
+ }
+
+ /*
+ * When selecting clocks, all ATI accelerators use a different
+ * clock ordering.
+ */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ {
+ pATI->NewHW.ClockMap = ATIMachVGAClockMap;
+ pATI->NewHW.ClockUnmap = ATIMachVGAClockUnmap;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->NewHW.ClockMap = ATIAcceleratorClockMap;
+ pATI->NewHW.ClockUnmap = ATIAcceleratorClockUnmap;
+ }
+ }
+ }
+ }
+
+ pATI->OldHW.ClockMap = pATI->NewHW.ClockMap;
+ pATI->OldHW.ClockUnmap = pATI->NewHW.ClockUnmap;
+
+ NumberOfClocks = NumberOfUndividedClocks * NumberOfDividers;
+
+ /*
+ * Respect any XF86Config clocks line. Well, that's the theory, anyway.
+ * In practice, however, the regular use of probed values is widespread, at
+ * times causing otherwise inexplicable results. So, attempt to normalise
+ * the clocks to known (i.e. specification) values.
+ */
+ if (!pGDev->numclocks || pATI->OptionProbeClocks ||
+ xf86ServerIsOnlyProbing())
+ {
+ if (pATI->ProgrammableClock != ATI_CLOCK_FIXED)
+ {
+ /*
+ * For unsupported programmable clock generators, pick the highest
+ * frequency set by BIOS initialisation for clock calibration.
+ */
+ CalibrationClockNumber = CalibrationClockValue = 0;
+ for (ClockIndex = 0;
+ ClockIndex < NumberOfUndividedClocks;
+ ClockIndex++)
+ if (CalibrationClockValue < pATI->BIOSClocks[ClockIndex])
+ {
+ CalibrationClockNumber = ClockIndex;
+ CalibrationClockValue = pATI->BIOSClocks[ClockIndex];
+ }
+ CalibrationClockNumber =
+ MapClockIndex(pATI->NewHW.ClockUnmap, CalibrationClockNumber);
+ CalibrationClockValue *= 10;
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /*
+ * The current video state needs to be saved before the clock
+ * probe, and restored after. Video memory corruption and other
+ * effects occur because, at this early stage, the clock probe
+ * cannot reliably be prevented from enabling frequencies that are
+ * greater than what the adapter can handle.
+ */
+ ATIModeSave(pScreenInfo, pATI, &pATI->OldHW);
+
+ /* Ensure clock select pins are not OR'ed with anything */
+ if (pATI->CPIO_VGAWonder && (pATI->OldHW.crtc == ATI_CRTC_VGA))
+ ATIModifyExtReg(pATI, 0xB5U, pATI->OldHW.b5, 0x7FU, 0x00U);
+ }
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Probe the adapter for clock values. The following is essentially
+ * the common layer's xf86GetClocks() reworked to fit. One difference
+ * is the ability to monitor a VSync bit in MMIO space.
+ */
+ CanDisableInterrupts = TRUE; /* An assumption verified below */
+
+ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++)
+ {
+ pScreenInfo->clock[ClockIndex] = 0;
+
+ /* Remap clock number */
+ Index = MapClockIndex(pATI->OldHW.ClockMap, ClockIndex);
+
+ /* Select the clock */
+ switch (pATI->OldHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /* Get generic two low-order bits */
+ genmo = (inb(R_GENMO) & 0xF3U) | ((Index << 2) & 0x0CU);
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ /*
+ * On adapters with crystals, switching to one of the
+ * spare assignments doesn't do anything (i.e. the
+ * previous setting remains in effect). So, disable
+ * their selection.
+ */
+ if (((Index & 0x03U) == 0x02U) &&
+ ((pATI->Chip <= ATI_CHIP_18800) ||
+ (pATI->Adapter == ATI_ADAPTER_V4)))
+ continue;
+
+ /* Start sequencer reset */
+ PutReg(SEQX, 0x00U, 0x00U);
+
+ /* Set high-order bits */
+ if (pATI->Chip <= ATI_CHIP_18800)
+ ATIModifyExtReg(pATI, 0xB2U, -1, 0xBFU,
+ Index << 4);
+ else
+ {
+ ATIModifyExtReg(pATI, 0xBEU, -1, 0xEFU,
+ Index << 2);
+ if (pATI->Adapter != ATI_ADAPTER_V4)
+ {
+ Index >>= 1;
+ ATIModifyExtReg(pATI, 0xB9U, -1, 0xFDU,
+ Index >> 1);
+ }
+ }
+
+ /* Set clock divider bits */
+ ATIModifyExtReg(pATI, 0xB8U, -1, 0x00U,
+ (Index << 3) & 0xC0U);
+ }
+ else
+ {
+ /*
+ * Reject clocks that cannot be selected.
+ */
+ if (Index & ~0x03U)
+ continue;
+
+ /* Start sequencer reset */
+ PutReg(SEQX, 0x00U, 0x00U);
+ }
+
+ /* Must set miscellaneous output register last */
+ outb(GENMO, genmo);
+
+ /* End sequencer reset */
+ PutReg(SEQX, 0x00U, 0x03U);
+
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ out8(CLOCK_CNTL, CLOCK_STROBE |
+ SetBits(Index, CLOCK_SELECT | CLOCK_DIVIDER));
+ break;
+
+ default:
+ continue;
+ }
+
+ usleep(50000); /* Let clock stabilise */
+
+ xf86SetPriority(TRUE);
+
+ /* Try to disable interrupts */
+ if (CanDisableInterrupts && !xf86DisableInterrupts())
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to disable interrupts; Clock probe will not be as"
+ " accurate.\n");
+ CanDisableInterrupts = FALSE;
+ }
+
+ /*
+ * Generate a count while monitoring the vertical sync or blanking
+ * pulse. This is dependent on the CRTC used by the mode on server
+ * entry.
+ */
+ switch (pATI->OldHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /* Verify vertical sync pulses are in fact occurring */
+ Index = 1 << 19;
+ while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U))
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+ Index = 1 << 19;
+ while (inb(GENS1(pATI->CPIO_VGABase)) & 0x08U)
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+ Index = 1 << 19;
+ while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U))
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+
+ /* Generate the count */
+ for (Index = 0; Index < 8; Index++)
+ {
+ while (inb(GENS1(pATI->CPIO_VGABase)) & 0x08U)
+ pScreenInfo->clock[ClockIndex]++;
+ while (!(inb(GENS1(pATI->CPIO_VGABase)) & 0x08U))
+ pScreenInfo->clock[ClockIndex]++;
+ }
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ /* Verify vertical blanking pulses are in fact occurring */
+ Index = 1 << 19;
+ while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK))
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+ Index = 1 << 19;
+ while (inr(CRTC_INT_CNTL) & CRTC_VBLANK)
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+ Index = 1 << 19;
+ while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK))
+ if (Index-- <= 0)
+ goto EnableInterrupts;
+
+ /* Generate the count */
+ for (Index = 0; Index < 4; Index++)
+ {
+ while (inr(CRTC_INT_CNTL) & CRTC_VBLANK)
+ pScreenInfo->clock[ClockIndex]++;
+ while (!(inr(CRTC_INT_CNTL) & CRTC_VBLANK))
+ pScreenInfo->clock[ClockIndex]++;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ EnableInterrupts:
+ if (CanDisableInterrupts)
+ xf86EnableInterrupts();
+
+ xf86SetPriority(FALSE);
+ }
+
+ ScaleFactor = (double)CalibrationClockValue *
+ (double)pScreenInfo->clock[CalibrationClockNumber];
+
+ /* Scale the clocks from counts to kHz */
+ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++)
+ {
+ if (ClockIndex == CalibrationClockNumber)
+ pScreenInfo->clock[ClockIndex] = CalibrationClockValue;
+ else if (pScreenInfo->clock[ClockIndex])
+ /* Round to the nearest 10 kHz */
+ pScreenInfo->clock[ClockIndex] =
+ (int)(((ScaleFactor /
+ (double)pScreenInfo->clock[ClockIndex]) +
+ 5) / 10) * 10;
+ }
+
+ pScreenInfo->numClocks = NumberOfClocks;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /* Restore video state */
+ ATIModeSet(pScreenInfo, pATI, &pATI->OldHW);
+ xfree(pATI->OldHW.frame_buffer);
+ pATI->OldHW.frame_buffer = NULL;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Tell user clocks were probed, instead of supplied */
+ pATI->OptionProbeClocks = TRUE;
+
+ /* Attempt to match probed clocks to a known specification */
+ pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI,
+ SpecificationClockLine, NumberOfUndividedClocks,
+ CalibrationClockNumber, 0);
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Chip <= ATI_CHIP_18800) ||
+ (pATI->Adapter == ATI_ADAPTER_V4))
+ {
+ /* V3 and V4 adapters don't have clock chips */
+ if (pATI->Clock > ATI_CLOCK_CRYSTALS)
+ pATI->Clock = ATI_CLOCK_NONE;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ /* All others don't have crystals */
+ if (pATI->Clock == ATI_CLOCK_CRYSTALS)
+ pATI->Clock = ATI_CLOCK_NONE;
+ }
+ }
+ else
+ {
+ /*
+ * Allow for an initial subset of specification clocks. Can't allow
+ * for any more than that though...
+ */
+ if (NumberOfClocks > pGDev->numclocks)
+ {
+ NumberOfClocks = pGDev->numclocks;
+ if (NumberOfUndividedClocks > NumberOfClocks)
+ NumberOfUndividedClocks = NumberOfClocks;
+ }
+
+ /* Move XF86Config clocks into the ScrnInfoRec */
+ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++)
+ pScreenInfo->clock[ClockIndex] = pGDev->clock[ClockIndex];
+ pScreenInfo->numClocks = NumberOfClocks;
+
+ /* Attempt to match clocks to a known specification */
+ pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI,
+ SpecificationClockLine, NumberOfUndividedClocks, -1, 0);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter != ATI_ADAPTER_VGA)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (pATI->Clock == ATI_CLOCK_NONE)
+ {
+ /*
+ * Reject certain clock lines that are obviously wrong. This
+ * includes the standard VGA clocks for ATI adapters, and clock
+ * lines that could have been used with the pre-2.1.1 driver.
+ */
+ if (ATIMatchClockLine(pScreenInfo, pATI, InvalidClockLine,
+ NumberOfClocks, -1, 0))
+ pATI->OptionProbeClocks = TRUE;
+ else
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Chip >= ATI_CHIP_18800) &&
+ (pATI->Adapter != ATI_ADAPTER_V4))
+
+#endif /* AVOID_CPIO */
+
+ {
+ /*
+ * Check for clocks that are specified in the wrong order.
+ * This is meant to catch those who are trying to use the
+ * clock order intended for the old accelerated servers.
+ */
+ while ((++ClockMap, ClockMap %= NumberOf(ClockMaps)))
+ {
+ pATI->Clock = ATIMatchClockLine(pScreenInfo, pATI,
+ SpecificationClockLine, NumberOfUndividedClocks,
+ -1, ClockMap);
+ if (pATI->Clock != ATI_CLOCK_NONE)
+ {
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex,
+ X_WARNING, 0,
+ "XF86Config clock ordering incorrect. Clocks"
+ " will be reordered.\n");
+ break;
+ }
+ }
+ }
+ }
+ else
+ /* Ensure crystals are not matched to clock chips, and vice versa */
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Chip <= ATI_CHIP_18800) ||
+ (pATI->Adapter == ATI_ADAPTER_V4))
+ {
+ if (pATI->Clock > ATI_CLOCK_CRYSTALS)
+ pATI->OptionProbeClocks = TRUE;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (pATI->Clock == ATI_CLOCK_CRYSTALS)
+ pATI->OptionProbeClocks = TRUE;
+ }
+
+ if (pATI->OptionProbeClocks)
+ {
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
+ "Invalid or obsolete XF86Config clocks line rejected.\n"
+ " Clocks will be probed.\n");
+ goto ProbeClocks;
+ }
+ }
+ }
+
+ if (pATI->ProgrammableClock != ATI_CLOCK_FIXED)
+ pATI->ProgrammableClock = ATI_CLOCK_FIXED;
+ else if (pATI->Clock == ATI_CLOCK_NONE)
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
+ "Unknown clock generator detected.\n");
+ else
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Clock == ATI_CLOCK_CRYSTALS)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "This adapter uses crystals to generate clock frequencies.\n");
+ else if (pATI->Clock != ATI_CLOCK_VGA)
+
+#endif /* AVOID_CPIO */
+
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s clock chip detected.\n", ATIClockNames[pATI->Clock]);
+ }
+
+ if (pATI->Clock != ATI_CLOCK_NONE)
+ {
+ /* Replace undivided clocks with specification values */
+ for (ClockIndex = 0;
+ ClockIndex < NumberOfUndividedClocks;
+ ClockIndex++)
+ {
+ /*
+ * Don't replace clocks that are probed, documented, or set by the
+ * user to zero. One exception is that we need to override the
+ * user's value for the spare settings on a crystal-based adapter.
+ * Another exception is when the user specifies the clock ordering
+ * intended for the old accelerated servers.
+ */
+ SpecificationClock =
+ SpecificationClockLine[pATI->Clock][ClockIndex];
+ if (SpecificationClock < 0)
+ break;
+ if (!ClockMap)
+ {
+ if (!pScreenInfo->clock[ClockIndex])
+ continue;
+ if (!SpecificationClock)
+ {
+ if (pATI->Clock != ATI_CLOCK_CRYSTALS)
+ continue;
+ }
+ else
+ {
+ /*
+ * Due to the way clock lines are matched, the following
+ * can prevent the override if the clock is probed,
+ * documented or set by the user to a value greater than
+ * maxClock.
+ */
+ if (abs(SpecificationClock -
+ pScreenInfo->clock[ClockIndex]) > CLOCK_TOLERANCE)
+ continue;
+ }
+ }
+ pScreenInfo->clock[ClockIndex] = SpecificationClock;
+ }
+
+ /* Adjust divided clocks */
+ for (ClockIndex = NumberOfUndividedClocks;
+ ClockIndex < NumberOfClocks;
+ ClockIndex++)
+ pScreenInfo->clock[ClockIndex] = ATIDivide(
+ pScreenInfo->clock[ClockIndex % NumberOfUndividedClocks],
+ (ClockIndex / NumberOfUndividedClocks) + 1, 0, 0);
+ }
+
+ /* Tell user about fixed clocks */
+ xf86ShowClocks(pScreenInfo, pATI->OptionProbeClocks ? X_PROBED : X_CONFIG);
+
+ /* Prevent selection of high clocks, even by V_CLKDIV2 modes */
+ for (ClockIndex = 0; ClockIndex < NumberOfClocks; ClockIndex++)
+ if (pScreenInfo->clock[ClockIndex] > pRange->maxClock)
+ pScreenInfo->clock[ClockIndex] = 0;
+}
+
+/*
+ * ATIClockSave --
+ *
+ * This function saves that part of an ATIHWRec that relates to clocks.
+ */
+void
+ATIClockSave
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ if (pScreenInfo->vtSema && (pATI->ProgrammableClock > ATI_CLOCK_FIXED))
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATIHW->crtc == ATI_CRTC_VGA)
+ {
+ pATIHW->ClockMap = ATIVGAProgrammableClockMap;
+ pATIHW->ClockUnmap = ATIVGAProgrammableClockUnmap;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->ClockMap = ATIProgrammableClockMap;
+ pATIHW->ClockUnmap = ATIProgrammableClockUnmap;
+ }
+ }
+ else
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATIHW->crtc != ATI_CRTC_VGA)
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->ClockMap = ATIAcceleratorClockMap;
+ pATIHW->ClockUnmap = ATIAcceleratorClockUnmap;
+ }
+
+#ifndef AVOID_CPIO
+
+ else if (pATI->Chip < ATI_CHIP_68800)
+ {
+ pATIHW->ClockMap = ATIVGAWonderClockMap;
+ pATIHW->ClockUnmap = ATIVGAWonderClockUnmap;
+ }
+ else
+ {
+ pATIHW->ClockMap = ATIMachVGAClockMap;
+ pATIHW->ClockUnmap = ATIMachVGAClockUnmap;
+ }
+
+#endif /* AVOID_CPIO */
+
+ }
+}
+
+/*
+ * ATIClockCalculate --
+ *
+ * This function is called to generate, if necessary, the data needed for clock
+ * programming, and set clock select bits in various register values.
+ */
+Bool
+ATIClockCalculate
+(
+ int iScreen,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ int N, M, D;
+ int ClockSelect, N1, MinimumGap;
+ int Frequency, Multiple; /* Used as temporaries */
+
+ /* Set default values */
+ pATIHW->FeedbackDivider = pATIHW->ReferenceDivider = pATIHW->PostDivider = 0;
+
+ if ((pATI->ProgrammableClock <= ATI_CLOCK_FIXED) ||
+ ((pATI->ProgrammableClock == ATI_CLOCK_CH8398) &&
+ (pMode->ClockIndex < 2)))
+ {
+ /* Use a fixed clock */
+ ClockSelect = pMode->ClockIndex;
+ }
+ else
+ {
+ /* Generate clock programme word, using units of kHz */
+ MinimumGap = ((unsigned int)(-1)) >> 1;
+
+ /* Loop through reference dividers */
+ for (M = pATI->ClockDescriptor.MinM;
+ M <= pATI->ClockDescriptor.MaxM;
+ M++)
+ {
+ /* Loop through post-dividers */
+ for (D = 0; D < pATI->ClockDescriptor.NumD; D++)
+ {
+ if (!pATI->ClockDescriptor.PostDividers[D])
+ continue;
+
+ /* Limit undivided VCO to maxClock */
+ if (pATI->maxClock &&
+ ((pATI->maxClock / pATI->ClockDescriptor.PostDividers[D]) <
+ pMode->Clock))
+ continue;
+
+ /*
+ * Calculate closest feedback divider and apply its
+ * restrictions.
+ */
+ Multiple = M * pATI->ReferenceDenominator *
+ pATI->ClockDescriptor.PostDividers[D];
+ N = ATIDivide(pMode->Clock * Multiple,
+ pATI->ReferenceNumerator, 0, 0);
+ if (N < pATI->ClockDescriptor.MinN)
+ N = pATI->ClockDescriptor.MinN;
+ else if (N > pATI->ClockDescriptor.MaxN)
+ N = pATI->ClockDescriptor.MaxN;
+ N -= pATI->ClockDescriptor.NAdjust;
+ N1 = (N / pATI->ClockDescriptor.N1) * pATI->ClockDescriptor.N2;
+ if (N > N1)
+ N = ATIDivide(N1 + 1, pATI->ClockDescriptor.N1, 0, 1);
+ N += pATI->ClockDescriptor.NAdjust;
+ N1 += pATI->ClockDescriptor.NAdjust;
+
+ for (; ; N = N1)
+ {
+ /* Pick the closest setting */
+ Frequency = abs(ATIDivide(N * pATI->ReferenceNumerator,
+ Multiple, 0, 0) - pMode->Clock);
+ if ((Frequency < MinimumGap) ||
+ ((Frequency == MinimumGap) &&
+ (pATIHW->FeedbackDivider < N)))
+ {
+ /* Save settings */
+ pATIHW->FeedbackDivider = N;
+ pATIHW->ReferenceDivider = M;
+ pATIHW->PostDivider = D;
+ MinimumGap = Frequency;
+ }
+
+ if (N <= N1)
+ break;
+ }
+ }
+ }
+
+ Multiple = pATIHW->ReferenceDivider * pATI->ReferenceDenominator *
+ pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider];
+ Frequency = pATIHW->FeedbackDivider * pATI->ReferenceNumerator;
+ Frequency = ATIDivide(Frequency, Multiple, 0, 0);
+ if (abs(Frequency - pMode->Clock) > CLOCK_TOLERANCE)
+ {
+ xf86DrvMsg(iScreen, X_ERROR,
+ "Unable to programme clock %.3fMHz for mode %s.\n",
+ (double)(pMode->Clock) / 1000.0, pMode->name);
+ return FALSE;
+ }
+ pMode->SynthClock = Frequency;
+ ClockSelect = pATI->ClockNumberToProgramme;
+
+ xf86ErrorFVerb(4,
+ "\n Programming clock %d to %.3fMHz for mode %s."
+ " N=%d, M=%d, D=%d.\n",
+ ClockSelect, (double)Frequency / 1000.0, pMode->name,
+ pATIHW->FeedbackDivider, pATIHW->ReferenceDivider,
+ pATIHW->PostDivider);
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ ATIDSPCalculate(pATI, pATIHW, pMode);
+ }
+
+ /* Set clock select bits, after remapping them */
+ pATIHW->clock = ClockSelect; /* Save pre-map clock number */
+ ClockSelect = MapClockIndex(pATIHW->ClockMap, ClockSelect);
+
+ switch (pATIHW->crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ pATIHW->genmo = (pATIHW->genmo & 0xF3U) |
+ ((ClockSelect << 2) & 0x0CU);
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ /* Set ATI clock select bits */
+ if (pATI->Chip <= ATI_CHIP_18800)
+ pATIHW->b2 = (pATIHW->b2 & 0xBFU) |
+ ((ClockSelect << 4) & 0x40U);
+ else
+ {
+ pATIHW->be = (pATIHW->be & 0xEFU) |
+ ((ClockSelect << 2) & 0x10U);
+ if (pATI->Adapter != ATI_ADAPTER_V4)
+ {
+ ClockSelect >>= 1;
+ pATIHW->b9 = (pATIHW->b9 & 0xFDU) |
+ ((ClockSelect >> 1) & 0x02U);
+ }
+ }
+
+ /* Set clock divider bits */
+ pATIHW->b8 = (pATIHW->b8 & 0x3FU) |
+ ((ClockSelect << 3) & 0xC0U);
+ }
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ pATIHW->clock_cntl = CLOCK_STROBE |
+ SetBits(ClockSelect, CLOCK_SELECT | CLOCK_DIVIDER);
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/*
+ * ATIClockSet --
+ *
+ * This function is called to programme a clock for the mode being set.
+ */
+void
+ATIClockSet
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ CARD32 crtc_gen_cntl, tmp;
+ CARD8 clock_cntl0;
+ CARD8 tmp2;
+ unsigned int Programme;
+ int N = pATIHW->FeedbackDivider - pATI->ClockDescriptor.NAdjust;
+ int M = pATIHW->ReferenceDivider - pATI->ClockDescriptor.MAdjust;
+ int D = pATIHW->PostDivider;
+
+ /* Temporarily switch to accelerator mode */
+ crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
+
+ switch (pATI->ProgrammableClock)
+ {
+ case ATI_CLOCK_ICS2595:
+ clock_cntl0 = in8(CLOCK_CNTL);
+
+ Programme = (SetBits(pATIHW->clock, ICS2595_CLOCK) |
+ SetBits(N, ICS2595_FB_DIV) | SetBits(D, ICS2595_POST_DIV)) ^
+ ICS2595_TOGGLE;
+
+ ATIDelay(50000); /* 50 milliseconds */
+
+ (void)xf86DisableInterrupts();
+
+ /* Send all 20 bits of programme word */
+ while (Programme >= CLOCK_BIT)
+ {
+ tmp = (Programme & CLOCK_BIT) | CLOCK_STROBE;
+ out8(CLOCK_CNTL, tmp);
+ ATIDelay(26); /* 26 microseconds */
+ out8(CLOCK_CNTL, tmp | CLOCK_PULSE);
+ ATIDelay(26); /* 26 microseconds */
+ Programme >>= 1;
+ }
+
+ xf86EnableInterrupts();
+
+ /* Restore register */
+ out8(CLOCK_CNTL, clock_cntl0 | CLOCK_STROBE);
+ break;
+
+ case ATI_CLOCK_STG1703:
+ (void)ATIGetDACCmdReg(pATI);
+ (void)in8(M64_DAC_MASK);
+ out8(M64_DAC_MASK, (pATIHW->clock << 1) + 0x20U);
+ out8(M64_DAC_MASK, 0);
+ out8(M64_DAC_MASK, SetBits(N, 0xFFU));
+ out8(M64_DAC_MASK, SetBits(M, 0x1FU) | SetBits(D, 0xE0U));
+ break;
+
+ case ATI_CLOCK_CH8398:
+ tmp = inr(DAC_CNTL) | (DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
+ outr(DAC_CNTL, tmp);
+ out8(M64_DAC_WRITE, pATIHW->clock);
+ out8(M64_DAC_DATA, SetBits(N, 0xFFU));
+ out8(M64_DAC_DATA, SetBits(M, 0x3FU) | SetBits(D, 0xC0U));
+ out8(M64_DAC_MASK, 0x04U);
+ outr(DAC_CNTL, tmp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3));
+ tmp2 = in8(M64_DAC_WRITE);
+ out8(M64_DAC_WRITE, (tmp2 & 0x70U) | 0x80U);
+ outr(DAC_CNTL, tmp & ~DAC_EXT_SEL_RS2);
+ break;
+
+ case ATI_CLOCK_INTERNAL:
+ /* Reset VCLK generator */
+ ATIPutMach64PLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl);
+
+ /* Set post-divider */
+ tmp2 = pATIHW->clock << 1;
+ tmp = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV);
+ tmp &= ~(0x03U << tmp2);
+ tmp |= SetBits(D, 0x03U) << tmp2;
+ ATIPutMach64PLLReg(PLL_VCLK_POST_DIV, tmp);
+
+ /* Set extended post-divider */
+ tmp = ATIGetMach64PLLReg(PLL_XCLK_CNTL);
+ tmp &= ~(SetBits(1, PLL_VCLK0_XDIV) << pATIHW->clock);
+ tmp |= SetBits(D >> 2, PLL_VCLK0_XDIV) << pATIHW->clock;
+ ATIPutMach64PLLReg(PLL_XCLK_CNTL, tmp);
+
+ /* Set feedback divider */
+ tmp = PLL_VCLK0_FB_DIV + pATIHW->clock;
+ ATIPutMach64PLLReg(tmp, SetBits(N, 0xFFU));
+
+ /* End VCLK generator reset */
+ ATIPutMach64PLLReg(PLL_VCLK_CNTL,
+ pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET);
+
+ /* Reset write bit */
+ ATIAccessMach64PLLReg(pATI, 0, FALSE);
+ break;
+
+ case ATI_CLOCK_ATT20C408:
+ (void)ATIGetDACCmdReg(pATI);
+ tmp = in8(M64_DAC_MASK);
+ (void)ATIGetDACCmdReg(pATI);
+ out8(M64_DAC_MASK, tmp | 1);
+ out8(M64_DAC_WRITE, 1);
+ out8(M64_DAC_MASK, tmp | 9);
+ ATIDelay(400); /* 400 microseconds */
+ tmp2 = (pATIHW->clock << 2) + 0x40U;
+ out8(M64_DAC_WRITE, tmp2);
+ out8(M64_DAC_MASK, SetBits(N, 0xFFU));
+ out8(M64_DAC_WRITE, ++tmp2);
+ out8(M64_DAC_MASK, SetBits(M, 0x3FU) | SetBits(D, 0xC0U));
+ out8(M64_DAC_WRITE, ++tmp2);
+ out8(M64_DAC_MASK, 0x77U);
+ ATIDelay(400); /* 400 microseconds */
+ out8(M64_DAC_WRITE, 1);
+ out8(M64_DAC_MASK, tmp);
+ break;
+
+ case ATI_CLOCK_IBMRGB514:
+ /*
+ * Here, only update in-core data. It will be written out later by
+ * ATIRGB514Set().
+ */
+ tmp = (pATIHW->clock << 1) + 0x20U;
+ pATIHW->ibmrgb514[tmp] =
+ (SetBits(N, 0x3FU) | SetBits(D, 0xC0U)) ^ 0xC0U;
+ pATIHW->ibmrgb514[tmp + 1] = SetBits(M, 0x3FU);
+ break;
+
+ default:
+ break;
+ }
+
+ (void)in8(M64_DAC_WRITE); /* Clear DAC counter */
+
+ /* Restore register */
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl);
+}
diff --git a/src/aticlock.h b/src/aticlock.h
new file mode 100644
index 0000000..641ba69
--- /dev/null
+++ b/src/aticlock.h
@@ -0,0 +1,86 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticlock.h,v 1.8 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICLOCK_H___
+#define ___ATICLOCK_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+/*
+ * Definitions related to non-programmable clock generators.
+ */
+typedef enum
+{
+ ATI_CLOCK_NONE = 0,
+ ATI_CLOCK_VGA = 1,
+ ATI_CLOCK_CRYSTALS = 2,
+ ATI_CLOCK_18810,
+ ATI_CLOCK_18811_0,
+ ATI_CLOCK_18811_1,
+ ATI_CLOCK_2494AM,
+ ATI_CLOCK_MACH64A,
+ ATI_CLOCK_MACH64B,
+ ATI_CLOCK_MACH64C
+} ATIClockType;
+extern const char *ATIClockNames[];
+
+/*
+ * Definitions related to programmable clock generators.
+ */
+typedef enum
+{
+ ATI_CLOCK_UNKNOWN = -1,
+ ATI_CLOCK_FIXED = 0, /* Further described by ATIClockType */
+ ATI_CLOCK_ICS2595,
+ ATI_CLOCK_STG1703,
+ ATI_CLOCK_CH8398,
+ ATI_CLOCK_INTERNAL,
+ ATI_CLOCK_ATT20C408,
+ ATI_CLOCK_IBMRGB514,
+ ATI_CLOCK_MAX /* Must be last */
+} ATIProgrammableClockType;
+
+typedef struct
+{
+ CARD16 MinN, MaxN; /* Feedback divider and ... */
+ CARD16 NAdjust; /* ... its adjustment and ... */
+ CARD16 N1, N2; /* ... its restrictions */
+ CARD16 MinM, MaxM; /* Reference divider and ... */
+ CARD16 MAdjust; /* ... its adjustment */
+ CARD16 NumD, *PostDividers; /* Post-dividers */
+ const char *ClockName;
+} ClockRec, *ClockPtr;
+extern ClockRec ATIClockDescriptors[];
+
+extern void ATIClockPreInit FunctionPrototype((ScrnInfoPtr, ATIPtr, GDevPtr,
+ ClockRangePtr));
+extern void ATIClockSave FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+extern Bool ATIClockCalculate FunctionPrototype((int, ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIClockSet FunctionPrototype((ATIPtr, ATIHWPtr));
+
+#endif /* ___ATICLOCK_H___ */
diff --git a/src/aticonfig.c b/src/aticonfig.c
new file mode 100644
index 0000000..b0aa2be
--- /dev/null
+++ b/src/aticonfig.c
@@ -0,0 +1,244 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonfig.c,v 1.12 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "aticonfig.h"
+#include "aticursor.h"
+#include "atioption.h"
+#include "atistruct.h"
+
+/*
+ * Non-publicised XF86Config options.
+ */
+typedef enum
+{
+ ATI_OPTION_CRT_SCREEN, /* Legacy negation of "PanelDisplay" */
+ ATI_OPTION_DEVEL, /* Intentionally undocumented */
+ ATI_OPTION_BLEND, /* Force horizontal blending of small modes */
+ ATI_OPTION_SYNC /* Use XF86Config panel mode porches */
+} ATIPrivateOptionType;
+
+/*
+ * ATIProcessOptions --
+ *
+ * This function extracts options from what was parsed out of the XF86Config
+ * file.
+ */
+void
+ATIProcessOptions
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ OptionInfoPtr PublicOption = xnfalloc(ATIPublicOptionSize);
+ OptionInfoRec PrivateOption[] =
+ {
+ { /* Negation of "PanelDisplay" public option */
+ ATI_OPTION_CRT_SCREEN,
+ "crtscreen",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ { /* ON: Horizontally blend most modes */
+ ATI_OPTION_BLEND, /* OFF: Use pixel replication more often */
+ "lcdblend",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ { /* ON: Use XF86Config porch timings */
+ ATI_OPTION_SYNC, /* OFF: Use porches from mode on entry */
+ "lcdsync",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ { /* ON: Ease exploration of loose ends */
+ ATI_OPTION_DEVEL, /* OFF: Fit for public consumption */
+ "tsi",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ -1,
+ NULL,
+ OPTV_NONE,
+ {0, },
+ FALSE
+ }
+ };
+
+ (void)memcpy(PublicOption, ATIPublicOptions, ATIPublicOptionSize);
+
+# define Accel PublicOption[ATI_OPTION_ACCEL].value.bool
+# define Blend PrivateOption[ATI_OPTION_BLEND].value.bool
+# define CRTDisplay PublicOption[ATI_OPTION_CRT_DISPLAY].value.bool
+# define CRTScreen PrivateOption[ATI_OPTION_CRT_SCREEN].value.bool
+# define CSync PublicOption[ATI_OPTION_CSYNC].value.bool
+# define Devel PrivateOption[ATI_OPTION_DEVEL].value.bool
+# define HWCursor PublicOption[ATI_OPTION_HWCURSOR].value.bool
+
+#ifndef AVOID_CPIO
+
+# define Linear PublicOption[ATI_OPTION_LINEAR].value.bool
+
+#endif /* AVOID_CPIO */
+
+# define CacheMMIO PublicOption[ATI_OPTION_MMIO_CACHE].value.bool
+# define PanelDisplay PublicOption[ATI_OPTION_PANEL_DISPLAY].value.bool
+# define ProbeClocks PublicOption[ATI_OPTION_PROBE_CLOCKS].value.bool
+# define ShadowFB PublicOption[ATI_OPTION_SHADOW_FB].value.bool
+# define SWCursor PublicOption[ATI_OPTION_SWCURSOR].value.bool
+# define Sync PrivateOption[ATI_OPTION_SYNC].value.bool
+
+# define ReferenceClock \
+ PublicOption[ATI_OPTION_REFERENCE_CLOCK].value.freq.freq
+
+ /* Pick up XF86Config options */
+ xf86CollectOptions(pScreenInfo, NULL);
+
+ /* Set non-zero defaults */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH64)
+
+#endif /* AVOID_CPIO */
+
+ {
+ Accel = CacheMMIO = HWCursor = TRUE;
+
+#ifndef AVOID_CPIO
+
+ Linear = TRUE;
+
+#endif /* AVOID_CPIO */
+
+ }
+
+ ReferenceClock = ((double)157500000.0) / ((double)11.0);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->PCIInfo)
+
+#endif /* AVOID_CPIO */
+
+ {
+ ShadowFB = TRUE;
+ }
+
+ Blend = PanelDisplay = TRUE;
+
+ xf86ProcessOptions(pScreenInfo->scrnIndex, pScreenInfo->options,
+ PublicOption);
+ xf86ProcessOptions(pScreenInfo->scrnIndex, pScreenInfo->options,
+ PrivateOption);
+
+#ifndef AVOID_CPIO
+
+ /* Disable linear apertures if the OS doesn't support them */
+ if (!xf86LinearVidMem() && Linear)
+ {
+ if (PublicOption[ATI_OPTION_LINEAR].found)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "OS does not support linear apertures.\n");
+ Linear = FALSE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Move option values into driver private structure */
+ pATI->OptionAccel = Accel;
+ pATI->OptionBlend = Blend;
+ pATI->OptionCRTDisplay = CRTDisplay;
+ pATI->OptionCSync = CSync;
+ pATI->OptionDevel = Devel;
+
+#ifndef AVOID_CPIO
+
+ pATI->OptionLinear = Linear;
+
+#endif /* AVOID_CPIO */
+
+ pATI->OptionMMIOCache = CacheMMIO;
+ pATI->OptionProbeClocks = ProbeClocks;
+ pATI->OptionShadowFB = ShadowFB;
+ pATI->OptionSync = Sync;
+
+ /* "CRTScreen" is now "NoPanelDisplay" */
+ if ((PanelDisplay != CRTScreen) ||
+ PublicOption[ATI_OPTION_PANEL_DISPLAY].found)
+ pATI->OptionPanelDisplay = PanelDisplay;
+ else
+ pATI->OptionPanelDisplay = !CRTScreen;
+
+ /* Validate and set cursor options */
+ pATI->Cursor = ATI_CURSOR_SOFTWARE;
+ if (SWCursor || !HWCursor)
+ {
+ if (HWCursor && PublicOption[ATI_OPTION_HWCURSOR].found)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Option \"sw_cursor\" overrides Option \"hw_cursor\".\n");
+ }
+ else if (pATI->Chip < ATI_CHIP_264CT)
+ {
+ if (HWCursor && PublicOption[ATI_OPTION_HWCURSOR].found)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Option \"hw_cursor\" not supported in this configuration.\n");
+ }
+ else
+ {
+ pATI->Cursor = ATI_CURSOR_HARDWARE;
+ }
+
+ /* Only set the reference clock if it hasn't already been determined */
+ if (!pATI->ReferenceNumerator || !pATI->ReferenceDenominator)
+ {
+ switch ((int)(ReferenceClock / ((double)100000.0)))
+ {
+ case 143:
+ pATI->ReferenceNumerator = 157500;
+ pATI->ReferenceDenominator = 11;
+ break;
+
+ case 286:
+ pATI->ReferenceNumerator = 315000;
+ pATI->ReferenceDenominator = 11;
+ break;
+
+ default:
+ pATI->ReferenceNumerator =
+ (int)(ReferenceClock / ((double)1000.0));
+ pATI->ReferenceDenominator = 1;
+ break;
+ }
+ }
+
+ xfree(PublicOption);
+}
diff --git a/src/aticonfig.h b/src/aticonfig.h
new file mode 100644
index 0000000..bf9c24b
--- /dev/null
+++ b/src/aticonfig.h
@@ -0,0 +1,34 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonfig.h,v 1.5 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICONFIG_H___
+#define ___ATICONFIG_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern void ATIProcessOptions FunctionPrototype((ScrnInfoPtr, ATIPtr));
+
+#endif /* ___ATICONFIG_H___ */
diff --git a/src/aticonsole.c b/src/aticonsole.c
new file mode 100644
index 0000000..cdd91f4
--- /dev/null
+++ b/src/aticonsole.c
@@ -0,0 +1,360 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.c,v 1.20 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiadapter.h"
+#include "aticonsole.h"
+#include "aticrtc.h"
+#include "atilock.h"
+#include "atimach64.h"
+#include "atimode.h"
+#include "atistruct.h"
+#include "ativga.h"
+#include "atividmem.h"
+
+#include "xf86.h"
+
+/*
+ * ATISaveScreen --
+ *
+ * This function is a screen saver hook for DIX.
+ */
+Bool
+ATISaveScreen
+(
+ ScreenPtr pScreen,
+ int Mode
+)
+{
+ ScrnInfoPtr pScreenInfo;
+ ATIPtr pATI;
+
+ if ((Mode != SCREEN_SAVER_ON) && (Mode != SCREEN_SAVER_CYCLE))
+ SetTimeSinceLastInputEvent();
+
+ if (!pScreen)
+ return TRUE;
+
+ pScreenInfo = xf86Screens[pScreen->myNum];
+ if (!pScreenInfo->vtSema)
+ return TRUE;
+
+ pATI = ATIPTR(pScreenInfo);
+ switch (pATI->NewHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ ATIVGASaveScreen(pATI, Mode);
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ ATIMach64SaveScreen(pATI, Mode);
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/*
+ * ATISetDPMSMode --
+ *
+ * This function sets the adapter's VESA Display Power Management Signaling
+ * mode.
+ */
+void
+ATISetDPMSMode
+(
+ ScrnInfoPtr pScreenInfo,
+ int DPMSMode,
+ int flags
+)
+{
+ ATIPtr pATI;
+
+ if (!pScreenInfo || !pScreenInfo->vtSema)
+ return;
+
+ pATI = ATIPTR(pScreenInfo);
+
+ switch (pATI->Adapter)
+ {
+ case ATI_ADAPTER_MACH64:
+ ATIMach64SetDPMSMode(pScreenInfo, pATI, DPMSMode);
+ break;
+
+ default:
+
+#ifndef AVOID_CPIO
+
+ /* Assume EGA/VGA */
+ ATIVGASetDPMSMode(pATI, DPMSMode);
+ break;
+
+ case ATI_ADAPTER_NONE:
+ case ATI_ADAPTER_8514A:
+ case ATI_ADAPTER_MACH8:
+
+#endif /* AVOID_CPIO */
+
+ break;
+ }
+}
+
+/*
+ * ATIEnterGraphics --
+ *
+ * This function sets the hardware to a graphics video state.
+ */
+Bool
+ATIEnterGraphics
+(
+ ScreenPtr pScreen,
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ /* Map apertures */
+ if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
+ return FALSE;
+
+ /* Unlock device */
+ ATIUnlock(pATI);
+
+ /* Calculate hardware data */
+ if (pScreen &&
+ !ATIModeCalculate(pScreenInfo->scrnIndex, pATI, &pATI->NewHW,
+ pScreenInfo->currentMode))
+ return FALSE;
+
+ pScreenInfo->vtSema = TRUE;
+
+ /* Save current state */
+ ATIModeSave(pScreenInfo, pATI, &pATI->OldHW);
+
+ /* Set graphics state */
+ ATIModeSet(pScreenInfo, pATI, &pATI->NewHW);
+
+ /* Possibly blank the screen */
+ if (pScreen)
+ (void)ATISaveScreen(pScreen, SCREEN_SAVER_ON);
+
+ /* Position the screen */
+ (*pScreenInfo->AdjustFrame)(pScreenInfo->scrnIndex,
+ pScreenInfo->frameX0, pScreenInfo->frameY0, 0);
+
+ SetTimeSinceLastInputEvent();
+
+ return TRUE;
+}
+
+/*
+ * ATILeaveGraphics --
+ *
+ * This function restores the hardware to its previous state.
+ */
+void
+ATILeaveGraphics
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ if (pScreenInfo->vtSema)
+ {
+ /* If not exiting, save graphics video state */
+ if (!xf86ServerIsExiting())
+ ATIModeSave(pScreenInfo, pATI, &pATI->NewHW);
+
+ /* Restore mode in effect on server entry */
+ ATIModeSet(pScreenInfo, pATI, &pATI->OldHW);
+
+ pScreenInfo->vtSema = FALSE;
+ }
+
+ /* Lock device */
+ ATILock(pATI);
+
+ /* Unmap apertures */
+
+#ifdef AVOID_DGA
+
+ if (!pATI->Closeable)
+
+#else /* AVOID_DGA */
+
+ if (!pATI->Closeable || !pATI->nDGAMode)
+
+#endif /* AVOID_DGA */
+
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+
+ SetTimeSinceLastInputEvent();
+}
+
+/*
+ * ATISwitchMode --
+ *
+ * This function switches to another graphics video state.
+ */
+Bool
+ATISwitchMode
+(
+ int iScreen,
+ DisplayModePtr pMode,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ /* Calculate new hardware data */
+ if (!ATIModeCalculate(iScreen, pATI, &pATI->NewHW, pMode))
+ return FALSE;
+
+ /* Set new hardware state */
+ if (pScreenInfo->vtSema)
+ {
+ pScreenInfo->currentMode = pMode;
+ ATIModeSet(pScreenInfo, pATI, &pATI->NewHW);
+ }
+
+ SetTimeSinceLastInputEvent();
+
+ return TRUE;
+}
+
+/*
+ * ATIEnterVT --
+ *
+ * This function sets the server's virtual console to a graphics video state.
+ */
+Bool
+ATIEnterVT
+(
+ int iScreen,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ScreenPtr pScreen = pScreenInfo->pScreen;
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ PixmapPtr pScreenPixmap;
+ DevUnion PixmapPrivate;
+ Bool Entered;
+
+ if (!ATIEnterGraphics(NULL, pScreenInfo, pATI))
+ return FALSE;
+
+ /* The rest of this isn't needed for shadowfb */
+ if (pATI->OptionShadowFB)
+ return TRUE;
+
+#ifndef AVOID_CPIO
+
+ /* If used, modify banking interface */
+ if (!miModifyBanking(pScreen, &pATI->BankInfo))
+ return FALSE;
+
+#endif /* AVOID_CPIO */
+
+ pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
+ PixmapPrivate = pScreenPixmap->devPrivate;
+ if (!PixmapPrivate.ptr)
+ pScreenPixmap->devPrivate = pScreenInfo->pixmapPrivate;
+
+ /* Tell framebuffer about remapped aperture */
+ Entered = (*pScreen->ModifyPixmapHeader)(pScreenPixmap,
+ -1, -1, -1, -1, -1, pATI->pMemory);
+
+ if (!PixmapPrivate.ptr)
+ {
+ pScreenInfo->pixmapPrivate = pScreenPixmap->devPrivate;
+ pScreenPixmap->devPrivate.ptr = NULL;
+ }
+
+ return Entered;
+}
+
+/*
+ * ATILeaveVT --
+ *
+ * This function restores the server's virtual console to its state on server
+ * entry.
+ */
+void
+ATILeaveVT
+(
+ int iScreen,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+
+ ATILeaveGraphics(pScreenInfo, ATIPTR(pScreenInfo));
+}
+
+/*
+ * ATIFreeScreen --
+ *
+ * This function frees all driver data related to a screen.
+ */
+void
+ATIFreeScreen
+(
+ int iScreen,
+ int flags
+)
+{
+ ScreenPtr pScreen = screenInfo.screens[iScreen];
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->Closeable)
+ (void)(*pScreen->CloseScreen)(iScreen, pScreen);
+
+ ATILeaveGraphics(pScreenInfo, pATI);
+
+#ifndef AVOID_CPIO
+
+ xfree(pATI->OldHW.frame_buffer);
+ xfree(pATI->NewHW.frame_buffer);
+
+#endif /* AVOID_CPIO */
+
+ xfree(pATI->pShadow);
+
+#ifndef AVOID_DGA
+
+ xfree(pATI->pDGAMode);
+
+#endif /* AVOID_DGA */
+
+ xfree(pATI);
+ pScreenInfo->driverPrivate = NULL;
+}
diff --git a/src/aticonsole.h b/src/aticonsole.h
new file mode 100644
index 0000000..8157d83
--- /dev/null
+++ b/src/aticonsole.h
@@ -0,0 +1,46 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.h,v 1.9 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICONSOLE_H___
+#define ___ATICONSOLE_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATISaveScreen FunctionPrototype((ScreenPtr, int));
+extern void ATISetDPMSMode FunctionPrototype((ScrnInfoPtr, int, int));
+
+extern Bool ATIEnterGraphics FunctionPrototype((ScreenPtr, ScrnInfoPtr,
+ ATIPtr));
+extern void ATILeaveGraphics FunctionPrototype((ScrnInfoPtr, ATIPtr));
+
+extern Bool ATISwitchMode FunctionPrototype((int, DisplayModePtr, int));
+
+extern Bool ATIEnterVT FunctionPrototype((int, int));
+extern void ATILeaveVT FunctionPrototype((int, int));
+
+extern void ATIFreeScreen FunctionPrototype((int, int));
+
+#endif /* ___ATICONSOLE_H___ */
diff --git a/src/aticrtc.h b/src/aticrtc.h
new file mode 100644
index 0000000..9f6ec38
--- /dev/null
+++ b/src/aticrtc.h
@@ -0,0 +1,43 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticrtc.h,v 1.8 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICRTC_H___
+#define ___ATICRTC_H___ 1
+
+/*
+ * CRTC related definitions.
+ */
+typedef enum
+{
+
+#ifndef AVOID_CPIO
+
+ ATI_CRTC_VGA, /* Use VGA CRTC */
+ ATI_CRTC_8514, /* Use 8514/Mach8/Mach32 accelerator CRTC */
+
+#endif /* AVOID_CPIO */
+
+ ATI_CRTC_MACH64 /* Use Mach64 accelerator CRTC */
+} ATICRTCType;
+
+#endif /* ___ATICRTC_H___ */
diff --git a/src/aticursor.c b/src/aticursor.c
new file mode 100644
index 0000000..627b05e
--- /dev/null
+++ b/src/aticursor.c
@@ -0,0 +1,75 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticursor.c,v 1.3 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiadapter.h"
+#include "aticursor.h"
+#include "atimach64.h"
+#include "atistruct.h"
+
+#include "xf86.h"
+
+/*
+ * ATIInitializeCursor --
+ *
+ * This function initialises the screen cursor.
+ */
+Bool
+ATIInitializeCursor
+(
+ ScreenPtr pScreen,
+ ATIPtr pATI
+)
+{
+ /* Initialise software cursor */
+ if (!miDCInitialize(pScreen, xf86GetPointerScreenFuncs()))
+ return FALSE;
+
+ if (pATI->Cursor == ATI_CURSOR_SOFTWARE)
+ return TRUE;
+
+ if (!(pATI->pCursorInfo = xf86CreateCursorInfoRec()))
+ return FALSE;
+
+ switch (pATI->Adapter)
+ {
+ case ATI_ADAPTER_MACH64:
+ if (ATIMach64CursorInit(pATI->pCursorInfo))
+ break;
+ /* Fall through */
+
+ default:
+ xf86DestroyCursorInfoRec(pATI->pCursorInfo);
+ pATI->pCursorInfo = NULL;
+ return FALSE;
+ }
+
+ if (xf86InitCursor(pScreen, pATI->pCursorInfo))
+ {
+ xf86SetSilkenMouse(pScreen);
+ return TRUE;
+ }
+
+ xf86DestroyCursorInfoRec(pATI->pCursorInfo);
+ pATI->pCursorInfo = NULL;
+ return FALSE;
+}
diff --git a/src/aticursor.h b/src/aticursor.h
new file mode 100644
index 0000000..9f8790d
--- /dev/null
+++ b/src/aticursor.h
@@ -0,0 +1,44 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticursor.h,v 1.3 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATICURSOR_H___
+#define ___ATICURSOR_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "screenint.h"
+
+/*
+ * Cursor related definitions.
+ */
+typedef enum
+{
+ ATI_CURSOR_SOFTWARE, /* Software cursor */
+ ATI_CURSOR_HARDWARE, /* Hardware cursor provided by CRTC */
+ ATI_CURSOR_DAC /* Hardware cursor provided by RAMDAC */
+} ATICursorType;
+
+extern Bool ATIInitializeCursor FunctionPrototype((ScreenPtr, ATIPtr));
+
+#endif /* ___ATICURSOR_H___ */
diff --git a/src/atidac.c b/src/atidac.c
new file mode 100644
index 0000000..1d3e943
--- /dev/null
+++ b/src/atidac.c
@@ -0,0 +1,522 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidac.c,v 1.18 2003/02/25 17:58:13 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atidac.h"
+#include "atimach64io.h"
+#include "atimono.h"
+
+/*
+ * RAMDAC-related definitions.
+ */
+const SymTabRec ATIDACDescriptors[] =
+{ /* Keep this table in ascending DACType order */
+ {ATI_DAC_ATI68830, "ATI 68830 or similar"},
+ {ATI_DAC_SC11483, "Sierra 11483 or similar"},
+ {ATI_DAC_ATI68875, "ATI 68875 or similar"},
+ {ATI_DAC_TVP3026_A, "TI ViewPoint3026 or similar"},
+ {ATI_DAC_GENERIC, "Brooktree 476 or similar"},
+ {ATI_DAC_BT481, "Brooktree 481 or similar"},
+ {ATI_DAC_ATT20C491, "AT&T 20C491 or similar"},
+ {ATI_DAC_SC15026, "Sierra 15026 or similar"},
+ {ATI_DAC_MU9C1880, "Music 9C1880 or similar"},
+ {ATI_DAC_IMSG174, "Inmos G174 or similar"},
+ {ATI_DAC_ATI68860_B, "ATI 68860 (Revision B) or similar"},
+ {ATI_DAC_ATI68860_C, "ATI 68860 (Revision C) or similar"},
+ {ATI_DAC_TVP3026_B, "TI ViewPoint3026 or similar"},
+ {ATI_DAC_STG1700, "SGS-Thompson 1700 or similar"},
+ {ATI_DAC_ATT20C498, "AT&T 20C498 or similar"},
+ {ATI_DAC_STG1702, "SGS-Thompson 1702 or similar"},
+ {ATI_DAC_SC15021, "Sierra 15021 or similar"},
+ {ATI_DAC_ATT21C498, "AT&T 21C498 or similar"},
+ {ATI_DAC_STG1703, "SGS-Thompson 1703 or similar"},
+ {ATI_DAC_CH8398, "Chrontel 8398 or similar"},
+ {ATI_DAC_ATT20C408, "AT&T 20C408 or similar"},
+ {ATI_DAC_INTERNAL, "Internal"},
+ {ATI_DAC_IBMRGB514, "IBM RGB 514 or similar"},
+ {ATI_DAC_UNKNOWN, "Unknown"} /* Must be last */
+};
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATISetDACIOPorts --
+ *
+ * This function sets up DAC access I/O port numbers.
+ */
+void
+ATISetDACIOPorts
+(
+ ATIPtr pATI,
+ ATICRTCType crtc
+)
+{
+ switch (crtc)
+ {
+ case ATI_CRTC_VGA:
+ pATI->CPIO_DAC_DATA = VGA_DAC_DATA;
+ pATI->CPIO_DAC_MASK = VGA_DAC_MASK;
+ pATI->CPIO_DAC_READ = VGA_DAC_READ;
+ pATI->CPIO_DAC_WRITE = VGA_DAC_WRITE;
+ pATI->CPIO_DAC_WAIT = GENS1(pATI->CPIO_VGABase);
+ break;
+
+ case ATI_CRTC_8514:
+ pATI->CPIO_DAC_DATA = IBM_DAC_DATA;
+ pATI->CPIO_DAC_MASK = IBM_DAC_MASK;
+ pATI->CPIO_DAC_READ = IBM_DAC_READ;
+ pATI->CPIO_DAC_WRITE = IBM_DAC_WRITE;
+ pATI->CPIO_DAC_WAIT = pATI->CPIO_DAC_MASK;
+ break;
+
+ case ATI_CRTC_MACH64:
+ pATI->CPIO_DAC_DATA = ATIIOPort(DAC_REGS) + 1;
+ pATI->CPIO_DAC_MASK = ATIIOPort(DAC_REGS) + 2;
+ pATI->CPIO_DAC_READ = ATIIOPort(DAC_REGS) + 3;
+ pATI->CPIO_DAC_WRITE = ATIIOPort(DAC_REGS) + 0;
+ pATI->CPIO_DAC_WAIT = pATI->CPIOBase;
+ break;
+
+ default:
+ break;
+ }
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIGetDACCmdReg --
+ *
+ * Setup to access a RAMDAC's command register.
+ */
+CARD8
+ATIGetDACCmdReg
+(
+ ATIPtr pATI
+)
+{
+
+#ifdef AVOID_CPIO
+
+ (void)in8(M64_DAC_WRITE); /* Reset to PEL mode */
+ (void)in8(M64_DAC_MASK);
+ (void)in8(M64_DAC_MASK);
+ (void)in8(M64_DAC_MASK);
+ return in8(M64_DAC_MASK);
+
+#else /* AVOID_CPIO */
+
+ (void)inb(pATI->CPIO_DAC_WRITE); /* Reset to PEL mode */
+ (void)inb(pATI->CPIO_DAC_MASK);
+ (void)inb(pATI->CPIO_DAC_MASK);
+ (void)inb(pATI->CPIO_DAC_MASK);
+ return inb(pATI->CPIO_DAC_MASK);
+
+#endif /* AVOID_CPIO */
+
+}
+
+/*
+ * ATIDACPreInit --
+ *
+ * This function initialises the fields in an ATIHWRec that relate to DACs.
+ */
+void
+ATIDACPreInit
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index, Index2;
+ CARD8 maxColour = (1 << pATI->rgbBits) - 1;
+
+ pATIHW->dac_read = pATIHW->dac_write = 0x00U;
+ pATIHW->dac_mask = 0xFFU;
+
+ /*
+ * Set colour lookup table. The first entry has already been zeroed out.
+ */
+ if (pATI->depth > 8)
+ for (Index = 1; Index < (NumberOf(pATIHW->lut) / 3); Index++)
+ {
+ Index2 = Index * 3;
+ pATIHW->lut[Index2 + 0] =
+ pATIHW->lut[Index2 + 1] =
+ pATIHW->lut[Index2 + 2] = Index;
+ }
+ else
+ {
+ /*
+ * Initialise hardware colour map so that use of uninitialised
+ * software colour map entries can easily be seen. For 256-colour
+ * modes, this doesn't remain effective for very long...
+ */
+ pATIHW->lut[3] = pATIHW->lut[4] = pATIHW->lut[5] = 0xFFU;
+ for (Index = 2; Index < (NumberOf(pATIHW->lut) / 3); Index++)
+ {
+ Index2 = Index * 3;
+ pATIHW->lut[Index2 + 0] = maxColour;
+ pATIHW->lut[Index2 + 1] = 0x00U;
+ pATIHW->lut[Index2 + 2] = maxColour;
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth == 1)
+ {
+ rgb blackColour = pScreenInfo->display->blackColour,
+ whiteColour = pScreenInfo->display->whiteColour;
+
+ if (blackColour.red > maxColour)
+ blackColour.red = maxColour;
+ if (blackColour.green > maxColour)
+ blackColour.green = maxColour;
+ if (blackColour.blue > maxColour)
+ blackColour.blue = maxColour;
+ if (whiteColour.red > maxColour)
+ whiteColour.red = maxColour;
+ if (whiteColour.green > maxColour)
+ whiteColour.green = maxColour;
+ if (whiteColour.blue > maxColour)
+ whiteColour.blue = maxColour;
+
+ if ((blackColour.red == whiteColour.red) &&
+ (blackColour.green == whiteColour.green) &&
+ (blackColour.blue == whiteColour.blue))
+ {
+ blackColour.red ^= maxColour;
+ blackColour.green ^= maxColour;
+ blackColour.blue ^= maxColour;
+ }
+
+ pATIHW->lut[(MONO_BLACK * 3) + 0] = blackColour.red;
+ pATIHW->lut[(MONO_BLACK * 3) + 1] = blackColour.green;
+ pATIHW->lut[(MONO_BLACK * 3) + 2] = blackColour.blue;
+ pATIHW->lut[(MONO_WHITE * 3) + 0] = whiteColour.red;
+ pATIHW->lut[(MONO_WHITE * 3) + 1] = whiteColour.green;
+ pATIHW->lut[(MONO_WHITE * 3) + 2] = whiteColour.blue;
+ }
+
+ if (pATIHW->crtc == ATI_CRTC_VGA)
+ {
+ /* Initialise overscan to black */
+ Index = pATIHW->attr[17] * 3;
+ pATIHW->lut[Index + 0] =
+ pATIHW->lut[Index + 1] =
+ pATIHW->lut[Index + 2] = 0x00U;
+ }
+
+#endif /* AVOID_CPIO */
+
+ }
+}
+
+/*
+ * ATIDACSave --
+ *
+ * This function is called to save the current RAMDAC state into an ATIHWRec
+ * structure occurrence.
+ */
+void
+ATIDACSave
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index;
+
+#ifdef AVOID_CPIO
+
+ pATIHW->dac_read = in8(M64_DAC_READ);
+ DACDelay;
+ pATIHW->dac_write = in8(M64_DAC_WRITE);
+ DACDelay;
+ pATIHW->dac_mask = in8(M64_DAC_MASK);
+ DACDelay;
+
+ /* Save DAC's colour lookup table */
+ out8(M64_DAC_MASK, 0xFFU);
+ DACDelay;
+ out8(M64_DAC_READ, 0x00U);
+ DACDelay;
+ for (Index = 0; Index < NumberOf(pATIHW->lut); Index++)
+ {
+ pATIHW->lut[Index] = in8(M64_DAC_DATA);
+ DACDelay;
+ }
+
+ out8(M64_DAC_MASK, pATIHW->dac_mask);
+ DACDelay;
+ out8(M64_DAC_READ, pATIHW->dac_read);
+ DACDelay;
+
+#else /* AVOID_CPIO */
+
+ ATISetDACIOPorts(pATI, pATIHW->crtc);
+
+ pATIHW->dac_read = inb(pATI->CPIO_DAC_READ);
+ DACDelay;
+ pATIHW->dac_write = inb(pATI->CPIO_DAC_WRITE);
+ DACDelay;
+ pATIHW->dac_mask = inb(pATI->CPIO_DAC_MASK);
+ DACDelay;
+
+ /* Save DAC's colour lookup table */
+ outb(pATI->CPIO_DAC_MASK, 0xFFU);
+ DACDelay;
+ outb(pATI->CPIO_DAC_READ, 0x00U);
+ DACDelay;
+ for (Index = 0; Index < NumberOf(pATIHW->lut); Index++)
+ {
+ pATIHW->lut[Index] = inb(pATI->CPIO_DAC_DATA);
+ DACDelay;
+ }
+
+ outb(pATI->CPIO_DAC_MASK, pATIHW->dac_mask);
+ DACDelay;
+ outb(pATI->CPIO_DAC_READ, pATIHW->dac_read);
+ DACDelay;
+
+#endif /* AVOID_CPIO */
+
+}
+
+/*
+ * ATIDACSet --
+ *
+ * This function loads RAMDAC data from an ATIHWRec structure occurrence.
+ */
+void
+ATIDACSet
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index;
+
+#ifdef AVOID_CPIO
+
+ /* Load DAC's colour lookup table */
+ out8(M64_DAC_MASK, 0xFFU);
+ DACDelay;
+ out8(M64_DAC_WRITE, 0x00U);
+ DACDelay;
+ for (Index = 0; Index < NumberOf(pATIHW->lut); Index++)
+ {
+ out8(M64_DAC_DATA, pATIHW->lut[Index]);
+ DACDelay;
+ }
+
+ out8(M64_DAC_MASK, pATIHW->dac_mask);
+ DACDelay;
+ out8(M64_DAC_READ, pATIHW->dac_read);
+ DACDelay;
+ out8(M64_DAC_WRITE, pATIHW->dac_write);
+ DACDelay;
+
+#else /* AVOID_CPIO */
+
+ ATISetDACIOPorts(pATI, pATIHW->crtc);
+
+ /* Load DAC's colour lookup table */
+ outb(pATI->CPIO_DAC_MASK, 0xFFU);
+ DACDelay;
+ outb(pATI->CPIO_DAC_WRITE, 0x00U);
+ DACDelay;
+ for (Index = 0; Index < NumberOf(pATIHW->lut); Index++)
+ {
+ outb(pATI->CPIO_DAC_DATA, pATIHW->lut[Index]);
+ DACDelay;
+ }
+
+ outb(pATI->CPIO_DAC_MASK, pATIHW->dac_mask);
+ DACDelay;
+ outb(pATI->CPIO_DAC_READ, pATIHW->dac_read);
+ DACDelay;
+ outb(pATI->CPIO_DAC_WRITE, pATIHW->dac_write);
+ DACDelay;
+
+#endif /* AVOID_CPIO */
+
+}
+
+/*
+ * ATILoadPalette --
+ *
+ * This function updates the RAMDAC's LUT and the in-memory copy of it in
+ * NewHW.
+ */
+void
+ATILoadPalette
+(
+ ScrnInfoPtr pScreenInfo,
+ int nColours,
+ int *Indices,
+ LOCO *Colours,
+ VisualPtr pVisual
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ CARD8 *LUTEntry;
+ int i, j, Index;
+
+ if (((pVisual->class | DynamicClass) == DirectColor) &&
+ ((1 << pVisual->nplanes) > (SizeOf(pATI->NewHW.lut) / 3)))
+ {
+ int reds = pVisual->redMask >> pVisual->offsetRed;
+ int greens = pVisual->greenMask >> pVisual->offsetGreen;
+ int blues = pVisual->blueMask >> pVisual->offsetBlue;
+
+ int redShift = 8 - pATI->weight.red;
+ int greenShift = 8 - pATI->weight.green;
+ int blueShift = 8 - pATI->weight.blue;
+
+ int redMult = 3 << redShift;
+ int greenMult = 3 << greenShift;
+ int blueMult = 3 << blueShift;
+
+ int minShift;
+
+ CARD8 fChanged[SizeOf(pATI->NewHW.lut) / 3];
+
+ (void)memset(fChanged, SizeOf(fChanged), 0);
+
+ minShift = redShift;
+ if (minShift > greenShift)
+ minShift = greenShift;
+ if (minShift > blueShift)
+ minShift = blueShift;
+
+ for (i = 0; i < nColours; i++)
+ {
+ if((Index = Indices[i]) < 0)
+ continue;
+
+ if (Index <= reds)
+ {
+ j = Index * redMult;
+ pATI->NewHW.lut[j + 0] = Colours[Index].red;
+ fChanged[j / 3] = TRUE;
+ }
+ if (Index <= greens)
+ {
+ j = Index * greenMult;
+ pATI->NewHW.lut[j + 1] = Colours[Index].green;
+ fChanged[j / 3] = TRUE;
+ }
+ if (Index <= blues)
+ {
+ j = Index * blueMult;
+ pATI->NewHW.lut[j + 2] = Colours[Index].blue;
+ fChanged[j / 3] = TRUE;
+ }
+ }
+
+ if (pScreenInfo->vtSema || pATI->currentMode)
+ {
+ /* Rewrite LUT entries that could have been changed */
+ i = 1 << minShift;
+ LUTEntry = pATI->NewHW.lut;
+
+ for (Index = 0;
+ Index < (SizeOf(pATI->NewHW.lut) / 3);
+ Index += i, LUTEntry += i * 3)
+ {
+ if (!fChanged[Index])
+ continue;
+
+#ifdef AVOID_CPIO
+
+ out8(M64_DAC_WRITE, Index);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[0]);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[1]);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[2]);
+ DACDelay;
+
+#else /* AVOID_CPIO */
+
+ outb(pATI->CPIO_DAC_WRITE, Index);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[0]);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[1]);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[2]);
+ DACDelay;
+
+#endif /* AVOID_CPIO */
+
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < nColours; i++)
+ {
+ Index = Indices[i];
+ if ((Index < 0) || (Index >= (SizeOf(pATI->NewHW.lut) / 3)))
+ continue;
+
+ LUTEntry = &pATI->NewHW.lut[Index * 3];
+ LUTEntry[0] = Colours[Index].red;
+ LUTEntry[1] = Colours[Index].green;
+ LUTEntry[2] = Colours[Index].blue;
+
+ if (pScreenInfo->vtSema || pATI->currentMode)
+ {
+
+#ifdef AVOID_CPIO
+
+ out8(M64_DAC_WRITE, Index);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[0]);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[1]);
+ DACDelay;
+ out8(M64_DAC_DATA, LUTEntry[2]);
+ DACDelay;
+
+#else /* AVOID_CPIO */
+
+ outb(pATI->CPIO_DAC_WRITE, Index);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[0]);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[1]);
+ DACDelay;
+ outb(pATI->CPIO_DAC_DATA, LUTEntry[2]);
+ DACDelay;
+
+#endif /* AVOID_CPIO */
+
+ }
+ }
+ }
+}
diff --git a/src/atidac.h b/src/atidac.h
new file mode 100644
index 0000000..fc3b758
--- /dev/null
+++ b/src/atidac.h
@@ -0,0 +1,103 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidac.h,v 1.15 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIDAC_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error missing #include "ati.h" before #include "atidac.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIDAC_H___ 1
+
+#include "aticrtc.h"
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+#include "colormapst.h"
+
+/*
+ * RAMDAC-related definitions.
+ */
+#define ATI_DAC_MAX_TYPE MaxBits(DACTYPE)
+#define ATI_DAC_MAX_SUBTYPE MaxBits(BIOS_INIT_DAC_SUBTYPE)
+
+#define ATI_DAC(_Type, _Subtype) (((_Type) << 4) | (_Subtype))
+
+#define ATI_DAC_ATI68830 ATI_DAC(0x0U, 0x0U)
+#define ATI_DAC_SC11483 ATI_DAC(0x1U, 0x0U)
+#define ATI_DAC_ATI68875 ATI_DAC(0x2U, 0x0U)
+#define ATI_DAC_TVP3026_A ATI_DAC(0x2U, 0x7U)
+#define ATI_DAC_GENERIC ATI_DAC(0x3U, 0x0U)
+#define ATI_DAC_BT481 ATI_DAC(0x4U, 0x0U)
+#define ATI_DAC_ATT20C491 ATI_DAC(0x4U, 0x1U)
+#define ATI_DAC_SC15026 ATI_DAC(0x4U, 0x2U)
+#define ATI_DAC_MU9C1880 ATI_DAC(0x4U, 0x3U)
+#define ATI_DAC_IMSG174 ATI_DAC(0x4U, 0x4U)
+#define ATI_DAC_ATI68860_B ATI_DAC(0x5U, 0x0U)
+#define ATI_DAC_ATI68860_C ATI_DAC(0x5U, 0x1U)
+#define ATI_DAC_TVP3026_B ATI_DAC(0x5U, 0x7U)
+#define ATI_DAC_STG1700 ATI_DAC(0x6U, 0x0U)
+#define ATI_DAC_ATT20C498 ATI_DAC(0x6U, 0x1U)
+#define ATI_DAC_STG1702 ATI_DAC(0x7U, 0x0U)
+#define ATI_DAC_SC15021 ATI_DAC(0x7U, 0x1U)
+#define ATI_DAC_ATT21C498 ATI_DAC(0x7U, 0x2U)
+#define ATI_DAC_STG1703 ATI_DAC(0x7U, 0x3U)
+#define ATI_DAC_CH8398 ATI_DAC(0x7U, 0x4U)
+#define ATI_DAC_ATT20C408 ATI_DAC(0x7U, 0x5U)
+#define ATI_DAC_INTERNAL ATI_DAC(0x8U, 0x0U)
+#define ATI_DAC_IBMRGB514 ATI_DAC(0x9U, 0x0U)
+#define ATI_DAC_UNKNOWN ATI_DAC((ATI_DAC_MAX_TYPE << 2) + 3, \
+ ATI_DAC_MAX_SUBTYPE)
+extern const SymTabRec ATIDACDescriptors[];
+
+#ifdef AVOID_CPIO
+
+# define DACDelay /* Nothing */
+
+#else /* AVOID_CPIO */
+
+# define DACDelay \
+ do \
+ { \
+ (void)inb(pATI->CPIO_DAC_WAIT); \
+ (void)inb(pATI->CPIO_DAC_WAIT); \
+ } while (0)
+
+ extern void ATISetDACIOPorts FunctionPrototype((ATIPtr, ATICRTCType));
+
+#endif /* AVOID_CPIO */
+
+extern CARD8 ATIGetDACCmdReg FunctionPrototype((ATIPtr));
+
+extern void ATIDACPreInit FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+extern void ATIDACSave FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIDACSet FunctionPrototype((ATIPtr, ATIHWPtr));
+
+extern void ATILoadPalette FunctionPrototype((ScrnInfoPtr, int, int *,
+ LOCO *, VisualPtr));
+
+#endif /* ___ATIDAC_H___ */
diff --git a/src/atidga.c b/src/atidga.c
new file mode 100644
index 0000000..beca2d8
--- /dev/null
+++ b/src/atidga.c
@@ -0,0 +1,479 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.c,v 1.9 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AVOID_DGA
+
+#include "ati.h"
+#include "atiadjust.h"
+#include "atichip.h"
+#include "atidac.h"
+#include "atidga.h"
+#include "atiident.h"
+#include "atimode.h"
+#include "atistruct.h"
+
+#include "dgaproc.h"
+
+/*
+ * ATIDGAOpenFramebuffer --
+ *
+ * This function returns various framebuffer attributes to a DGA client.
+ */
+static Bool
+ATIDGAOpenFramebuffer
+(
+ ScrnInfoPtr pScreenInfo,
+ char **DeviceName,
+ unsigned char **ApertureBase,
+ int *ApertureSize,
+ int *ApertureOffset,
+ int *flags
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ *DeviceName = NULL; /* No special device */
+ *ApertureBase = (unsigned char *)(pATI->LinearBase);
+ *ApertureSize = pScreenInfo->videoRam * 1024;
+ *ApertureOffset = 0; /* Always */
+ *flags = 0; /* Root premissions OS-dependent */
+
+ return TRUE;
+}
+
+static int
+BitsSet
+(
+ unsigned long data
+)
+{
+ unsigned long mask = 1;
+ int set = 0;
+
+ for (; mask; mask <<= 1)
+ if (data & mask)
+ set++;
+
+ return set;
+}
+
+/*
+ * ATIDGASetMode --
+ *
+ * This function sets a graphics mode for a DGA client.
+ */
+static Bool
+ATIDGASetMode
+(
+ ScrnInfoPtr pScreenInfo,
+ DGAModePtr pDGAMode
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ DisplayModePtr pMode;
+ int iScreen = pScreenInfo->scrnIndex;
+ int frameX0, frameY0;
+
+ if (pDGAMode)
+ {
+ pMode = pDGAMode->mode;
+ pATI->depth = pDGAMode->depth;
+ pATI->bitsPerPixel = pDGAMode->bitsPerPixel;
+ pATI->displayWidth =
+ pDGAMode->bytesPerScanline * 8 / pATI->bitsPerPixel;
+ pATI->weight.red = BitsSet(pDGAMode->red_mask);
+ pATI->weight.green = BitsSet(pDGAMode->green_mask);
+ pATI->weight.blue = BitsSet(pDGAMode->blue_mask);
+ frameX0 = frameY0 = 0;
+ if (!pATI->currentMode)
+ pATI->currentMode = pScreenInfo->currentMode;
+ }
+ else
+ {
+ if (!(pMode = pATI->currentMode))
+ return TRUE;
+
+ pATI->depth = pScreenInfo->depth;
+ pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
+ pATI->displayWidth = pScreenInfo->displayWidth;
+ pATI->weight = pScreenInfo->weight;
+ frameX0 = pScreenInfo->frameX0;
+ frameY0 = pScreenInfo->frameY0;
+ }
+
+ pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
+ ATIAdjustPreInit(pATI);
+ ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
+
+ if (!(*pScreenInfo->SwitchMode)(iScreen, pMode, 0))
+ return FALSE;
+ if (!pDGAMode)
+ pATI->currentMode = NULL;
+ (*pScreenInfo->AdjustFrame)(iScreen, frameX0, frameY0, 0);
+
+ return TRUE;
+}
+
+/*
+ * ATIDGASetViewport --
+ *
+ * This function sets the display start address for a DGA client.
+ */
+static void
+ATIDGASetViewport
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int flags
+)
+{
+ (*pScreenInfo->AdjustFrame)(pScreenInfo->pScreen->myNum, x, y, flags);
+}
+
+/*
+ * ATIDGAGetViewport --
+ *
+ * This function returns the current status of prior DGA requests to set the
+ * adapter's display start address.
+ */
+static int
+ATIDGAGetViewport
+(
+ ScrnInfoPtr pScreenInfo
+)
+{
+ return 0; /* There are never any pending requests */
+}
+
+/*
+ * ATIDGAFillRect --
+ *
+ * This function calls XAA solid fill primitives to fill a rectangle.
+ */
+static void
+ATIDGAFillRect
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int w,
+ int h,
+ unsigned long colour
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+
+ (*pXAAInfo->SetupForSolidFill)(pScreenInfo, (int)colour, GXcopy,
+ (CARD32)(~0));
+ (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, x, y, w, h);
+
+ if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
+ SET_SYNC_FLAG(pXAAInfo);
+}
+
+/*
+ * ATIDGABlitRect --
+ *
+ * This function calls XAA screen-to-screen copy primitives to copy a
+ * rectangle.
+ */
+static void
+ATIDGABlitRect
+(
+ ScrnInfoPtr pScreenInfo,
+ int xSrc,
+ int ySrc,
+ int w,
+ int h,
+ int xDst,
+ int yDst
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+ int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1;
+ int ydir = (ySrc < yDst) ? -1 : 1;
+
+ (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo,
+ xdir, ydir, GXcopy, (CARD32)(~0), -1);
+ (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
+ xSrc, ySrc, xDst, yDst, w, h);
+
+ if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
+ SET_SYNC_FLAG(pXAAInfo);
+}
+
+/*
+ * ATIDGABlitTransRect --
+ *
+ * This function calls XAA screen-to-screen copy primitives to transparently
+ * copy a rectangle.
+ */
+static void
+ATIDGABlitTransRect
+(
+ ScrnInfoPtr pScreenInfo,
+ int xSrc,
+ int ySrc,
+ int w,
+ int h,
+ int xDst,
+ int yDst,
+ unsigned long colour
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+ int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1;
+ int ydir = (ySrc < yDst) ? -1 : 1;
+
+ pATI->XAAForceTransBlit = TRUE;
+
+ (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo,
+ xdir, ydir, GXcopy, (CARD32)(~0), (int)colour);
+
+ pATI->XAAForceTransBlit = FALSE;
+
+ (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
+ xSrc, ySrc, xDst, yDst, w, h);
+
+ if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
+ SET_SYNC_FLAG(pXAAInfo);
+}
+
+/*
+ * ATIDGAAddModes --
+ *
+ * This function translates DisplayModeRec's into DGAModeRec's.
+ */
+static void
+ATIDGAAddModes
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ int flags,
+ int depth,
+ int bitsPerPixel,
+ int redMask,
+ int greenMask,
+ int blueMask,
+ int visualClass
+)
+{
+ DisplayModePtr pMode = pScreenInfo->modes;
+ DGAModePtr pDGAMode;
+ int displayWidth = pScreenInfo->displayWidth;
+ int videoBits = pScreenInfo->videoRam * 1024 * 8;
+ int xViewportStep = 64 / UnitOf(bitsPerPixel);
+ int modePitch, bitsPerScanline, maxViewportY;
+
+ if (bitsPerPixel != pScreenInfo->bitsPerPixel)
+ displayWidth = 0;
+
+ while (1)
+ {
+ /* Weed out multiscanned modes */
+ if ((pMode->VScan <= 1) ||
+ ((pMode->VScan == 2) && !(pMode->Flags & V_DBLSCAN)))
+ {
+ /*
+ * For code simplicity, ensure DGA mode pitch is a multiple of 64
+ * bytes.
+ */
+ if (!(modePitch = displayWidth))
+ {
+ modePitch = ((64 * 8) / UnitOf(bitsPerPixel)) - 1;
+ modePitch = (pMode->HDisplay + modePitch) & ~modePitch;
+ }
+
+ /* Ensure the mode fits in video memory */
+ if ((modePitch * bitsPerPixel * pMode->VDisplay) <= videoBits)
+ {
+ /* Stop generating modes on out-of-memory conditions */
+ pDGAMode = xrealloc(pATI->pDGAMode,
+ (pATI->nDGAMode + 1) * SizeOf(DGAModeRec));
+ if (!pDGAMode)
+ break;
+
+ pATI->pDGAMode = pDGAMode;
+ pDGAMode += pATI->nDGAMode;
+ pATI->nDGAMode++;
+ (void)memset(pDGAMode, 0, SizeOf(DGAModeRec));
+
+ /* Fill in the mode structure */
+ pDGAMode->mode = pMode;
+ pDGAMode->flags = flags;
+ if (bitsPerPixel == pScreenInfo->bitsPerPixel)
+ {
+ pDGAMode->flags |= DGA_PIXMAP_AVAILABLE;
+ pDGAMode->address = pATI->pMemory;
+
+ if (pATI->pXAAInfo)
+ pDGAMode->flags &= ~DGA_CONCURRENT_ACCESS;
+ }
+ if ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1))
+ pDGAMode->flags |= DGA_DOUBLESCAN;
+ if (pMode->Flags & V_INTERLACE)
+ pDGAMode->flags |= DGA_INTERLACED;
+
+ pDGAMode->byteOrder = pScreenInfo->imageByteOrder;
+ pDGAMode->depth = depth;
+ pDGAMode->bitsPerPixel = bitsPerPixel;
+ pDGAMode->red_mask = redMask;
+ pDGAMode->green_mask = greenMask;
+ pDGAMode->blue_mask = blueMask;
+ pDGAMode->visualClass = visualClass;
+
+ pDGAMode->viewportWidth = pMode->HDisplay;
+ pDGAMode->viewportHeight = pMode->VDisplay;
+ pDGAMode->xViewportStep = xViewportStep;
+ pDGAMode->yViewportStep = 1;
+
+ bitsPerScanline = modePitch * bitsPerPixel;
+ pDGAMode->bytesPerScanline = bitsPerScanline / 8;
+ pDGAMode->imageWidth = pDGAMode->pixmapWidth = modePitch;
+ pDGAMode->imageHeight = pDGAMode->pixmapHeight =
+ videoBits / bitsPerScanline;
+
+ pDGAMode->maxViewportX =
+ pDGAMode->imageWidth - pDGAMode->viewportWidth;
+ pDGAMode->maxViewportY =
+ pDGAMode->imageHeight - pDGAMode->viewportHeight;
+ maxViewportY =
+ ((((pATI->AdjustMaxBase * 8) / bitsPerPixel) +
+ xViewportStep) / modePitch) - 1;
+ if (maxViewportY < pDGAMode->maxViewportY)
+ pDGAMode->maxViewportY = maxViewportY;
+ }
+ }
+
+ if ((pMode = pMode->next) == pScreenInfo->modes)
+ {
+ if (!displayWidth)
+ break;
+
+ displayWidth = 0;
+ }
+ }
+}
+
+/*
+ * ATIDGAInit --
+ *
+ * This function initialises the driver's support for the DGA extension.
+ */
+Bool
+ATIDGAInit
+(
+ ScrnInfoPtr pScreenInfo,
+ ScreenPtr pScreen,
+ ATIPtr pATI
+)
+{
+ XAAInfoRecPtr pXAAInfo;
+ int flags;
+
+ if (!pATI->nDGAMode)
+ {
+
+#ifndef AVOID_CPIO
+
+ /*
+ * Contrary to previous extension versions, DGA 2 does not support
+ * banked framebuffers. Also, disable DGA when non-DGA server modes
+ * are planar.
+ */
+ if (pATI->BankInfo.BankSize || (pScreenInfo->depth <= 4))
+ return FALSE;
+
+#endif /* AVOID_CPIO */
+
+ /* Set up DGA callbacks */
+ pATI->ATIDGAFunctions.OpenFramebuffer = ATIDGAOpenFramebuffer;
+ pATI->ATIDGAFunctions.SetMode = ATIDGASetMode;
+ pATI->ATIDGAFunctions.SetViewport = ATIDGASetViewport;
+ pATI->ATIDGAFunctions.GetViewport = ATIDGAGetViewport;
+
+ flags = 0;
+ if ((pXAAInfo = pATI->pXAAInfo))
+ {
+ pATI->ATIDGAFunctions.Sync = pXAAInfo->Sync;
+ if (pXAAInfo->SetupForSolidFill &&
+ pXAAInfo->SubsequentSolidFillRect)
+ {
+ flags |= DGA_FILL_RECT;
+ pATI->ATIDGAFunctions.FillRect = ATIDGAFillRect;
+ }
+ if (pXAAInfo->SetupForScreenToScreenCopy &&
+ pXAAInfo->SubsequentScreenToScreenCopy)
+ {
+ flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;
+ pATI->ATIDGAFunctions.BlitRect = ATIDGABlitRect;
+ pATI->ATIDGAFunctions.BlitTransRect = ATIDGABlitTransRect;
+ }
+ }
+ if (!flags)
+ flags = DGA_CONCURRENT_ACCESS;
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 8, 8, 0, 0, 0, PseudoColor);
+
+ if ((pATI->Chip >= ATI_CHIP_264CT) &&
+ (pATI->Chipset == ATI_CHIPSET_ATI))
+ {
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 15, 16, 0x7C00U, 0x03E0U, 0x001FU, TrueColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 16, 16, 0xF800U, 0x07E0U, 0x001FU, TrueColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor);
+
+ if (pATI->DAC != ATI_DAC_INTERNAL) /* Not first revision */
+ {
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 15, 16, 0x7C00U, 0x03E0U, 0x001FU, DirectColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 16, 16, 0xF800U, 0x07E0U, 0x001FU, DirectColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor);
+
+ ATIDGAAddModes(pScreenInfo, pATI, flags,
+ 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor);
+ }
+ }
+ }
+
+ return DGAInit(pScreen, &pATI->ATIDGAFunctions, pATI->pDGAMode,
+ pATI->nDGAMode);
+}
+
+#endif /* AVOID_DGA */
diff --git a/src/atidga.h b/src/atidga.h
new file mode 100644
index 0000000..1011a89
--- /dev/null
+++ b/src/atidga.h
@@ -0,0 +1,38 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.h,v 1.6 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIDGA_H___
+#define ___ATIDGA_H___ 1
+
+#ifndef AVOID_DGA
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIDGAInit FunctionPrototype((ScrnInfoPtr, ScreenPtr, ATIPtr));
+
+#endif /* AVOID_DGA */
+
+#endif /* ___ATIDGA_H___ */
diff --git a/src/atidsp.c b/src/atidsp.c
new file mode 100644
index 0000000..7ca2329
--- /dev/null
+++ b/src/atidsp.c
@@ -0,0 +1,323 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidsp.c,v 1.19 2003/01/01 19:16:31 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atichip.h"
+#include "aticrtc.h"
+#include "atidsp.h"
+#include "atimach64io.h"
+#include "atividmem.h"
+
+/*
+ * ATIDSPPreInit --
+ *
+ * This function initialises global variables used to set DSP registers on a
+ * VT-B or later.
+ */
+Bool
+ATIDSPPreInit
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ CARD32 IOValue, dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
+ int trp;
+
+ /*
+ * VT-B's and later have additional post-dividers that are not powers of
+ * two.
+ */
+ pATI->ClockDescriptor.NumD = 8;
+
+ /* Retrieve XCLK settings */
+ IOValue = ATIGetMach64PLLReg(PLL_XCLK_CNTL);
+ pATI->XCLKPostDivider = GetBits(IOValue, PLL_XCLK_SRC_SEL);
+ pATI->XCLKReferenceDivider = 1;
+ switch (pATI->XCLKPostDivider)
+ {
+ case 0: case 1: case 2: case 3:
+ break;
+
+ case 4:
+ pATI->XCLKReferenceDivider = 3;
+ pATI->XCLKPostDivider = 0;
+ break;
+
+ default:
+ xf86DrvMsg(iScreen, X_ERROR,
+ "Unsupported XCLK source: %d.\n", pATI->XCLKPostDivider);
+ return FALSE;
+ }
+
+ pATI->XCLKPostDivider -= GetBits(IOValue, PLL_MFB_TIMES_4_2B);
+ pATI->XCLKFeedbackDivider = ATIGetMach64PLLReg(PLL_MCLK_FB_DIV);
+
+ xf86DrvMsgVerb(iScreen, X_INFO, 2,
+ "Engine XCLK %.3f MHz; Refresh rate code %d.\n",
+ ATIDivide(pATI->XCLKFeedbackDivider * pATI->ReferenceNumerator,
+ pATI->XCLKReferenceDivider * pATI->ClockDescriptor.MaxM *
+ pATI->ReferenceDenominator, 1 - pATI->XCLKPostDivider, 0) /
+ (double)1000.0,
+ GetBits(pATI->LockData.mem_cntl, CTL_MEM_REFRESH_RATE_B));
+
+ /* Compute maximum RAS delay and friends */
+ trp = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRP);
+ pATI->XCLKPageFaultDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRCD) +
+ GetBits(pATI->LockData.mem_cntl, CTL_MEM_TCRD) + trp + 2;
+ pATI->XCLKMaxRASDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRAS) +
+ trp + 2;
+ pATI->DisplayFIFODepth = 32;
+
+ if (pATI->Chip < ATI_CHIP_264VT4)
+ {
+ pATI->XCLKPageFaultDelay += 2;
+ pATI->XCLKMaxRASDelay += 3;
+ pATI->DisplayFIFODepth = 24;
+ }
+
+ switch (pATI->MemoryType)
+ {
+ case MEM_264_DRAM:
+ if (pATI->VideoRAM <= 1024)
+ pATI->DisplayLoopLatency = 10;
+ else
+ {
+ pATI->DisplayLoopLatency = 8;
+ pATI->XCLKPageFaultDelay += 2;
+ }
+ break;
+
+ case MEM_264_EDO:
+ case MEM_264_PSEUDO_EDO:
+ if (pATI->VideoRAM <= 1024)
+ pATI->DisplayLoopLatency = 9;
+ else
+ {
+ pATI->DisplayLoopLatency = 8;
+ pATI->XCLKPageFaultDelay++;
+ }
+ break;
+
+ case MEM_264_SDRAM:
+ if (pATI->VideoRAM <= 1024)
+ pATI->DisplayLoopLatency = 11;
+ else
+ {
+ pATI->DisplayLoopLatency = 10;
+ pATI->XCLKPageFaultDelay++;
+ }
+ break;
+
+ case MEM_264_SGRAM:
+ pATI->DisplayLoopLatency = 8;
+ pATI->XCLKPageFaultDelay += 3;
+ break;
+
+ default: /* Set maximums */
+ pATI->DisplayLoopLatency = 11;
+ pATI->XCLKPageFaultDelay += 3;
+ break;
+ }
+
+ if (pATI->XCLKMaxRASDelay <= pATI->XCLKPageFaultDelay)
+ pATI->XCLKMaxRASDelay = pATI->XCLKPageFaultDelay + 1;
+
+ /* Allow BIOS to override */
+ dsp_config = inr(DSP_CONFIG);
+ dsp_on_off = inr(DSP_ON_OFF);
+ vga_dsp_config = inr(VGA_DSP_CONFIG);
+ vga_dsp_on_off = inr(VGA_DSP_ON_OFF);
+
+ if (dsp_config)
+ pATI->DisplayLoopLatency = GetBits(dsp_config, DSP_LOOP_LATENCY);
+
+ if ((!dsp_on_off && (pATI->Chip < ATI_CHIP_264GTPRO)) ||
+ ((dsp_on_off == vga_dsp_on_off) &&
+ (!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW))))
+ {
+ if (ATIDivide(GetBits(vga_dsp_on_off, VGA_DSP_OFF),
+ GetBits(vga_dsp_config, VGA_DSP_XCLKS_PER_QW), 5, 1) > 24)
+ pATI->DisplayFIFODepth = 32;
+ else
+ pATI->DisplayFIFODepth = 24;
+ }
+
+ return TRUE;
+}
+
+/*
+ * ATIDSPSave --
+ *
+ * This function is called to remember DSP register values on VT-B and later
+ * controllers.
+ */
+void
+ATIDSPSave
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ pATIHW->dsp_on_off = inr(DSP_ON_OFF);
+ pATIHW->dsp_config = inr(DSP_CONFIG);
+}
+
+
+/*
+ * ATIDSPCalculate --
+ *
+ * This function sets up DSP register values for a VTB or later. Note that
+ * this would be slightly different if VCLK 0 or 1 were used for the mode
+ * instead. In that case, this function would set VGA_DSP_CONFIG and
+ * VGA_DSP_ON_OFF, would have to zero out DSP_CONFIG and DSP_ON_OFF, and would
+ * have to consider that VGA_DSP_CONFIG is partitioned slightly differently
+ * than DSP_CONFIG.
+ */
+void
+ATIDSPCalculate
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ int Multiplier, Divider;
+ int RASMultiplier = pATI->XCLKMaxRASDelay, RASDivider = 1;
+ int dsp_precision, dsp_on, dsp_off, dsp_xclks;
+ int tmp, vshift, xshift;
+
+# define Maximum_DSP_PRECISION ((int)MaxBits(DSP_PRECISION))
+
+ /* Compute a memory-to-screen bandwidth ratio */
+ Multiplier = pATI->XCLKFeedbackDivider *
+ pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider];
+ Divider = pATIHW->FeedbackDivider * pATI->XCLKReferenceDivider;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth >= 8)
+
+#endif /* AVOID_CPIO */
+
+ {
+ Divider *= pATI->bitsPerPixel / 4;
+ }
+
+ /* Start by assuming a display FIFO width of 64 bits */
+ vshift = (6 - 2) - pATI->XCLKPostDivider;
+
+#ifndef AVOID_CPIO
+
+ if (pATIHW->crtc == ATI_CRTC_VGA)
+ vshift--; /* Nope, it's 32 bits wide */
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ {
+ /* Compensate for horizontal stretching */
+ Multiplier *= pATI->LCDHorizontal;
+ Divider *= pMode->HDisplay & ~7;
+
+ RASMultiplier *= pATI->LCDHorizontal;
+ RASDivider *= pMode->HDisplay & ~7;
+ }
+
+ /* Determine dsp_precision first */
+ tmp = ATIDivide(Multiplier * pATI->DisplayFIFODepth, Divider, vshift, -1);
+ for (dsp_precision = -5; tmp; dsp_precision++)
+ tmp >>= 1;
+ if (dsp_precision < 0)
+ dsp_precision = 0;
+ else if (dsp_precision > Maximum_DSP_PRECISION)
+ dsp_precision = Maximum_DSP_PRECISION;
+
+ xshift = 6 - dsp_precision;
+ vshift += xshift;
+
+ /* Move on to dsp_off */
+ dsp_off = ATIDivide(Multiplier * (pATI->DisplayFIFODepth - 1), Divider,
+ vshift, -1) - ATIDivide(1, 1, vshift - xshift, 1);
+
+ /* Next is dsp_on */
+
+#ifndef AVOID_CPIO
+
+ if ((pATIHW->crtc == ATI_CRTC_VGA) /* && (dsp_precision < 3) */)
+ {
+ /*
+ * TODO: I don't yet know why something like this appears necessary.
+ * But I don't have time to explore this right now.
+ */
+ dsp_on = ATIDivide(Multiplier * 5, Divider, vshift + 2, 1);
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ dsp_on = ATIDivide(Multiplier, Divider, vshift, 1);
+ tmp = ATIDivide(RASMultiplier, RASDivider, xshift, 1);
+ if (dsp_on < tmp)
+ dsp_on = tmp;
+ dsp_on += (tmp * 2) +
+ ATIDivide(pATI->XCLKPageFaultDelay, 1, xshift, 1);
+ }
+
+ /* Calculate rounding factor and apply it to dsp_on */
+ tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
+ dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
+
+ if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1)))
+ {
+ dsp_on = dsp_off - ATIDivide(Multiplier, Divider, vshift, -1);
+ dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
+ }
+
+ /* Last but not least: dsp_xclks */
+ dsp_xclks = ATIDivide(Multiplier, Divider, vshift + 5, 1);
+
+ /* Build DSP register contents */
+ pATIHW->dsp_on_off = SetBits(dsp_on, DSP_ON) |
+ SetBits(dsp_off, DSP_OFF);
+ pATIHW->dsp_config = SetBits(dsp_precision, DSP_PRECISION) |
+ SetBits(dsp_xclks, DSP_XCLKS_PER_QW) |
+ SetBits(pATI->DisplayLoopLatency, DSP_LOOP_LATENCY);
+}
+
+/*
+ * ATIDSPSet --
+ *
+ * This function is called to set DSP registers on VT-B and later controllers.
+ */
+void
+ATIDSPSet
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ outr(DSP_ON_OFF, pATIHW->dsp_on_off);
+ outr(DSP_CONFIG, pATIHW->dsp_config);
+}
diff --git a/src/atidsp.h b/src/atidsp.h
new file mode 100644
index 0000000..d6881cf
--- /dev/null
+++ b/src/atidsp.h
@@ -0,0 +1,38 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidsp.h,v 1.10 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIDSP_H___
+#define ___ATIDSP_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIDSPPreInit FunctionPrototype((int, ATIPtr));
+extern void ATIDSPSave FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIDSPCalculate FunctionPrototype((ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIDSPSet FunctionPrototype((ATIPtr, ATIHWPtr));
+
+#endif /* ___ATIDSP_H___ */
diff --git a/src/atiident.c b/src/atiident.c
new file mode 100644
index 0000000..1fb9dbb
--- /dev/null
+++ b/src/atiident.c
@@ -0,0 +1,134 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiident.c,v 1.11 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiident.h"
+#include "atiutil.h"
+#include "ativersion.h"
+
+#include "r128_probe.h"
+#include "radeon_probe.h"
+
+const char *ATIChipsetNames[] =
+{
+ "ati",
+
+#ifndef AVOID_CPIO
+
+ "ativga",
+ "ibmvga",
+ "ibm8514",
+ "vgawonder",
+ "mach8",
+ "mach32",
+
+#endif /* AVOID_CPIO */
+
+ "mach64",
+ "rage128",
+ "radeon"
+};
+
+static SymTabRec ATIPublicChipsetNames[] =
+{
+ {ATI_CHIPSET_ATI, "ati"},
+
+#ifndef AVOID_CPIO
+
+ {ATI_CHIPSET_ATIVGA, "ativga"},
+#ifdef __MAYBE_NOT__
+ {ATI_CHIPSET_IBMVGA, "ibmvga"},
+#endif
+#ifdef __NOT_YET__
+ {ATI_CHIPSET_IBM8514, "ibm8514"},
+#endif
+
+#endif /* AVOID_CPIO */
+
+ {-1, NULL}
+};
+
+/*
+ * ATIIdentify --
+ *
+ * Print the driver's list of chipset names.
+ */
+void
+ATIIdentify
+(
+ int flags
+)
+{
+ xf86PrintChipsets(ATI_NAME,
+ (NumberOf(ATIPublicChipsetNames) <= 2) ?
+ "ATI driver (version " ATI_VERSION_NAME ") for chipset" :
+ "ATI driver (version " ATI_VERSION_NAME ") for chipsets",
+ ATIPublicChipsetNames);
+ R128Identify(flags);
+ RADEONIdentify(flags);
+}
+
+/*
+ * ATIIdentProbe --
+ *
+ * This function determines if the user specified a chipset name acceptable to
+ * the driver. It returns an ATIChipsetType or -1.
+ */
+int
+ATIIdentProbe
+(
+ const char *ChipsetName
+)
+{
+ int Chipset;
+
+ static SymTabRec SpecificNames[] =
+ {
+
+#ifndef AVOID_CPIO
+
+ {ATI_CHIPSET_VGAWONDER, "vgawonder"},
+#ifdef __NOT_YET__
+ {ATI_CHIPSET_MACH8, "mach8"},
+#endif
+ {ATI_CHIPSET_MACH32, "mach32"},
+
+#endif /* AVOID_CPIO */
+
+ {ATI_CHIPSET_MACH64, "mach64"},
+ {ATI_CHIPSET_RAGE128, "rage128"},
+ {ATI_CHIPSET_RADEON, "radeon"},
+ {-1, NULL}
+ };
+
+ /* If no Chipset specification, default to "ati" */
+ if (!ChipsetName || !*ChipsetName)
+ return ATI_CHIPSET_ATI;
+
+ Chipset = xf86StringToToken(ATIPublicChipsetNames, ChipsetName);
+ if (Chipset != -1)
+ return Chipset;
+
+ /* Check for some other chipset names */
+ return xf86StringToToken(SpecificNames, ChipsetName);
+}
diff --git a/src/atiident.h b/src/atiident.h
new file mode 100644
index 0000000..74677c5
--- /dev/null
+++ b/src/atiident.h
@@ -0,0 +1,55 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiident.h,v 1.10 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIIDENT_H___
+#define ___ATIIDENT_H___ 1
+
+#include "atiproto.h"
+
+typedef enum
+{
+ ATI_CHIPSET_ATI,
+
+#ifndef AVOID_CPIO
+
+ ATI_CHIPSET_ATIVGA,
+ ATI_CHIPSET_IBMVGA,
+ ATI_CHIPSET_IBM8514,
+ ATI_CHIPSET_VGAWONDER,
+ ATI_CHIPSET_MACH8,
+ ATI_CHIPSET_MACH32,
+
+#endif /* AVOID_CPIO */
+
+ ATI_CHIPSET_MACH64,
+ ATI_CHIPSET_RAGE128,
+ ATI_CHIPSET_RADEON,
+ ATI_CHIPSET_MAX /* Must be last */
+} ATIChipsetType;
+
+extern const char *ATIChipsetNames[];
+
+extern void ATIIdentify FunctionPrototype((int));
+extern int ATIIdentProbe FunctionPrototype((const char *));
+
+#endif /* ___ATIIDENT_H___ */
diff --git a/src/atiio.h b/src/atiio.h
new file mode 100644
index 0000000..f6f871b
--- /dev/null
+++ b/src/atiio.h
@@ -0,0 +1,83 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiio.h,v 1.14 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIIO_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error missing #include "ati.h" before #include "atiio.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIIO_H___ 1
+
+#include "atiregs.h"
+
+#include "compiler.h"
+
+/* I/O decoding definitions */
+typedef enum
+{
+ SPARSE_IO,
+ BLOCK_IO
+} ATIIODecodingType;
+
+#ifndef AVOID_CPIO
+
+/* Wait until "n" queue entries are free */
+#define ibm8514WaitQueue(_n) \
+ { \
+ while (inw(GP_STAT) & (0x0100U >> (_n))); \
+ }
+#define ATIWaitQueue(_n) \
+ { \
+ while (inw(EXT_FIFO_STATUS) & (0x010000U >> (_n))); \
+ }
+
+/* Wait until GP is idle and queue is empty */
+#define WaitIdleEmpty() \
+ { \
+ while (inw(GP_STAT) & (GPBUSY | 1)); \
+ }
+#define ProbeWaitIdleEmpty() \
+ { \
+ int _i; \
+ CARD16 _value; \
+ for (_i = 0; _i < 100000; _i++) \
+ { \
+ _value = inw(GP_STAT); \
+ if (_value == (CARD16)(-1)) \
+ break; \
+ if (!(_value & (GPBUSY | 1))) \
+ break; \
+ } \
+ }
+
+/* Wait until GP has data available */
+#define WaitDataReady() \
+ { \
+ while (!(inw(GP_STAT) & DATARDY)); \
+ }
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIIO_H___ */
diff --git a/src/atiload.c b/src/atiload.c
new file mode 100644
index 0000000..83b5331
--- /dev/null
+++ b/src/atiload.c
@@ -0,0 +1,179 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.c,v 1.12 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef XFree86LOADER
+
+#include "ati.h"
+#include "aticursor.h"
+#include "atiload.h"
+#include "atistruct.h"
+
+/*
+ * All symbol lists belong here. They are externalised so that they can be
+ * referenced elsewhere. Note the naming convention for these things...
+ */
+
+const char *ATIint10Symbols[] =
+{
+ "xf86FreeInt10",
+ "xf86InitInt10",
+ "xf86int10Addr",
+ NULL
+};
+
+const char *ATIddcSymbols[] =
+{
+ "xf86PrintEDID",
+ "xf86SetDDCProperties",
+ NULL
+};
+
+const char *ATIvbeSymbols[] =
+{
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+#ifndef AVOID_CPIO
+
+const char *ATIxf1bppSymbols[] =
+{
+ "xf1bppScreenInit",
+ NULL
+};
+
+const char *ATIxf4bppSymbols[] =
+{
+ "xf4bppScreenInit",
+ NULL
+};
+
+#endif /* AVOID_CPIO */
+
+const char *ATIfbSymbols[] =
+{
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+const char *ATIshadowfbSymbols[] =
+{
+ "ShadowFBInit",
+ NULL
+};
+
+const char *ATIxaaSymbols[] =
+{
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ NULL
+};
+
+const char *ATIramdacSymbols[] =
+{
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ "xf86ForceHWCursor",
+ NULL
+};
+
+/*
+ * ATILoadModule --
+ *
+ * Load a specific module and register with the loader those of its entry
+ * points that are referenced by this driver.
+ */
+pointer
+ATILoadModule
+(
+ ScrnInfoPtr pScreenInfo,
+ const char *Module,
+ const char **SymbolList
+)
+{
+ pointer pModule = xf86LoadSubModule(pScreenInfo, Module);
+
+ if (pModule)
+ xf86LoaderReqSymLists(SymbolList, NULL);
+
+ return pModule;
+}
+
+/*
+ * ATILoadModules --
+ *
+ * This function loads other modules required for a screen.
+ */
+pointer
+ATILoadModules
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ /* Load shadow frame buffer code if needed */
+ if (pATI->OptionShadowFB &&
+ !ATILoadModule(pScreenInfo, "shadowfb", ATIshadowfbSymbols))
+ return NULL;
+
+ /* Load XAA if needed */
+ if (pATI->OptionAccel &&
+ !ATILoadModule(pScreenInfo, "xaa", ATIxaaSymbols))
+ return NULL;
+
+ /* Load ramdac module if needed */
+ if ((pATI->Cursor > ATI_CURSOR_SOFTWARE) &&
+ !ATILoadModule(pScreenInfo, "ramdac", ATIramdacSymbols))
+ return NULL;
+
+ /* Load depth-specific entry points */
+ switch (pATI->bitsPerPixel)
+ {
+
+#ifndef AVOID_CPIO
+
+ case 1:
+ return ATILoadModule(pScreenInfo, "xf1bpp", ATIxf1bppSymbols);
+
+ case 4:
+ return ATILoadModule(pScreenInfo, "xf4bpp", ATIxf4bppSymbols);
+
+#endif /* AVOID_CPIO */
+
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ return ATILoadModule(pScreenInfo, "fb", ATIfbSymbols);
+
+ default:
+ return NULL;
+ }
+}
+
+#endif /* XFree86LOADER */
diff --git a/src/atiload.h b/src/atiload.h
new file mode 100644
index 0000000..050404e
--- /dev/null
+++ b/src/atiload.h
@@ -0,0 +1,56 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.h,v 1.5 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATILOAD_H___
+#define ___ATILOAD_H___ 1
+
+#ifdef XFree86LOADER
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern const char *ATIint10Symbols[], *ATIddcSymbols[], *ATIvbeSymbols[],
+
+#ifndef AVOID_CPIO
+
+ *ATIxf1bppSymbols[], *ATIxf4bppSymbols[],
+
+#endif /* AVOID_CPIO */
+
+ *ATIfbSymbols[], *ATIshadowfbSymbols[], *ATIxaaSymbols[],
+ *ATIramdacSymbols[];
+
+extern pointer ATILoadModule FunctionPrototype((ScrnInfoPtr, const char *,
+ const char **));
+extern pointer ATILoadModules FunctionPrototype((ScrnInfoPtr, ATIPtr));
+
+#else /* XFree86LOADER */
+
+#define ATILoadModule(pScreenInfo, Module, SymboList) ((pointer)1)
+#define ATILoadModules(pScreenInfo, pATI) ((pointer)1)
+
+#endif /* XFree86LOADER */
+
+#endif /* ___ATILOAD_H___ */
diff --git a/src/atilock.c b/src/atilock.c
new file mode 100644
index 0000000..336696c
--- /dev/null
+++ b/src/atilock.c
@@ -0,0 +1,586 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c,v 1.18 2003/01/10 20:57:57 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "atilock.h"
+#include "atimach64io.h"
+#include "atiwonderio.h"
+
+/*
+ * ATIUnlock --
+ *
+ * This function is entered to unlock registers and disable unwanted
+ * emulations. It saves the current state for later restoration by ATILock().
+ */
+void
+ATIUnlock
+(
+ ATIPtr pATI
+)
+{
+ CARD32 tmp;
+
+#ifndef AVOID_CPIO
+
+ CARD32 saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->Unlocked)
+ return;
+ pATI->Unlocked = TRUE;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->ChipHasSUBSYS_CNTL)
+ {
+ /* Save register values to be modified */
+ pATI->LockData.clock_sel = inw(CLOCK_SEL);
+ if (pATI->Chip >= ATI_CHIP_68800)
+ {
+ pATI->LockData.misc_options = inw(MISC_OPTIONS);
+ pATI->LockData.mem_bndry = inw(MEM_BNDRY);
+ pATI->LockData.mem_cfg = inw(MEM_CFG);
+ }
+
+ tmp = inw(SUBSYS_STAT) & _8PLANE;
+
+ /* Reset the 8514/A and disable all interrupts */
+ outw(SUBSYS_CNTL, tmp | (GPCTRL_RESET | CHPTEST_NORMAL));
+ outw(SUBSYS_CNTL, tmp | (GPCTRL_ENAB | CHPTEST_NORMAL | RVBLNKFLG |
+ RPICKFLAG | RINVALIDIO | RGPIDLE));
+
+ /* Ensure VGA is enabled */
+ outw(CLOCK_SEL, pATI->LockData.clock_sel &~DISABPASSTHRU);
+ if (pATI->Chip >= ATI_CHIP_68800)
+ {
+ outw(MISC_OPTIONS, pATI->LockData.misc_options &
+ ~(DISABLE_VGA | DISABLE_DAC));
+
+ /* Disable any video memory boundary */
+ outw(MEM_BNDRY, pATI->LockData.mem_bndry &
+ ~(MEM_PAGE_BNDRY | MEM_BNDRY_ENA));
+
+ /* Disable direct video memory aperture */
+ outw(MEM_CFG, pATI->LockData.mem_cfg &
+ ~(MEM_APERT_SEL | MEM_APERT_PAGE | MEM_APERT_LOC));
+ }
+
+ /* Wait for all activity to die down */
+ ProbeWaitIdleEmpty();
+ }
+ else if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+ /* Reset everything */
+ pATI->LockData.bus_cntl = inr(BUS_CNTL);
+ if (pATI->Chip < ATI_CHIP_264VT4)
+ {
+ pATI->LockData.bus_cntl =
+ (pATI->LockData.bus_cntl & ~BUS_HOST_ERR_INT_EN) |
+ BUS_HOST_ERR_INT;
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ pATI->LockData.bus_cntl =
+ (pATI->LockData.bus_cntl & ~BUS_FIFO_ERR_INT_EN) |
+ BUS_FIFO_ERR_INT;
+ }
+ tmp = pATI->LockData.bus_cntl & ~BUS_ROM_DIS;
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ tmp |= SetBits(15, BUS_FIFO_WS);
+ else
+ tmp &= ~BUS_MASTER_DIS;
+ if (pATI->Chip >= ATI_CHIP_264VT)
+ tmp |= BUS_EXT_REG_EN; /* Enable Block 1 */
+ outr(BUS_CNTL, tmp);
+ pATI->LockData.crtc_int_cntl = inr(CRTC_INT_CNTL);
+ outr(CRTC_INT_CNTL, (pATI->LockData.crtc_int_cntl & ~CRTC_INT_ENS) |
+ CRTC_INT_ACKS);
+ pATI->LockData.gen_test_cntl = inr(GEN_TEST_CNTL) &
+ (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN |
+ GEN_BLOCK_WR_EN);
+ tmp = pATI->LockData.gen_test_cntl & ~GEN_CUR_EN;
+ outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
+ outr(GEN_TEST_CNTL, tmp);
+ outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
+ tmp = pATI->LockData.crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
+ ~(CRTC_EN | CRTC_LOCK_REGS);
+ if (pATI->Chip >= ATI_CHIP_264XL)
+ tmp = (tmp & ~CRTC_INT_ENS_X) | CRTC_INT_ACKS_X;
+ outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
+ outr(CRTC_GEN_CNTL, tmp);
+ outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
+ if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
+ {
+ pATI->LockData.lcd_index = inr(LCD_INDEX);
+ if (pATI->Chip >= ATI_CHIP_264XL)
+ outr(LCD_INDEX, pATI->LockData.lcd_index &
+ ~(LCD_MONDET_INT_EN | LCD_MONDET_INT));
+
+ /*
+ * Prevent BIOS initiated display switches on dual-CRT controllers.
+ */
+ if (pATI->Chip != ATI_CHIP_264XL)
+ {
+ pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3);
+ outr(SCRATCH_REG3,
+ pATI->LockData.scratch_reg3 | DISPLAY_SWITCH_DISABLE);
+ }
+ }
+
+ pATI->LockData.mem_cntl = inr(MEM_CNTL);
+ if (pATI->Chip < ATI_CHIP_264CT)
+ outr(MEM_CNTL, pATI->LockData.mem_cntl &
+ ~(CTL_MEM_BNDRY | CTL_MEM_BNDRY_EN));
+
+ /* Disable feature connector on integrated controllers */
+ tmp = pATI->LockData.dac_cntl = inr(DAC_CNTL);
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ tmp &= ~DAC_FEA_CON_EN;
+
+#ifndef AVOID_CPIO
+
+ /* Ensure VGA aperture is enabled */
+ pATI->LockData.config_cntl = inr(CONFIG_CNTL);
+ tmp |= DAC_VGA_ADR_EN;
+ outr(CONFIG_CNTL, pATI->LockData.config_cntl & ~CFG_VGA_DIS);
+
+#endif /* AVOID_CPIO */
+
+ outr(DAC_CNTL, tmp);
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ pATI->LockData.mpp_config = inr(MPP_CONFIG);
+ pATI->LockData.mpp_strobe_seq = inr(MPP_STROBE_SEQ);
+ pATI->LockData.tvo_cntl = inr(TVO_CNTL);
+
+ if (pATI->Chip >= ATI_CHIP_264GT2C)
+ {
+ pATI->LockData.hw_debug = inr(HW_DEBUG);
+
+ if (pATI->Chip >= ATI_CHIP_264GTPRO)
+ {
+ if (!(pATI->LockData.hw_debug & CMDFIFO_SIZE_EN))
+ outr(HW_DEBUG,
+ pATI->LockData.hw_debug | CMDFIFO_SIZE_EN);
+
+ pATI->LockData.i2c_cntl_0 =
+ inr(I2C_CNTL_0) | (I2C_CNTL_STAT | I2C_CNTL_HPTR_RST);
+ outr(I2C_CNTL_0,
+ pATI->LockData.i2c_cntl_0 & ~I2C_CNTL_INT_EN);
+ pATI->LockData.i2c_cntl_1 = inr(I2C_CNTL_1);
+ }
+ else
+ {
+ if (pATI->LockData.hw_debug & CMDFIFO_SIZE_DIS)
+ outr(HW_DEBUG,
+ pATI->LockData.hw_debug & ~CMDFIFO_SIZE_DIS);
+ }
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ }
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ if (pATI->CPIO_VGAWonder)
+ {
+ /*
+ * Ensure all registers are read/write and disable all non-VGA
+ * emulations.
+ */
+ pATI->LockData.b1 = ATIGetExtReg(0xB1U);
+ ATIModifyExtReg(pATI, 0xB1U, pATI->LockData.b1, 0xFCU, 0x00U);
+ pATI->LockData.b4 = ATIGetExtReg(0xB4U);
+ ATIModifyExtReg(pATI, 0xB4U, pATI->LockData.b4, 0x00U, 0x00U);
+ pATI->LockData.b5 = ATIGetExtReg(0xB5U);
+ ATIModifyExtReg(pATI, 0xB5U, pATI->LockData.b5, 0xBFU, 0x00U);
+ pATI->LockData.b6 = ATIGetExtReg(0xB6U);
+ ATIModifyExtReg(pATI, 0xB6U, pATI->LockData.b6, 0xDDU, 0x00U);
+ pATI->LockData.b8 = ATIGetExtReg(0xB8U);
+ ATIModifyExtReg(pATI, 0xB8U, pATI->LockData.b8, 0xC0U, 0x00U);
+ pATI->LockData.b9 = ATIGetExtReg(0xB9U);
+ ATIModifyExtReg(pATI, 0xB9U, pATI->LockData.b9, 0x7FU, 0x00U);
+ if (pATI->Chip > ATI_CHIP_18800)
+ {
+ pATI->LockData.be = ATIGetExtReg(0xBEU);
+ ATIModifyExtReg(pATI, 0xBEU, pATI->LockData.be, 0xFAU, 0x01U);
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ pATI->LockData.a6 = ATIGetExtReg(0xA6U);
+ ATIModifyExtReg(pATI, 0xA6U, pATI->LockData.a6,
+ 0x7FU, 0x00U);
+ pATI->LockData.ab = ATIGetExtReg(0xABU);
+ ATIModifyExtReg(pATI, 0xABU, pATI->LockData.ab,
+ 0xE7U, 0x00U);
+ }
+ }
+ }
+
+ if (pATI->LCDPanelID >= 0)
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ /* Setup to unlock non-shadow registers */
+ lcd_gen_ctrl = saved_lcd_gen_ctrl &
+ ~(SHADOW_EN | SHADOW_RW_EN);
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ saved_lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+
+ /* Setup to unlock non-shadow registers */
+ lcd_gen_ctrl = saved_lcd_gen_ctrl &
+ ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN);
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+ }
+ }
+
+ ATISetVGAIOBase(pATI, inb(R_GENMO));
+
+ /*
+ * There's a bizarre interaction here. If bit 0x80 of CRTC[17] is on,
+ * then CRTC[3] is read-only. If bit 0x80 of CRTC[3] is off, then
+ * CRTC[17] is write-only (or a read attempt actually returns bits from
+ * C/EGA's light pen position). This means that if both conditions are
+ * met, CRTC[17]'s value on server entry cannot be retrieved.
+ */
+
+ pATI->LockData.crt03 = tmp = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
+ if ((tmp & 0x80U) ||
+ ((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
+ tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
+ {
+ /* CRTC[16-17] should be readable */
+ pATI->LockData.crt11 = tmp =
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
+ if (tmp & 0x80U) /* Unprotect CRTC[0-7] */
+ outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
+ }
+ else
+ {
+ /*
+ * Could not make CRTC[17] readable, so unprotect CRTC[0-7]
+ * replacing VSyncEnd with zero. This zero will be replaced after
+ * acquiring the needed access.
+ */
+ unsigned int VSyncEnd, VBlankStart, VBlankEnd;
+ CARD8 crt07, crt09;
+
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
+ /* Make CRTC[16-17] readable */
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
+ /* Make vertical synch pulse as wide as possible */
+ crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
+ crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
+ VBlankStart = (((crt09 & 0x20U) << 4) | ((crt07 & 0x08U) << 5) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
+ VBlankEnd = (VBlankStart & 0x0300U) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
+ if (VBlankEnd <= VBlankStart)
+ VBlankEnd += 0x0100U;
+ VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
+ if (VSyncEnd >= VBlankEnd)
+ VSyncEnd = VBlankEnd - 1;
+ pATI->LockData.crt11 = (VSyncEnd & 0x0FU) | 0x20U;
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
+ pATI->LockData.crt11 |= 0x80U;
+ }
+
+ if (pATI->LCDPanelID >= 0)
+ {
+ /* Setup to unlock shadow registers */
+ lcd_gen_ctrl |= SHADOW_EN | SHADOW_RW_EN;
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+
+ /* Unlock shadow registers */
+ ATISetVGAIOBase(pATI, inb(R_GENMO));
+
+ pATI->LockData.shadow_crt03 = tmp =
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
+ if ((tmp & 0x80U) ||
+ ((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
+ tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
+ {
+ /* CRTC[16-17] should be readable */
+ pATI->LockData.shadow_crt11 = tmp =
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
+ if (tmp & 0x80U) /* Unprotect CRTC[0-7] */
+ outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
+ else if (!tmp && pATI->LockData.crt11)
+ {
+ pATI->LockData.shadow_crt11 = tmp = pATI->LockData.crt11;
+ outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
+ }
+ }
+ else
+ {
+ /*
+ * Could not make CRTC[17] readable, so unprotect CRTC[0-7]
+ * replacing VSyncEnd with zero. This zero will be replaced
+ * after acquiring the needed access.
+ */
+ unsigned int VSyncEnd, VBlankStart, VBlankEnd;
+ CARD8 crt07, crt09;
+
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
+ /* Make CRTC[16-17] readable */
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
+ /* Make vertical synch pulse as wide as possible */
+ crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
+ crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
+ VBlankStart = (((crt09 & 0x20U) << 4) |
+ ((crt07 & 0x08U) << 5) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
+ VBlankEnd = (VBlankStart & 0x0300U) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
+ if (VBlankEnd <= VBlankStart)
+ VBlankEnd += 0x0100U;
+ VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
+ GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
+ if (VSyncEnd >= VBlankEnd)
+ VSyncEnd = VBlankEnd - 1;
+ pATI->LockData.shadow_crt11 = (VSyncEnd & 0x0FU) | 0x20U;
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
+ pATI->LockData.shadow_crt11);
+ pATI->LockData.shadow_crt11 |= 0x80U;
+ }
+
+ /* Restore selection */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
+
+ /* Restore LCD index */
+ out8(LCD_INDEX, GetByte(pATI->LockData.lcd_index, 0));
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ }
+}
+
+/*
+ * ATILock --
+ *
+ * This function restores the state saved by ATIUnlock() above.
+ */
+void
+ATILock
+(
+ ATIPtr pATI
+)
+{
+
+#ifndef AVOID_CPIO
+
+ CARD32 tmp, saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
+
+#endif /* AVOID_CPIO */
+
+ if (!pATI->Unlocked)
+ return;
+ pATI->Unlocked = FALSE;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ if (pATI->LCDPanelID >= 0)
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ /* Setup to lock non-shadow registers */
+ lcd_gen_ctrl = saved_lcd_gen_ctrl &
+ ~(SHADOW_EN | SHADOW_RW_EN);
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ saved_lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+
+ /* Setup to lock non-shadow registers */
+ lcd_gen_ctrl = saved_lcd_gen_ctrl &
+ ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN);
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+ }
+ }
+
+ ATISetVGAIOBase(pATI, inb(R_GENMO));
+
+ /* Restore VGA locks */
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, pATI->LockData.crt03);
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
+
+ if (pATI->LCDPanelID >= 0)
+ {
+ /* Setup to lock shadow registers */
+ lcd_gen_ctrl |= SHADOW_EN | SHADOW_RW_EN;
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+
+ /* Lock shadow registers */
+ ATISetVGAIOBase(pATI, inb(R_GENMO));
+
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x03U,
+ pATI->LockData.shadow_crt03);
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
+ pATI->LockData.shadow_crt11);
+
+ /* Restore selection */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
+ }
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ /*
+ * Restore emulation and protection bits in ATI extended VGA
+ * registers.
+ */
+ ATIModifyExtReg(pATI, 0xB1U, -1, 0xFCU, pATI->LockData.b1);
+ ATIModifyExtReg(pATI, 0xB4U, -1, 0x00U, pATI->LockData.b4);
+ ATIModifyExtReg(pATI, 0xB5U, -1, 0xBFU, pATI->LockData.b5);
+ ATIModifyExtReg(pATI, 0xB6U, -1, 0xDDU, pATI->LockData.b6);
+ ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8 & 0x03U);
+ ATIModifyExtReg(pATI, 0xB9U, -1, 0x7FU, pATI->LockData.b9);
+ if (pATI->Chip > ATI_CHIP_18800)
+ {
+ ATIModifyExtReg(pATI, 0xBEU, -1, 0xFAU, pATI->LockData.be);
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ ATIModifyExtReg(pATI, 0xA6U, -1, 0x7FU, pATI->LockData.a6);
+ ATIModifyExtReg(pATI, 0xABU, -1, 0xE7U, pATI->LockData.ab);
+ }
+ }
+ ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8);
+ }
+ }
+
+ if (pATI->ChipHasSUBSYS_CNTL)
+ {
+ tmp = inw(SUBSYS_STAT) & _8PLANE;
+
+ /* Reset the 8514/A and disable all interrupts */
+ outw(SUBSYS_CNTL, tmp | (GPCTRL_RESET | CHPTEST_NORMAL));
+ outw(SUBSYS_CNTL, tmp | (GPCTRL_ENAB | CHPTEST_NORMAL | RVBLNKFLG |
+ RPICKFLAG | RINVALIDIO | RGPIDLE));
+
+ /* Restore modified accelerator registers */
+ outw(CLOCK_SEL, pATI->LockData.clock_sel);
+ if (pATI->Chip >= ATI_CHIP_68800)
+ {
+ outw(MISC_OPTIONS, pATI->LockData.misc_options);
+ outw(MEM_BNDRY, pATI->LockData.mem_bndry);
+ outw(MEM_CFG, pATI->LockData.mem_cfg);
+ }
+
+ /* Wait for all activity to die down */
+ ProbeWaitIdleEmpty();
+ }
+ else if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+ /* Reset everything */
+ outr(BUS_CNTL, pATI->LockData.bus_cntl);
+
+ outr(CRTC_INT_CNTL, pATI->LockData.crtc_int_cntl);
+
+ outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
+ outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl);
+ outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
+
+ outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
+ outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl);
+ outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
+
+#ifndef AVOID_CPIO
+
+ outr(CONFIG_CNTL, pATI->LockData.config_cntl);
+
+#endif /* AVOID_CPIO */
+
+ outr(DAC_CNTL, pATI->LockData.dac_cntl);
+ if (pATI->Chip < ATI_CHIP_264CT)
+ outr(MEM_CNTL, pATI->LockData.mem_cntl);
+ if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
+ {
+ outr(LCD_INDEX, pATI->LockData.lcd_index);
+ if (pATI->Chip != ATI_CHIP_264XL)
+ outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
+ }
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ outr(MPP_CONFIG, pATI->LockData.mpp_config);
+ outr(MPP_STROBE_SEQ, pATI->LockData.mpp_strobe_seq);
+ outr(TVO_CNTL, pATI->LockData.tvo_cntl);
+ if (pATI->Chip >= ATI_CHIP_264GT2C)
+ {
+ outr(HW_DEBUG, pATI->LockData.hw_debug);
+ if (pATI->Chip >= ATI_CHIP_264GTPRO)
+ {
+ outr(I2C_CNTL_0, pATI->LockData.i2c_cntl_0);
+ outr(I2C_CNTL_1, pATI->LockData.i2c_cntl_1);
+ }
+ }
+ }
+ }
+}
diff --git a/src/atilock.h b/src/atilock.h
new file mode 100644
index 0000000..9b94943
--- /dev/null
+++ b/src/atilock.h
@@ -0,0 +1,33 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.h,v 1.5 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATILOCK_H___
+#define ___ATILOCK_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+extern void ATIUnlock FunctionPrototype((ATIPtr));
+extern void ATILock FunctionPrototype((ATIPtr));
+
+#endif /* ___ATILOCK_H___ */
diff --git a/src/atimach64.c b/src/atimach64.c
new file mode 100644
index 0000000..1f457e8
--- /dev/null
+++ b/src/atimach64.c
@@ -0,0 +1,2164 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c,v 1.51 2003/02/24 20:46:54 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atibus.h"
+#include "atichip.h"
+#include "atidac.h"
+#include "atimach64.h"
+#include "atimach64io.h"
+#include "atirgb514.h"
+
+#include "miline.h"
+
+#ifndef DPMS_SERVER
+# define DPMS_SERVER
+#endif
+#include "extensions/dpms.h"
+
+/*
+ * X-to-Mach64 mix translation table.
+ */
+static CARD8 ATIMach64ALU[16] =
+{
+ MIX_0,
+ MIX_AND,
+ MIX_SRC_AND_NOT_DST,
+ MIX_SRC,
+ MIX_NOT_SRC_AND_DST,
+ MIX_DST,
+ MIX_XOR,
+ MIX_OR,
+ MIX_NOR,
+ MIX_XNOR,
+ MIX_NOT_DST,
+ MIX_SRC_OR_NOT_DST,
+ MIX_NOT_SRC,
+ MIX_NOT_SRC_OR_DST,
+ MIX_NAND,
+ MIX_1
+};
+
+/*
+ * ATIMach64PreInit --
+ *
+ * This function fills in the Mach64 portion of an ATIHWRec that is common to
+ * all video modes generated by the driver.
+ */
+void
+ATIMach64PreInit
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ CARD32 bus_cntl, config_cntl;
+ int tmp;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth <= 4)
+ pATIHW->crtc_off_pitch = SetBits(pATI->displayWidth >> 4, CRTC_PITCH);
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->crtc_off_pitch = SetBits(pATI->displayWidth >> 3, CRTC_PITCH);
+ }
+
+ if ((pATI->LockData.crtc_gen_cntl & CRTC_CSYNC_EN) && !pATI->OptionCSync)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Using composite sync to match input timing.\n");
+ pATI->OptionCSync = TRUE;
+ }
+
+ pATIHW->bus_cntl = bus_cntl = inr(BUS_CNTL);
+ if (pATI->Chip < ATI_CHIP_264VT4)
+ pATIHW->bus_cntl = (pATIHW->bus_cntl & ~BUS_HOST_ERR_INT_EN) |
+ BUS_HOST_ERR_INT;
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ {
+ pATIHW->bus_cntl &= ~(BUS_FIFO_ERR_INT_EN | BUS_ROM_DIS);
+ pATIHW->bus_cntl |= SetBits(15, BUS_FIFO_WS) | BUS_FIFO_ERR_INT;
+ }
+ else if (pATI->MMIOInLinear)
+ {
+ pATIHW->bus_cntl &= ~BUS_APER_REG_DIS;
+ }
+ else
+ {
+ pATIHW->bus_cntl |= BUS_APER_REG_DIS;
+ }
+ if (pATI->Chip >= ATI_CHIP_264VT)
+ pATIHW->bus_cntl |= BUS_EXT_REG_EN; /* Enable Block 1 */
+
+#ifdef AVOID_CPIO
+
+ pATIHW->mem_vga_wp_sel = SetBits(0, MEM_VGA_WPS0) |
+ SetBits(1, MEM_VGA_WPS1);
+ pATIHW->mem_vga_rp_sel = SetBits(0, MEM_VGA_RPS0) |
+ SetBits(1, MEM_VGA_RPS1);
+
+#else /* AVOID_CPIO */
+
+ pATIHW->mem_vga_wp_sel = SetBits(0, MEM_VGA_WPS0) |
+ SetBits(pATIHW->nPlane, MEM_VGA_WPS1);
+ pATIHW->mem_vga_rp_sel = SetBits(0, MEM_VGA_RPS0) |
+ SetBits(pATIHW->nPlane, MEM_VGA_RPS1);
+
+#endif /* AVOID_CPIO */
+
+ pATIHW->dac_cntl = inr(DAC_CNTL) &
+ ~(DAC1_CLK_SEL | DAC_PALETTE_ACCESS_CNTL | DAC_8BIT_EN);
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ pATIHW->dac_cntl &= ~DAC_FEA_CON_EN;
+ if (pATI->rgbBits == 8)
+ pATIHW->dac_cntl |= DAC_8BIT_EN;
+
+ pATIHW->gen_test_cntl = pATI->LockData.gen_test_cntl & ~GEN_CUR_EN;
+ if (pATI->DAC == ATI_DAC_IBMRGB514)
+ pATIHW->gen_test_cntl |= GEN_OVR_OUTPUT_EN;
+
+ pATIHW->config_cntl = config_cntl = inr(CONFIG_CNTL);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->UseSmallApertures)
+ pATIHW->config_cntl |= CFG_MEM_VGA_AP_EN;
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->config_cntl &= ~CFG_MEM_VGA_AP_EN;
+ }
+
+ if (pATI->LinearBase && (pATI->Chip < ATI_CHIP_264CT))
+ {
+ /* Replace linear aperture size and address */
+ pATIHW->config_cntl &= ~(CFG_MEM_AP_LOC | CFG_MEM_AP_SIZE);
+ pATIHW->config_cntl |= SetBits(pATI->LinearBase >> 22, CFG_MEM_AP_LOC);
+ if ((pATI->Chip < ATI_CHIP_264CT) && (pATI->VideoRAM < 4096))
+ pATIHW->config_cntl |= SetBits(1, CFG_MEM_AP_SIZE);
+ else
+ pATIHW->config_cntl |= SetBits(2, CFG_MEM_AP_SIZE);
+ }
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ pATIHW->mem_cntl = (pATI->LockData.mem_cntl &
+ ~(CTL_MEM_LOWER_APER_ENDIAN | CTL_MEM_UPPER_APER_ENDIAN)) |
+ SetBits(CTL_MEM_APER_BYTE_ENDIAN, CTL_MEM_LOWER_APER_ENDIAN);
+
+ switch (pATI->bitsPerPixel)
+ {
+ default:
+ pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_BYTE_ENDIAN,
+ CTL_MEM_UPPER_APER_ENDIAN);
+ break;
+
+ case 16:
+ pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_WORD_ENDIAN,
+ CTL_MEM_UPPER_APER_ENDIAN);
+ break;
+
+ case 32:
+ pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_LONG_ENDIAN,
+ CTL_MEM_UPPER_APER_ENDIAN);
+ break;
+ }
+
+ pATIHW->mpp_config = inr(MPP_CONFIG);
+ pATIHW->mpp_config &=
+ ~(MPP_PRESCALE | MPP_NSTATES | MPP_FORMAT | MPP_WAIT_STATE |
+ MPP_INSERT_WAIT | MPP_TRISTATE_ADDR | MPP_AUTO_INC_EN |
+ MPP_CHKREQ_EN | MPP_BUFFER_SIZE | MPP_BUFFER_MODE | MPP_BUSY);
+ pATIHW->mpp_config |=
+ (MPP_NSTATES_8 | MPP_FORMAT_DA8 | SetBits(4, MPP_WAIT_STATE) |
+ MPP_CHKRDY_EN | MPP_READ_EARLY | MPP_RW_MODE | MPP_EN);
+ pATIHW->mpp_strobe_seq = inr(MPP_STROBE_SEQ);
+ pATIHW->mpp_strobe_seq &= ~(MPP_STB0_SEQ | MPP_STB1_SEQ);
+ pATIHW->mpp_strobe_seq |=
+ SetBits(0x0087U, MPP_STB0_SEQ) | SetBits(0x0083U, MPP_STB1_SEQ);
+ pATIHW->tvo_cntl = 0;
+ }
+
+ /* Draw engine setup */
+ if (pATI->OptionAccel)
+ {
+ /* Ensure apertures are enabled */
+ outr(BUS_CNTL, pATIHW->bus_cntl);
+ outr(CONFIG_CNTL, pATIHW->config_cntl);
+
+ /*
+ * When possible, max out command FIFO size.
+ */
+ if (pATI->Chip >= ATI_CHIP_264VT4)
+ pATIHW->gui_cntl = inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE;
+
+ /* Initialise destination registers */
+ pATIHW->dst_off_pitch =
+ SetBits((pATI->displayWidth * pATI->XModifier) >> 3, DST_PITCH);
+ pATIHW->dst_cntl = DST_X_DIR | DST_Y_DIR | DST_LAST_PEL;
+
+ /* Initialise source registers */
+ pATIHW->src_off_pitch = pATIHW->dst_off_pitch;
+ pATIHW->src_width1 = pATIHW->src_height1 =
+ pATIHW->src_width2 = pATIHW->src_height2 = 1;
+ pATIHW->src_cntl = SRC_LINE_X_DIR;
+
+ /* Initialise scissor, allowing for offscreen areas */
+ pATIHW->sc_right = (pATI->displayWidth * pATI->XModifier) - 1;
+ tmp = (pScreenInfo->videoRam * (1024 * 8) /
+ pATI->displayWidth / pATI->bitsPerPixel) - 1;
+ if (tmp > ATIMach64MaxY)
+ tmp = ATIMach64MaxY;
+ pATIHW->sc_bottom = tmp;
+ pATI->sc_left_right = SetWord(pATI->NewHW.sc_right, 1) |
+ SetWord(pATI->NewHW.sc_left, 0);
+ pATI->sc_top_bottom = SetWord(pATI->NewHW.sc_bottom, 1) |
+ SetWord(pATI->NewHW.sc_top, 0);
+
+ /* Initialise data path */
+ pATIHW->dp_frgd_clr = (CARD32)(-1);
+ pATIHW->dp_write_mask = (CARD32)(-1);
+
+ switch (pATI->depth)
+ {
+ case 8:
+ pATIHW->dp_chain_mask = DP_CHAIN_8BPP;
+ pATIHW->dp_pix_width =
+ SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
+ break;
+
+ case 15:
+ pATIHW->dp_chain_mask = DP_CHAIN_15BPP_1555;
+ pATIHW->dp_pix_width =
+ SetBits(PIX_WIDTH_15BPP, DP_DST_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_15BPP, DP_SRC_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
+ break;
+
+ case 16:
+ pATIHW->dp_chain_mask = DP_CHAIN_16BPP_565;
+ pATIHW->dp_pix_width =
+ SetBits(PIX_WIDTH_16BPP, DP_DST_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_16BPP, DP_SRC_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
+ break;
+
+ case 24:
+ if (pATI->bitsPerPixel == 24)
+ {
+ pATIHW->dp_chain_mask = DP_CHAIN_24BPP_888;
+ pATIHW->dp_pix_width =
+ SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
+ }
+ else
+ {
+ pATIHW->dp_chain_mask = DP_CHAIN_32BPP_8888;
+ pATIHW->dp_pix_width =
+ SetBits(PIX_WIDTH_32BPP, DP_DST_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_32BPP, DP_SRC_PIX_WIDTH) |
+ SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+
+ pATIHW->dp_pix_width |= DP_BYTE_PIX_ORDER;
+
+#endif /* X_BYTE_ORDER */
+
+ pATIHW->dp_mix = SetBits(MIX_SRC, DP_FRGD_MIX) |
+ SetBits(MIX_DST, DP_BKGD_MIX);
+ pATIHW->dp_src = DP_MONO_SRC_ALLONES |
+ SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC);
+
+ /* Initialise colour compare */
+ pATIHW->clr_cmp_msk = (1 << pATI->depth) - 1;
+
+ /* Restore aperture enablement */
+ outr(BUS_CNTL, bus_cntl);
+ outr(CONFIG_CNTL, config_cntl);
+ }
+}
+
+/*
+ * ATIMach64Save --
+ *
+ * This function is called to save the Mach64 portion of the current video
+ * state.
+ */
+void
+ATIMach64Save
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
+ pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
+ pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
+ pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
+
+ pATIHW->crtc_off_pitch = inr(CRTC_OFF_PITCH);
+
+ pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+
+ pATIHW->ovr_clr = inr(OVR_CLR);
+ pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
+ pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
+
+ pATIHW->cur_clr0 = inr(CUR_CLR0);
+ pATIHW->cur_clr1 = inr(CUR_CLR1);
+ pATIHW->cur_offset = inr(CUR_OFFSET);
+ pATIHW->cur_horz_vert_posn = inr(CUR_HORZ_VERT_POSN);
+ pATIHW->cur_horz_vert_off = inr(CUR_HORZ_VERT_OFF);
+
+ pATIHW->clock_cntl = inr(CLOCK_CNTL);
+
+ pATIHW->bus_cntl = inr(BUS_CNTL);
+
+ pATIHW->mem_vga_wp_sel = inr(MEM_VGA_WP_SEL);
+ pATIHW->mem_vga_rp_sel = inr(MEM_VGA_RP_SEL);
+
+ pATIHW->dac_cntl = inr(DAC_CNTL);
+
+ pATIHW->config_cntl = inr(CONFIG_CNTL);
+
+ pATIHW->gen_test_cntl = inr(GEN_TEST_CNTL) & ~GEN_CUR_EN;
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ pATIHW->mem_cntl = inr(MEM_CNTL);
+ pATIHW->mpp_config = inr(MPP_CONFIG);
+ pATIHW->mpp_strobe_seq = inr(MPP_STROBE_SEQ);
+ pATIHW->tvo_cntl = inr(TVO_CNTL);
+ }
+
+ /* Save draw engine state */
+ if (pATI->OptionAccel && (pATIHW == &pATI->OldHW))
+ {
+ /* Ensure apertures are enabled */
+ outr(BUS_CNTL, pATI->NewHW.bus_cntl);
+ outr(CONFIG_CNTL, pATI->NewHW.config_cntl);
+
+ ATIMach64WaitForIdle(pATI);
+
+ /* Save FIFO size */
+ if (pATI->Chip >= ATI_CHIP_264VT4)
+ pATIHW->gui_cntl = inm(GUI_CNTL);
+
+ /* Save destination registers */
+ pATIHW->dst_off_pitch = inm(DST_OFF_PITCH);
+ pATIHW->dst_x = inm(DST_X);
+ pATIHW->dst_y = inm(DST_Y);
+ pATIHW->dst_height = inm(DST_HEIGHT);
+ pATIHW->dst_bres_err = inm(DST_BRES_ERR);
+ pATIHW->dst_bres_inc = inm(DST_BRES_INC);
+ pATIHW->dst_bres_dec = inm(DST_BRES_DEC);
+ pATIHW->dst_cntl = inm(DST_CNTL);
+
+ /* Save source registers */
+ pATIHW->src_off_pitch = inm(SRC_OFF_PITCH);
+ pATIHW->src_x = inm(SRC_X);
+ pATIHW->src_y = inm(SRC_Y);
+ pATIHW->src_width1 = inm(SRC_WIDTH1);
+ pATIHW->src_height1 = inm(SRC_HEIGHT1);
+ pATIHW->src_x_start = inm(SRC_X_START);
+ pATIHW->src_y_start = inm(SRC_Y_START);
+ pATIHW->src_width2 = inm(SRC_WIDTH2);
+ pATIHW->src_height2 = inm(SRC_HEIGHT2);
+ pATIHW->src_cntl = inm(SRC_CNTL);
+
+ /* Save host data register */
+ pATIHW->host_cntl = inm(HOST_CNTL);
+
+ /* Save pattern registers */
+ pATIHW->pat_reg0 = inm(PAT_REG0);
+ pATIHW->pat_reg1 = inm(PAT_REG1);
+ pATIHW->pat_cntl = inm(PAT_CNTL);
+
+ /* Save scissor registers */
+ pATIHW->sc_left = pATI->sc_left = inm(SC_LEFT);
+ pATIHW->sc_right = pATI->sc_right = inm(SC_RIGHT);
+ pATIHW->sc_top = pATI->sc_top = inm(SC_TOP);
+ pATIHW->sc_bottom = pATI->sc_bottom = inm(SC_BOTTOM);
+
+ /* Save data path registers */
+ pATIHW->dp_bkgd_clr = inm(DP_BKGD_CLR);
+ pATIHW->dp_frgd_clr = inm(DP_FRGD_CLR);
+ pATIHW->dp_write_mask = inm(DP_WRITE_MASK);
+ pATIHW->dp_chain_mask = inm(DP_CHAIN_MASK);
+ pATIHW->dp_pix_width = inm(DP_PIX_WIDTH);
+ pATIHW->dp_mix = inm(DP_MIX);
+ pATIHW->dp_src = inm(DP_SRC);
+
+ /* Save colour compare registers */
+ pATIHW->clr_cmp_clr = inm(CLR_CMP_CLR);
+ pATIHW->clr_cmp_msk = inm(CLR_CMP_MSK);
+ pATIHW->clr_cmp_cntl = inm(CLR_CMP_CNTL);
+
+ /* Save context */
+ pATIHW->context_mask = inm(CONTEXT_MASK);
+
+ /* Restore aperture enablement */
+ outr(BUS_CNTL, pATIHW->bus_cntl);
+ outr(CONFIG_CNTL, pATIHW->config_cntl);
+ }
+}
+
+/*
+ * ATIMach64Calculate --
+ *
+ * This function is called to fill in the Mach64 portion of an ATIHWRec.
+ */
+void
+ATIMach64Calculate
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ int VDisplay;
+
+ /* If not already done adjust horizontal timings */
+ if (!pMode->CrtcHAdjusted)
+ {
+ pMode->CrtcHAdjusted = TRUE;
+ /* XXX Deal with Blank Start/End and overscan later */
+ pMode->CrtcHDisplay = (pMode->HDisplay >> 3) - 1;
+ pMode->CrtcHSyncStart = (pMode->HSyncStart >> 3) - 1;
+ pMode->CrtcHSyncEnd = (pMode->HSyncEnd >> 3) - 1;
+ pMode->CrtcHTotal = (pMode->HTotal >> 3) - 1;
+
+ /* Make adjustments if sync pulse width is out-of-bounds */
+ if ((pMode->CrtcHSyncEnd - pMode->CrtcHSyncStart) >
+ (int)MaxBits(CRTC_H_SYNC_WID))
+ pMode->CrtcHSyncEnd =
+ pMode->CrtcHSyncStart + MaxBits(CRTC_H_SYNC_WID);
+ else if (pMode->CrtcHSyncStart == pMode->CrtcHSyncEnd)
+ {
+ if (pMode->CrtcHDisplay < pMode->CrtcHSyncStart)
+ pMode->CrtcHSyncStart--;
+ else if (pMode->CrtcHSyncEnd < pMode->CrtcHTotal)
+ pMode->CrtcHSyncEnd++;
+ }
+ }
+
+ /*
+ * Always re-do vertical adjustments.
+ */
+ pMode->CrtcVDisplay = pMode->VDisplay;
+ pMode->CrtcVSyncStart = pMode->VSyncStart;
+ pMode->CrtcVSyncEnd = pMode->VSyncEnd;
+ pMode->CrtcVTotal = pMode->VTotal;
+
+ if ((pATI->Chip >= ATI_CHIP_264CT) &&
+ ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1)))
+ {
+ pMode->CrtcVDisplay <<= 1;
+ pMode->CrtcVSyncStart <<= 1;
+ pMode->CrtcVSyncEnd <<= 1;
+ pMode->CrtcVTotal <<= 1;
+ }
+
+ /*
+ * Might as well default to the same as VGA with respect to sync
+ * polarities.
+ */
+ if ((!(pMode->Flags & (V_PHSYNC | V_NHSYNC))) ||
+ (!(pMode->Flags & (V_PVSYNC | V_NVSYNC))))
+ {
+ pMode->Flags &= ~(V_PHSYNC | V_NHSYNC | V_PVSYNC | V_NVSYNC);
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ VDisplay = pATI->LCDVertical;
+ else
+ VDisplay = pMode->CrtcVDisplay;
+
+ if (VDisplay < 400)
+ pMode->Flags |= V_PHSYNC | V_NVSYNC;
+ else if (VDisplay < 480)
+ pMode->Flags |= V_NHSYNC | V_PVSYNC;
+ else if (VDisplay < 768)
+ pMode->Flags |= V_NHSYNC | V_NVSYNC;
+ else
+ pMode->Flags |= V_PHSYNC | V_PVSYNC;
+ }
+
+ pMode->CrtcVDisplay--;
+ pMode->CrtcVSyncStart--;
+ pMode->CrtcVSyncEnd--;
+ pMode->CrtcVTotal--;
+ /* Make sure sync pulse is not too wide */
+ if ((pMode->CrtcVSyncEnd - pMode->CrtcVSyncStart) >
+ (int)MaxBits(CRTC_V_SYNC_WID))
+ pMode->CrtcVSyncEnd = pMode->CrtcVSyncStart + MaxBits(CRTC_V_SYNC_WID);
+ pMode->CrtcVAdjusted = TRUE; /* Redundant */
+
+ /* Build register contents */
+ pATIHW->crtc_h_total_disp =
+ SetBits(pMode->CrtcHTotal, CRTC_H_TOTAL) |
+ SetBits(pMode->CrtcHDisplay, CRTC_H_DISP);
+ pATIHW->crtc_h_sync_strt_wid =
+ SetBits(pMode->CrtcHSyncStart, CRTC_H_SYNC_STRT) |
+ SetBits(pMode->CrtcHSkew, CRTC_H_SYNC_DLY) | /* ? */
+ SetBits(GetBits(pMode->CrtcHSyncStart, 0x0100U),
+ CRTC_H_SYNC_STRT_HI) |
+ SetBits(pMode->CrtcHSyncEnd - pMode->CrtcHSyncStart,
+ CRTC_H_SYNC_WID);
+ if (pMode->Flags & V_NHSYNC)
+ pATIHW->crtc_h_sync_strt_wid |= CRTC_H_SYNC_POL;
+
+ pATIHW->crtc_v_total_disp =
+ SetBits(pMode->CrtcVTotal, CRTC_V_TOTAL) |
+ SetBits(pMode->CrtcVDisplay, CRTC_V_DISP);
+ pATIHW->crtc_v_sync_strt_wid =
+ SetBits(pMode->CrtcVSyncStart, CRTC_V_SYNC_STRT) |
+ SetBits(pMode->CrtcVSyncEnd - pMode->CrtcVSyncStart,
+ CRTC_V_SYNC_WID);
+ if (pMode->Flags & V_NVSYNC)
+ pATIHW->crtc_v_sync_strt_wid |= CRTC_V_SYNC_POL;
+
+ pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
+ ~(CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN |
+ CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_CSYNC_EN |
+ CRTC_PIX_BY_2_EN | CRTC_DISPLAY_DIS | CRTC_VGA_XOVERSCAN |
+ CRTC_PIX_WIDTH | CRTC_BYTE_PIX_ORDER |
+ CRTC_VGA_128KAP_PAGING | CRTC_VFC_SYNC_TRISTATE |
+ CRTC_LOCK_REGS | /* Already off, but ... */
+ CRTC_SYNC_TRISTATE | CRTC_DISP_REQ_EN |
+ CRTC_VGA_TEXT_132 | CRTC_CUR_B_TEST);
+ pATIHW->crtc_gen_cntl |=
+ CRTC_EXT_DISP_EN | CRTC_EN | CRTC_VGA_LINEAR | CRTC_CNT_EN;
+ switch (pATI->depth)
+ {
+
+#ifndef AVOID_CPIO
+
+ case 1:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_1BPP, CRTC_PIX_WIDTH);
+ break;
+
+ case 4:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_4BPP, CRTC_PIX_WIDTH);
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case 8:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_8BPP, CRTC_PIX_WIDTH);
+ break;
+
+ case 15:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_15BPP, CRTC_PIX_WIDTH);
+ break;
+
+ case 16:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_16BPP, CRTC_PIX_WIDTH);
+ break;
+
+ case 24:
+ if (pATI->bitsPerPixel == 24)
+ {
+ pATIHW->crtc_gen_cntl |=
+ SetBits(PIX_WIDTH_24BPP, CRTC_PIX_WIDTH);
+ break;
+ }
+ if (pATI->bitsPerPixel != 32)
+ break;
+ /* Fall through */
+
+ case 32:
+ pATIHW->crtc_gen_cntl |= SetBits(PIX_WIDTH_32BPP, CRTC_PIX_WIDTH);
+ break;
+
+ default:
+ break;
+ }
+ if ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1))
+ pATIHW->crtc_gen_cntl |= CRTC_DBL_SCAN_EN;
+ if (pMode->Flags & V_INTERLACE)
+ pATIHW->crtc_gen_cntl |= CRTC_INTERLACE_EN;
+ if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
+ pATIHW->crtc_gen_cntl |= CRTC_CSYNC_EN;
+ /* For now, set display FIFO low water mark as high as possible */
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ pATIHW->crtc_gen_cntl |= CRTC_FIFO_LWM;
+}
+
+/*
+ * ATIMach64Set --
+ *
+ * This function is called to load a Mach64's accelerator CRTC and draw engine.
+ */
+void
+ATIMach64Set
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ /* First, turn off the display */
+ outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl & ~CRTC_EN);
+
+ if ((pATIHW->FeedbackDivider > 0) &&
+ (pATI->ProgrammableClock != ATI_CLOCK_NONE))
+ ATIClockSet(pATI, pATIHW); /* Programme clock */
+
+ if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIRGB514Set(pATI, pATIHW);
+
+ /* Load Mach64 CRTC registers */
+ outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp);
+ outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid);
+ outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp);
+ outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid);
+
+ outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch);
+
+ /* Load overscan registers */
+ outr(OVR_CLR, pATIHW->ovr_clr);
+ outr(OVR_WID_LEFT_RIGHT, pATIHW->ovr_wid_left_right);
+ outr(OVR_WID_TOP_BOTTOM, pATIHW->ovr_wid_top_bottom);
+
+ /* Load hardware cursor registers */
+ outr(CUR_CLR0, pATIHW->cur_clr0);
+ outr(CUR_CLR1, pATIHW->cur_clr1);
+ outr(CUR_OFFSET, pATIHW->cur_offset);
+ outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn);
+ outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off);
+
+ /* Set pixel clock */
+ outr(CLOCK_CNTL, pATIHW->clock_cntl | CLOCK_STROBE);
+
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN);
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl);
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN);
+
+ /* Finalise CRTC setup and turn on the screen */
+ outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl);
+
+ /* Load draw engine */
+ if (pATI->OptionAccel)
+ {
+ /* Clobber MMIO cache */
+ (void)memset(pATI->MMIOCached, 0, SizeOf(pATI->MMIOCached));
+
+ /* Ensure apertures are enabled */
+ outr(BUS_CNTL, pATI->NewHW.bus_cntl);
+ outr(CONFIG_CNTL, pATI->NewHW.config_cntl);
+
+ pATI->EngineIsBusy = TRUE; /* Force engine poll */
+ ATIMach64WaitForIdle(pATI);
+
+ /* Load FIFO size */
+ if (pATI->Chip >= ATI_CHIP_264VT4)
+ {
+ outm(GUI_CNTL, pATIHW->gui_cntl);
+ pATI->nAvailableFIFOEntries = 0;
+ ATIMach64PollEngineStatus(pATI);
+ }
+
+ /* Set FIFO depth */
+ pATI->nFIFOEntries = pATI->nAvailableFIFOEntries;
+
+ /* Load destination registers */
+ ATIMach64WaitForFIFO(pATI, 7);
+ outf(DST_OFF_PITCH, pATIHW->dst_off_pitch);
+ outf(DST_Y_X, SetWord(pATIHW->dst_x, 1) | SetWord(pATIHW->dst_y, 0));
+ outf(DST_HEIGHT, pATIHW->dst_height);
+ outf(DST_BRES_ERR, pATIHW->dst_bres_err);
+ outf(DST_BRES_INC, pATIHW->dst_bres_inc);
+ outf(DST_BRES_DEC, pATIHW->dst_bres_dec);
+ outf(DST_CNTL, pATIHW->dst_cntl);
+
+ /* Load source registers */
+ ATIMach64WaitForFIFO(pATI, 6);
+ outf(SRC_OFF_PITCH, pATIHW->src_off_pitch);
+ outf(SRC_Y_X, SetWord(pATIHW->src_x, 1) | SetWord(pATIHW->src_y, 0));
+ outf(SRC_HEIGHT1_WIDTH1,
+ SetWord(pATIHW->src_width1, 1) | SetWord(pATIHW->src_height1, 0));
+ outf(SRC_Y_X_START,
+ SetWord(pATIHW->src_x_start, 1) | SetWord(pATIHW->src_y_start, 0));
+ outf(SRC_HEIGHT2_WIDTH2,
+ SetWord(pATIHW->src_width2, 1) | SetWord(pATIHW->src_height2, 0));
+ outf(SRC_CNTL, pATIHW->src_cntl);
+
+ /* Load host data register */
+ ATIMach64WaitForFIFO(pATI, 1);
+ outf(HOST_CNTL, pATIHW->host_cntl);
+
+ /* Set host transfer window address and size clamp */
+ pATI->pHOST_DATA =
+ (CARD8 *)pATI->pBlock[GetBits(HOST_DATA_0, BLOCK_SELECT)] +
+ (HOST_DATA_0 & MM_IO_SELECT);
+ pATI->nHostFIFOEntries = pATI->nFIFOEntries >> 1;
+ if (pATI->nHostFIFOEntries > 16)
+ pATI->nHostFIFOEntries = 16;
+
+ /* Load pattern registers */
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(PAT_REG0, pATIHW->pat_reg0);
+ outf(PAT_REG1, pATIHW->pat_reg1);
+ outf(PAT_CNTL, pATIHW->pat_cntl);
+
+ /* Load scissor registers */
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(SC_LEFT_RIGHT,
+ SetWord(pATIHW->sc_right, 1) | SetWord(pATIHW->sc_left, 0));
+ outf(SC_TOP_BOTTOM,
+ SetWord(pATIHW->sc_bottom, 1) | SetWord(pATIHW->sc_top, 0));
+ pATI->sc_left = pATIHW->sc_left;
+ pATI->sc_right = pATIHW->sc_right;
+ pATI->sc_top = pATIHW->sc_top;
+ pATI->sc_bottom = pATIHW->sc_bottom;
+
+ /* Load data path registers */
+ ATIMach64WaitForFIFO(pATI, 7);
+ outf(DP_BKGD_CLR, pATIHW->dp_bkgd_clr);
+ outf(DP_FRGD_CLR, pATIHW->dp_frgd_clr);
+ outf(DP_WRITE_MASK, pATIHW->dp_write_mask);
+ outf(DP_CHAIN_MASK, pATIHW->dp_chain_mask);
+ outf(DP_PIX_WIDTH, pATIHW->dp_pix_width);
+ outf(DP_MIX, pATIHW->dp_mix);
+ outf(DP_SRC, pATIHW->dp_src);
+
+ /* Load colour compare registers */
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(CLR_CMP_CLR, pATIHW->clr_cmp_clr);
+ outf(CLR_CMP_MSK, pATIHW->clr_cmp_msk);
+ outf(CLR_CMP_CNTL, pATIHW->clr_cmp_cntl);
+
+ /* Load context mask */
+ ATIMach64WaitForFIFO(pATI, 1);
+ outf(CONTEXT_MASK, pATIHW->context_mask);
+
+ ATIMach64WaitForIdle(pATI);
+
+ if (pATI->OptionMMIOCache)
+ {
+ /*
+ * Enable write caching for selected MMIO registers. This can only
+ * be done for those registers whose value does not change without
+ * driver intervention.
+ */
+
+ CacheRegister(SRC_CNTL);
+
+ CacheRegister(HOST_CNTL);
+
+ CacheRegister(PAT_REG0);
+ CacheRegister(PAT_REG1);
+ CacheRegister(PAT_CNTL);
+
+ CacheRegister(SC_LEFT_RIGHT);
+ CacheRegister(SC_TOP_BOTTOM);
+
+ CacheRegister(DP_BKGD_CLR);
+ CacheRegister(DP_FRGD_CLR);
+ CacheRegister(DP_WRITE_MASK);
+ CacheRegister(DP_MIX);
+
+ CacheRegister(CLR_CMP_CLR);
+ CacheRegister(CLR_CMP_MSK);
+ CacheRegister(CLR_CMP_CNTL);
+ }
+ }
+
+ /* Aperture setup */
+ outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel);
+ outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel);
+
+ outr(DAC_CNTL, pATIHW->dac_cntl);
+
+ outr(CONFIG_CNTL, pATIHW->config_cntl);
+ outr(BUS_CNTL, pATIHW->bus_cntl);
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ outr(MEM_CNTL, pATIHW->mem_cntl);
+ outr(MPP_CONFIG, pATIHW->mpp_config);
+ outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq);
+ outr(TVO_CNTL, pATIHW->tvo_cntl);
+ }
+}
+
+/*
+ * ATIMach64SaveScreen --
+ *
+ * This function blanks or unblanks a Mach64 screen.
+ */
+void
+ATIMach64SaveScreen
+(
+ ATIPtr pATI,
+ int Mode
+)
+{
+ CARD32 crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+
+ switch (Mode)
+ {
+ case SCREEN_SAVER_OFF:
+ case SCREEN_SAVER_FORCER:
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl & ~CRTC_DISPLAY_DIS);
+ break;
+
+ case SCREEN_SAVER_ON:
+ case SCREEN_SAVER_CYCLE:
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_DISPLAY_DIS);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * ATIMach64SetDPMSMode --
+ *
+ * This function sets a Mach64's VESA Display Power Management Signaling mode.
+ */
+void
+ATIMach64SetDPMSMode
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ int DPMSMode
+)
+{
+ CARD32 crtc_gen_cntl =
+ inr(CRTC_GEN_CNTL) & ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS);
+
+ switch (DPMSMode)
+ {
+ case DPMSModeOn: /* HSync on, VSync on */
+ break;
+
+ case DPMSModeStandby: /* HSync off, VSync on */
+ crtc_gen_cntl |= CRTC_HSYNC_DIS;
+ break;
+
+ case DPMSModeSuspend: /* HSync on, VSync off */
+ crtc_gen_cntl |= CRTC_VSYNC_DIS;
+ break;
+
+ case DPMSModeOff: /* HSync off, VSync off */
+ crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
+ break;
+
+ default: /* Muffle compiler */
+ return;
+ }
+
+ if (pATI->pXAAInfo && pATI->pXAAInfo->NeedToSync)
+ (*pATI->pXAAInfo->Sync)(pScreenInfo);
+
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl);
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ {
+ CARD32 lcd_index = 0;
+
+ /*
+ * ATI's BIOS simply turns the panel on and off, so do the same by
+ * default, but keep the previous behaviour around for reference.
+ */
+ if (pATI->OptionDevel)
+ {
+ CARD32 power_management;
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ power_management = inr(POWER_MANAGEMENT);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ lcd_index = inr(LCD_INDEX);
+ power_management = ATIGetMach64LCDReg(LCD_POWER_MANAGEMENT);
+ }
+
+ power_management &= ~(STANDBY_NOW | SUSPEND_NOW);
+
+ switch (DPMSMode)
+ {
+ case DPMSModeOn:
+ break;
+
+ case DPMSModeStandby:
+ power_management |= STANDBY_NOW;
+ break;
+
+ case DPMSModeSuspend:
+ power_management |= SUSPEND_NOW;
+ break;
+
+ case DPMSModeOff:
+ power_management |= STANDBY_NOW | SUSPEND_NOW; /* ? */
+ break;
+
+ default: /* Muffle compiler */
+ return;
+ }
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(POWER_MANAGEMENT, power_management);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ ATIPutMach64LCDReg(LCD_POWER_MANAGEMENT, power_management);
+ outr(LCD_INDEX, lcd_index);
+ }
+ }
+ else
+ {
+ CARD32 lcd_gen_ctrl;
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ lcd_index = inr(LCD_INDEX);
+ lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+ }
+
+ if (DPMSMode == DPMSModeOn)
+ lcd_gen_ctrl |= LCD_ON;
+ else
+ lcd_gen_ctrl &= ~LCD_ON;
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+ outr(LCD_INDEX, lcd_index);
+ }
+ }
+ }
+}
+
+/*
+ * ATIMach64ValidateClip --
+ *
+ * This function ensures the current scissor settings do not interfere with
+ * the current draw request.
+ */
+static void
+ATIMach64ValidateClip
+(
+ ATIPtr pATI,
+ int sc_left,
+ int sc_right,
+ int sc_top,
+ int sc_bottom
+)
+{
+ if ((sc_left < (int)pATI->sc_left) || (sc_right > (int)pATI->sc_right))
+ {
+ outf(SC_LEFT_RIGHT, pATI->sc_left_right);
+ pATI->sc_left = pATI->NewHW.sc_left;
+ pATI->sc_right = pATI->NewHW.sc_right;
+ }
+
+ if ((sc_top < (int)pATI->sc_top) || (sc_bottom > (int)pATI->sc_bottom))
+ {
+ outf(SC_TOP_BOTTOM, pATI->sc_top_bottom);
+ pATI->sc_top = pATI->NewHW.sc_top;
+ pATI->sc_bottom = pATI->NewHW.sc_bottom;
+ }
+}
+
+/*
+ * ATIMach64Sync --
+ *
+ * This is called to wait for the draw engine to become idle.
+ */
+static void
+ATIMach64Sync
+(
+ ScrnInfoPtr pScreenInfo
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForIdle(pATI);
+
+ if (pATI->OptionMMIOCache)
+ {
+ /*
+ * For debugging purposes, attempt to verify that each cached register
+ * should actually be cached.
+ */
+ if (RegisterIsCached(SRC_CNTL) &&
+ (CacheSlot(SRC_CNTL) != inm(SRC_CNTL)))
+ {
+ UncacheRegister(SRC_CNTL);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "SRC_CNTL write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(HOST_CNTL) &&
+ (CacheSlot(HOST_CNTL) != inm(HOST_CNTL)))
+ {
+ UncacheRegister(HOST_CNTL);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "HOST_CNTL write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(PAT_REG0) &&
+ (CacheSlot(PAT_REG0) != inm(PAT_REG0)))
+ {
+ UncacheRegister(PAT_REG0);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "PAT_REG0 write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(PAT_REG1) &&
+ (CacheSlot(PAT_REG1) != inm(PAT_REG1)))
+ {
+ UncacheRegister(PAT_REG1);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "PAT_REG1 write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(PAT_CNTL) &&
+ (CacheSlot(PAT_CNTL) != inm(PAT_CNTL)))
+ {
+ UncacheRegister(PAT_CNTL);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "PAT_CNTL write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(SC_LEFT_RIGHT) &&
+ (CacheSlot(SC_LEFT_RIGHT) !=
+ (SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0))))
+ {
+ UncacheRegister(SC_LEFT_RIGHT);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "SC_LEFT_RIGHT write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(SC_TOP_BOTTOM) &&
+ (CacheSlot(SC_TOP_BOTTOM) !=
+ (SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0))))
+ {
+ UncacheRegister(SC_TOP_BOTTOM);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "SC_TOP_BOTTOM write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(DP_BKGD_CLR) &&
+ (CacheSlot(DP_BKGD_CLR) != inm(DP_BKGD_CLR)))
+ {
+ UncacheRegister(DP_BKGD_CLR);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "DP_BKGD_CLR write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(DP_FRGD_CLR) &&
+ (CacheSlot(DP_FRGD_CLR) != inm(DP_FRGD_CLR)))
+ {
+ UncacheRegister(DP_FRGD_CLR);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "DP_FRGD_CLR write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(DP_WRITE_MASK) &&
+ (CacheSlot(DP_WRITE_MASK) != inm(DP_WRITE_MASK)))
+ {
+ UncacheRegister(DP_WRITE_MASK);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "DP_WRITE_MASK write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(DP_MIX) &&
+ (CacheSlot(DP_MIX) != inm(DP_MIX)))
+ {
+ UncacheRegister(DP_MIX);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "DP_MIX write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(CLR_CMP_CLR) &&
+ (CacheSlot(CLR_CMP_CLR) != inm(CLR_CMP_CLR)))
+ {
+ UncacheRegister(CLR_CMP_CLR);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "CLR_CMP_CLR write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(CLR_CMP_MSK) &&
+ (CacheSlot(CLR_CMP_MSK) != inm(CLR_CMP_MSK)))
+ {
+ UncacheRegister(CLR_CMP_MSK);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "CLR_CMP_MSK write cache disabled!\n");
+ }
+
+ if (RegisterIsCached(CLR_CMP_CNTL) &&
+ (CacheSlot(CLR_CMP_CNTL) != inm(CLR_CMP_CNTL)))
+ {
+ UncacheRegister(CLR_CMP_CNTL);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "CLR_CMP_CNTL write cache disabled!\n");
+ }
+ }
+
+ /*
+ * For VTB's and later, the first CPU read of the framebuffer will return
+ * zeroes, so do it here. This appears to be due to some kind of engine
+ * caching of framebuffer data I haven't found any way of disabling, or
+ * otherwise circumventing. Thanks to Mark Vojkovich for the suggestion.
+ */
+ pATI->pXAAInfo->NeedToSync = FALSE;
+ pATI = *(volatile ATIPtr *)pATI->pMemory;
+}
+
+/*
+ * ATIMach64SetupForScreenToScreenCopy --
+ *
+ * This function sets up the draw engine for a series of screen-to-screen copy
+ * operations.
+ */
+static void
+ATIMach64SetupForScreenToScreenCopy
+(
+ ScrnInfoPtr pScreenInfo,
+ int xdir,
+ int ydir,
+ int rop,
+ unsigned int planemask,
+ int TransparencyColour
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(DP_WRITE_MASK, planemask);
+ outf(DP_SRC, DP_MONO_SRC_ALLONES |
+ SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
+
+#ifdef AVOID_DGA
+
+ if (TransparencyColour == -1)
+
+#else /* AVOID_DGA */
+
+ if (!pATI->XAAForceTransBlit && (TransparencyColour == -1))
+
+#endif /* AVOID_DGA */
+
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
+ else
+ {
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(CLR_CMP_CLR, TransparencyColour);
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D);
+ }
+
+ pATI->dst_cntl = 0;
+
+ if (ydir > 0)
+ pATI->dst_cntl |= DST_Y_DIR;
+ if (xdir > 0)
+ pATI->dst_cntl |= DST_X_DIR;
+
+ if (pATI->XModifier == 1)
+ outf(DST_CNTL, pATI->dst_cntl);
+ else
+ pATI->dst_cntl |= DST_24_ROT_EN;
+}
+
+/*
+ * ATIMach64SubsequentScreenToScreenCopy --
+ *
+ * This function performs a screen-to-screen copy operation.
+ */
+static void
+ATIMach64SubsequentScreenToScreenCopy
+(
+ ScrnInfoPtr pScreenInfo,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ int w,
+ int h
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ xSrc *= pATI->XModifier;
+ xDst *= pATI->XModifier;
+ w *= pATI->XModifier;
+
+ /* Disable clipping if it gets in the way */
+ ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1);
+
+ if (!(pATI->dst_cntl & DST_X_DIR))
+ {
+ xSrc += w - 1;
+ xDst += w - 1;
+ }
+
+ if (!(pATI->dst_cntl & DST_Y_DIR))
+ {
+ ySrc += h - 1;
+ yDst += h - 1;
+ }
+
+ if (pATI->XModifier != 1)
+ outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT));
+
+ ATIMach64WaitForFIFO(pATI, 4);
+ outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0));
+ outf(SRC_WIDTH1, w);
+ outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0));
+ outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
+}
+
+/*
+ * ATIMach64SetupForSolidFill --
+ *
+ * This function sets up the draw engine for a series of solid fills.
+ */
+static void
+ATIMach64SetupForSolidFill
+(
+ ScrnInfoPtr pScreenInfo,
+ int colour,
+ int rop,
+ unsigned int planemask
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 5);
+ outf(DP_WRITE_MASK, planemask);
+ outf(DP_SRC, DP_MONO_SRC_ALLONES |
+ SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
+ outf(DP_FRGD_CLR, colour);
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
+
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
+
+ if (pATI->XModifier == 1)
+ outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
+}
+
+/*
+ * ATIMach64SubsequentSolidFillRect --
+ *
+ * This function performs a solid rectangle fill.
+ */
+static void
+ATIMach64SubsequentSolidFillRect
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int w,
+ int h
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->XModifier != 1)
+ {
+ x *= pATI->XModifier;
+ w *= pATI->XModifier;
+
+ outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
+ (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
+ }
+
+ /* Disable clipping if it gets in the way */
+ ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
+
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
+ outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
+}
+
+/*
+ * ATIMach64SetupForSolidLine --
+ *
+ * This function sets up the draw engine for a series of solid lines. It is
+ * not used for 24bpp because the engine doesn't support it.
+ */
+static void
+ATIMach64SetupForSolidLine
+(
+ ScrnInfoPtr pScreenInfo,
+ int colour,
+ int rop,
+ unsigned int planemask
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 5);
+ outf(DP_WRITE_MASK, planemask);
+ outf(DP_SRC, DP_MONO_SRC_ALLONES |
+ SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
+ outf(DP_FRGD_CLR, colour);
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
+
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
+
+ ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right,
+ pATI->NewHW.sc_top, pATI->NewHW.sc_bottom);
+}
+
+/*
+ * ATIMach64SubsequentSolidHorVertLine --
+ *
+ * This is called to draw a solid horizontal or vertical line. This does a
+ * one-pixel wide solid fill.
+ */
+static void
+ATIMach64SubsequentSolidHorVertLine
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int len,
+ int dir
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
+ outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
+
+ if (dir == DEGREES_0)
+ outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0));
+ else /* if (dir == DEGREES_270) */
+ outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0));
+}
+
+/*
+ * ATIMach64SubsequentSolidBresenhamLine --
+ *
+ * This function draws a line using the Bresenham line engine.
+ */
+static void
+ATIMach64SubsequentSolidBresenhamLine
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int major,
+ int minor,
+ int err,
+ int len,
+ int octant
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ CARD32 dst_cntl = DST_LAST_PEL;
+
+ if (octant & YMAJOR)
+ dst_cntl |= DST_Y_MAJOR;
+
+ if (!(octant & XDECREASING))
+ dst_cntl |= DST_X_DIR;
+
+ if (!(octant & YDECREASING))
+ dst_cntl |= DST_Y_DIR;
+
+ ATIMach64WaitForFIFO(pATI, 6);
+ outf(DST_CNTL, dst_cntl);
+ outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
+ outf(DST_BRES_ERR, minor + err);
+ outf(DST_BRES_INC, minor);
+ outf(DST_BRES_DEC, minor - major);
+ outf(DST_BRES_LNTH, len);
+}
+
+/*
+ * ATIMach64SetupForMono8x8PatternFill --
+ *
+ * This function sets up the draw engine for a series of 8x8 1bpp pattern
+ * fills.
+ */
+static void
+ATIMach64SetupForMono8x8PatternFill
+(
+ ScrnInfoPtr pScreenInfo,
+ int patx,
+ int paty,
+ int fg,
+ int bg,
+ int rop,
+ unsigned int planemask
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(DP_WRITE_MASK, planemask);
+ outf(DP_SRC, DP_MONO_SRC_PATTERN |
+ SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
+ outf(DP_FRGD_CLR, fg);
+
+ if (bg == -1)
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
+ SetBits(MIX_DST, DP_BKGD_MIX));
+ else
+ {
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(DP_BKGD_CLR, bg);
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
+ SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
+ }
+
+ ATIMach64WaitForFIFO(pATI, 4);
+ outf(PAT_REG0, patx);
+ outf(PAT_REG1, paty);
+ outf(PAT_CNTL, PAT_MONO_EN);
+
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
+
+ if (pATI->XModifier == 1)
+ outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
+}
+
+/*
+ * ATIMach64SubsequentMono8x8PatternFillRect --
+ *
+ * This function performs an 8x8 1bpp pattern fill.
+ */
+static void
+ATIMach64SubsequentMono8x8PatternFillRect
+(
+ ScrnInfoPtr pScreenInfo,
+ int patx,
+ int paty,
+ int x,
+ int y,
+ int w,
+ int h
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->XModifier != 1)
+ {
+ x *= pATI->XModifier;
+ w *= pATI->XModifier;
+
+ outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
+ (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
+ }
+
+ /* Disable clipping if it gets in the way */
+ ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
+
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
+ outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
+}
+
+/*
+ * ATIMach64SetupForScanlineCPUToScreenColorExpandFill --
+ *
+ * This function sets up the engine for a series of colour expansion fills.
+ */
+static void
+ATIMach64SetupForScanlineCPUToScreenColorExpandFill
+(
+ ScrnInfoPtr pScreenInfo,
+ int fg,
+ int bg,
+ int rop,
+ unsigned int planemask
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ ATIMach64WaitForFIFO(pATI, 3);
+ outf(DP_WRITE_MASK, planemask);
+ outf(DP_SRC, DP_MONO_SRC_HOST |
+ SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
+ outf(DP_FRGD_CLR, fg);
+
+ if (bg == -1)
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
+ SetBits(MIX_DST, DP_BKGD_MIX));
+ else
+ {
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(DP_BKGD_CLR, bg);
+ outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
+ SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
+ }
+
+ outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
+
+ if (pATI->XModifier == 1)
+ outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
+}
+
+/*
+ * ATIMach64SubsequentScanlineCPUToScreenColorExpandFill --
+ *
+ * This function sets up the engine for a single colour expansion fill.
+ */
+static void
+ATIMach64SubsequentScanlineCPUToScreenColorExpandFill
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y,
+ int w,
+ int h,
+ int skipleft
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->XModifier != 1)
+ {
+ x *= pATI->XModifier;
+ w *= pATI->XModifier;
+ skipleft *= pATI->XModifier;
+
+ outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
+ (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
+ }
+
+ pATI->ExpansionBitmapWidth = (w + 31) / 32;
+
+ ATIMach64WaitForFIFO(pATI, 3);
+ pATI->sc_left = x + skipleft;
+ pATI->sc_right = x + w - 1;
+ outf(SC_LEFT_RIGHT,
+ SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0));
+ outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
+ outf(DST_HEIGHT_WIDTH,
+ SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0));
+}
+
+/*
+ * ATIMach64SubsequentColorExpandScanline --
+ *
+ * This function feeds a bitmap scanline to the engine for a colour expansion
+ * fill. This is written to do burst transfers for those platforms that can do
+ * them, and to improve CPU/engine concurrency.
+ */
+static void
+ATIMach64SubsequentColorExpandScanline
+(
+ ScrnInfoPtr pScreenInfo,
+ int iBuffer
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ CARD32 *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer];
+ int w = pATI->ExpansionBitmapWidth;
+ int nDWord;
+
+ while (w > 0)
+ {
+ /*
+ * Transfers are done in chunks of up to 64 bytes in length (32 on
+ * earlier controllers).
+ */
+ nDWord = w;
+ if (nDWord > pATI->nHostFIFOEntries)
+ nDWord = pATI->nHostFIFOEntries;
+
+ /* Make enough FIFO slots available */
+ ATIMach64WaitForFIFO(pATI, nDWord);
+
+ /*
+ * Always start transfers on a chuck-sized boundary. Note that
+ * HOST_DATA_0 is actually on a 512-byte boundary, but *pBitmapData can
+ * only be guaranteed to be on a chunk-sized boundary.
+ *
+ * Transfer current chunk. With any luck, the compiler won't mangle
+ * this too badly...
+ */
+
+# if defined(ATIMove32)
+
+ ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord);
+
+# else
+
+ {
+ volatile CARD32 *pDst;
+ CARD32 *pSrc;
+ unsigned int iDWord;
+
+ iDWord = 16 - nDWord;
+ pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord;
+ pSrc = pBitmapData - iDWord;
+
+ switch (iDWord)
+ {
+ case 0: MMIO_MOVE32(pDst + 0, 0, *(pSrc + 0));
+ case 1: MMIO_MOVE32(pDst + 1, 0, *(pSrc + 1));
+ case 2: MMIO_MOVE32(pDst + 2, 0, *(pSrc + 2));
+ case 3: MMIO_MOVE32(pDst + 3, 0, *(pSrc + 3));
+ case 4: MMIO_MOVE32(pDst + 4, 0, *(pSrc + 4));
+ case 5: MMIO_MOVE32(pDst + 5, 0, *(pSrc + 5));
+ case 6: MMIO_MOVE32(pDst + 6, 0, *(pSrc + 6));
+ case 7: MMIO_MOVE32(pDst + 7, 0, *(pSrc + 7));
+ case 8: MMIO_MOVE32(pDst + 8, 0, *(pSrc + 8));
+ case 9: MMIO_MOVE32(pDst + 9, 0, *(pSrc + 9));
+ case 10: MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10));
+ case 11: MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11));
+ case 12: MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12));
+ case 13: MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13));
+ case 14: MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14));
+ case 15: MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15));
+
+ default: /* Muffle compiler */
+ break;
+ }
+ }
+
+# endif
+
+ /* Step to next chunk */
+ pBitmapData += nDWord;
+ w -= nDWord;
+ pATI->nAvailableFIFOEntries -= nDWord;
+ }
+
+ pATI->EngineIsBusy = TRUE;
+}
+
+/*
+ * ATIMach64AccelInit --
+ *
+ * This function fills in structure fields needed for acceleration on Mach64
+ * variants.
+ */
+int
+ATIMach64AccelInit
+(
+ ATIPtr pATI,
+ XAAInfoRecPtr pXAAInfo
+)
+{
+ /* This doesn't seem quite right... */
+ if (pATI->XModifier == 1)
+ {
+ pXAAInfo->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
+
+#ifndef AVOID_CPIO
+
+ if (!pATI->BankInfo.BankSize)
+
+#endif /* AVOID_CPIO */
+
+ {
+ pXAAInfo->Flags |= LINEAR_FRAMEBUFFER;
+ }
+ }
+
+ /* Sync */
+ pXAAInfo->Sync = ATIMach64Sync;
+
+ /* Screen-to-screen copy */
+ pXAAInfo->SetupForScreenToScreenCopy = ATIMach64SetupForScreenToScreenCopy;
+ pXAAInfo->SubsequentScreenToScreenCopy =
+ ATIMach64SubsequentScreenToScreenCopy;
+
+ /* Solid fills */
+ pXAAInfo->SetupForSolidFill = ATIMach64SetupForSolidFill;
+ pXAAInfo->SubsequentSolidFillRect = ATIMach64SubsequentSolidFillRect;
+
+ /* 8x8 mono pattern fills */
+ pXAAInfo->Mono8x8PatternFillFlags =
+
+#if X_BYTE_ORDER != X_LITTLE_ENDIAN
+
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+
+#endif /* X_BYTE_ORDER */
+
+ HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN;
+ pXAAInfo->SetupForMono8x8PatternFill = ATIMach64SetupForMono8x8PatternFill;
+ pXAAInfo->SubsequentMono8x8PatternFillRect =
+ ATIMach64SubsequentMono8x8PatternFillRect;
+
+ /*
+ * Use scanline version of colour expansion, not only for the non-ix86
+ * case, but also to avoid PCI retries.
+ */
+ pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
+ LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
+ if (pATI->XModifier != 1)
+ pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP;
+ pXAAInfo->NumScanlineColorExpandBuffers = 1;
+
+ /* Align bitmap data on a 64-byte boundary */
+ pATI->ExpansionBitmapWidth = /* DWord size in bits */
+ ((pATI->displayWidth * pATI->XModifier) + 31) & ~31U;
+ pATI->ExpansionBitmapScanlinePtr[1] =
+ (CARD32 *)xnfalloc((pATI->ExpansionBitmapWidth >> 3) + 63);
+ pATI->ExpansionBitmapScanlinePtr[0] =
+ (pointer)(((unsigned long)pATI->ExpansionBitmapScanlinePtr[1] + 63) &
+ ~63UL);
+ pXAAInfo->ScanlineColorExpandBuffers =
+ (CARD8 **)pATI->ExpansionBitmapScanlinePtr;
+ pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
+ ATIMach64SetupForScanlineCPUToScreenColorExpandFill;
+ pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
+ ATIMach64SubsequentScanlineCPUToScreenColorExpandFill;
+ pXAAInfo->SubsequentColorExpandScanline =
+ ATIMach64SubsequentColorExpandScanline;
+
+ /* The engine does not support the following primitives for 24bpp */
+ if (pATI->XModifier != 1)
+ return ATIMach64MaxY;
+
+ /* Solid lines */
+ pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine;
+ pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine;
+ pXAAInfo->SubsequentSolidBresenhamLine =
+ ATIMach64SubsequentSolidBresenhamLine;
+
+ return ATIMach64MaxY;
+}
+
+/*
+ * ATIMach64SetCursorColours --
+ *
+ * Set hardware cursor foreground and background colours.
+ */
+static void
+ATIMach64SetCursorColours
+(
+ ScrnInfoPtr pScreenInfo,
+ int fg,
+ int bg
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ outr(CUR_CLR0, SetBits(fg, CUR_CLR));
+ outr(CUR_CLR1, SetBits(bg, CUR_CLR));
+}
+
+/*
+ * ATIMach64SetCursorPosition --
+ *
+ * Set position of hardware cursor.
+ */
+static void
+ATIMach64SetCursorPosition
+(
+ ScrnInfoPtr pScreenInfo,
+ int x,
+ int y
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ CARD16 CursorXOffset, CursorYOffset;
+
+ /* Adjust x & y when the cursor is partially obscured */
+ if (x < 0)
+ {
+ if ((CursorXOffset = -x) > 63)
+ CursorXOffset = 63;
+ x = 0;
+ }
+ else
+ {
+ CursorXOffset = pScreenInfo->frameX1 - pScreenInfo->frameX0;
+ if (x > CursorXOffset)
+ x = CursorXOffset;
+ CursorXOffset = 0;
+ }
+
+ if (y < 0)
+ {
+ if ((CursorYOffset = -y) > 63)
+ CursorYOffset = 63;
+ y = 0;
+ }
+ else
+ {
+ CursorYOffset = pScreenInfo->frameY1 - pScreenInfo->frameY0;
+ if (y > CursorYOffset)
+ y = CursorYOffset;
+ CursorYOffset = 0;
+ }
+
+ /* Adjust for multiscanned modes */
+ if (pScreenInfo->currentMode->Flags & V_DBLSCAN)
+ y *= 2;
+ if (pScreenInfo->currentMode->VScan > 1)
+ y *= pScreenInfo->currentMode->VScan;
+
+ do
+ {
+ if (CursorYOffset != pATI->CursorYOffset)
+ {
+ pATI->CursorYOffset = CursorYOffset;
+ outr(CUR_OFFSET, ((CursorYOffset << 4) + pATI->CursorOffset) >> 3);
+ }
+ else if (CursorXOffset == pATI->CursorXOffset)
+ break;
+
+ pATI->CursorXOffset = CursorXOffset;
+ outr(CUR_HORZ_VERT_OFF, SetBits(CursorXOffset, CUR_HORZ_OFF) |
+ SetBits(CursorYOffset, CUR_VERT_OFF));
+ } while (0);
+
+ outr(CUR_HORZ_VERT_POSN,
+ SetBits(x, CUR_HORZ_POSN) | SetBits(y, CUR_VERT_POSN));
+}
+
+/*
+ * ATIMach64LoadCursorImage --
+ *
+ * Copy hardware cursor image into offscreen video memory.
+ */
+static void
+ATIMach64LoadCursorImage
+(
+ ScrnInfoPtr pScreenInfo,
+ CARD8 *pImage
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+ CARD32 *pSrc = (pointer)pImage;
+ volatile CARD32 *pDst = pATI->pCursorImage;
+
+ /* Synchronise video memory accesses */
+ if (pXAAInfo && pXAAInfo->NeedToSync)
+ (*pXAAInfo->Sync)(pScreenInfo);
+
+# if defined(ATIMove32)
+
+ ATIMove32(pDst, pSrc, 256);
+
+# else
+
+ /* This is lengthy, but it does maximise burst modes */
+ pDst[ 0] = pSrc[ 0]; pDst[ 1] = pSrc[ 1];
+ pDst[ 2] = pSrc[ 2]; pDst[ 3] = pSrc[ 3];
+ pDst[ 4] = pSrc[ 4]; pDst[ 5] = pSrc[ 5];
+ pDst[ 6] = pSrc[ 6]; pDst[ 7] = pSrc[ 7];
+ pDst[ 8] = pSrc[ 8]; pDst[ 9] = pSrc[ 9];
+ pDst[ 10] = pSrc[ 10]; pDst[ 11] = pSrc[ 11];
+ pDst[ 12] = pSrc[ 12]; pDst[ 13] = pSrc[ 13];
+ pDst[ 14] = pSrc[ 14]; pDst[ 15] = pSrc[ 15];
+ pDst[ 16] = pSrc[ 16]; pDst[ 17] = pSrc[ 17];
+ pDst[ 18] = pSrc[ 18]; pDst[ 19] = pSrc[ 19];
+ pDst[ 20] = pSrc[ 20]; pDst[ 21] = pSrc[ 21];
+ pDst[ 22] = pSrc[ 22]; pDst[ 23] = pSrc[ 23];
+ pDst[ 24] = pSrc[ 24]; pDst[ 25] = pSrc[ 25];
+ pDst[ 26] = pSrc[ 26]; pDst[ 27] = pSrc[ 27];
+ pDst[ 28] = pSrc[ 28]; pDst[ 29] = pSrc[ 29];
+ pDst[ 30] = pSrc[ 30]; pDst[ 31] = pSrc[ 31];
+ pDst[ 32] = pSrc[ 32]; pDst[ 33] = pSrc[ 33];
+ pDst[ 34] = pSrc[ 34]; pDst[ 35] = pSrc[ 35];
+ pDst[ 36] = pSrc[ 36]; pDst[ 37] = pSrc[ 37];
+ pDst[ 38] = pSrc[ 38]; pDst[ 39] = pSrc[ 39];
+ pDst[ 40] = pSrc[ 40]; pDst[ 41] = pSrc[ 41];
+ pDst[ 42] = pSrc[ 42]; pDst[ 43] = pSrc[ 43];
+ pDst[ 44] = pSrc[ 44]; pDst[ 45] = pSrc[ 45];
+ pDst[ 46] = pSrc[ 46]; pDst[ 47] = pSrc[ 47];
+ pDst[ 48] = pSrc[ 48]; pDst[ 49] = pSrc[ 49];
+ pDst[ 50] = pSrc[ 50]; pDst[ 51] = pSrc[ 51];
+ pDst[ 52] = pSrc[ 52]; pDst[ 53] = pSrc[ 53];
+ pDst[ 54] = pSrc[ 54]; pDst[ 55] = pSrc[ 55];
+ pDst[ 56] = pSrc[ 56]; pDst[ 57] = pSrc[ 57];
+ pDst[ 58] = pSrc[ 58]; pDst[ 59] = pSrc[ 59];
+ pDst[ 60] = pSrc[ 60]; pDst[ 61] = pSrc[ 61];
+ pDst[ 62] = pSrc[ 62]; pDst[ 63] = pSrc[ 63];
+ pDst[ 64] = pSrc[ 64]; pDst[ 65] = pSrc[ 65];
+ pDst[ 66] = pSrc[ 66]; pDst[ 67] = pSrc[ 67];
+ pDst[ 68] = pSrc[ 68]; pDst[ 69] = pSrc[ 69];
+ pDst[ 70] = pSrc[ 70]; pDst[ 71] = pSrc[ 71];
+ pDst[ 72] = pSrc[ 72]; pDst[ 73] = pSrc[ 73];
+ pDst[ 74] = pSrc[ 74]; pDst[ 75] = pSrc[ 75];
+ pDst[ 76] = pSrc[ 76]; pDst[ 77] = pSrc[ 77];
+ pDst[ 78] = pSrc[ 78]; pDst[ 79] = pSrc[ 79];
+ pDst[ 80] = pSrc[ 80]; pDst[ 81] = pSrc[ 81];
+ pDst[ 82] = pSrc[ 82]; pDst[ 83] = pSrc[ 83];
+ pDst[ 84] = pSrc[ 84]; pDst[ 85] = pSrc[ 85];
+ pDst[ 86] = pSrc[ 86]; pDst[ 87] = pSrc[ 87];
+ pDst[ 88] = pSrc[ 88]; pDst[ 89] = pSrc[ 89];
+ pDst[ 90] = pSrc[ 90]; pDst[ 91] = pSrc[ 91];
+ pDst[ 92] = pSrc[ 92]; pDst[ 93] = pSrc[ 93];
+ pDst[ 94] = pSrc[ 94]; pDst[ 95] = pSrc[ 95];
+ pDst[ 96] = pSrc[ 96]; pDst[ 97] = pSrc[ 97];
+ pDst[ 98] = pSrc[ 98]; pDst[ 99] = pSrc[ 99];
+ pDst[100] = pSrc[100]; pDst[101] = pSrc[101];
+ pDst[102] = pSrc[102]; pDst[103] = pSrc[103];
+ pDst[104] = pSrc[104]; pDst[105] = pSrc[105];
+ pDst[106] = pSrc[106]; pDst[107] = pSrc[107];
+ pDst[108] = pSrc[108]; pDst[109] = pSrc[109];
+ pDst[110] = pSrc[110]; pDst[111] = pSrc[111];
+ pDst[112] = pSrc[112]; pDst[113] = pSrc[113];
+ pDst[114] = pSrc[114]; pDst[115] = pSrc[115];
+ pDst[116] = pSrc[116]; pDst[117] = pSrc[117];
+ pDst[118] = pSrc[118]; pDst[119] = pSrc[119];
+ pDst[120] = pSrc[120]; pDst[121] = pSrc[121];
+ pDst[122] = pSrc[122]; pDst[123] = pSrc[123];
+ pDst[124] = pSrc[124]; pDst[125] = pSrc[125];
+ pDst[126] = pSrc[126]; pDst[127] = pSrc[127];
+ pDst[128] = pSrc[128]; pDst[129] = pSrc[129];
+ pDst[130] = pSrc[130]; pDst[131] = pSrc[131];
+ pDst[132] = pSrc[132]; pDst[133] = pSrc[133];
+ pDst[134] = pSrc[134]; pDst[135] = pSrc[135];
+ pDst[136] = pSrc[136]; pDst[137] = pSrc[137];
+ pDst[138] = pSrc[138]; pDst[139] = pSrc[139];
+ pDst[140] = pSrc[140]; pDst[141] = pSrc[141];
+ pDst[142] = pSrc[142]; pDst[143] = pSrc[143];
+ pDst[144] = pSrc[144]; pDst[145] = pSrc[145];
+ pDst[146] = pSrc[146]; pDst[147] = pSrc[147];
+ pDst[148] = pSrc[148]; pDst[149] = pSrc[149];
+ pDst[150] = pSrc[150]; pDst[151] = pSrc[151];
+ pDst[152] = pSrc[152]; pDst[153] = pSrc[153];
+ pDst[154] = pSrc[154]; pDst[155] = pSrc[155];
+ pDst[156] = pSrc[156]; pDst[157] = pSrc[157];
+ pDst[158] = pSrc[158]; pDst[159] = pSrc[159];
+ pDst[160] = pSrc[160]; pDst[161] = pSrc[161];
+ pDst[162] = pSrc[162]; pDst[163] = pSrc[163];
+ pDst[164] = pSrc[164]; pDst[165] = pSrc[165];
+ pDst[166] = pSrc[166]; pDst[167] = pSrc[167];
+ pDst[168] = pSrc[168]; pDst[169] = pSrc[169];
+ pDst[170] = pSrc[170]; pDst[171] = pSrc[171];
+ pDst[172] = pSrc[172]; pDst[173] = pSrc[173];
+ pDst[174] = pSrc[174]; pDst[175] = pSrc[175];
+ pDst[176] = pSrc[176]; pDst[177] = pSrc[177];
+ pDst[178] = pSrc[178]; pDst[179] = pSrc[179];
+ pDst[180] = pSrc[180]; pDst[181] = pSrc[181];
+ pDst[182] = pSrc[182]; pDst[183] = pSrc[183];
+ pDst[184] = pSrc[184]; pDst[185] = pSrc[185];
+ pDst[186] = pSrc[186]; pDst[187] = pSrc[187];
+ pDst[188] = pSrc[188]; pDst[189] = pSrc[189];
+ pDst[190] = pSrc[190]; pDst[191] = pSrc[191];
+ pDst[192] = pSrc[192]; pDst[193] = pSrc[193];
+ pDst[194] = pSrc[194]; pDst[195] = pSrc[195];
+ pDst[196] = pSrc[196]; pDst[197] = pSrc[197];
+ pDst[198] = pSrc[198]; pDst[199] = pSrc[199];
+ pDst[200] = pSrc[200]; pDst[201] = pSrc[201];
+ pDst[202] = pSrc[202]; pDst[203] = pSrc[203];
+ pDst[204] = pSrc[204]; pDst[205] = pSrc[205];
+ pDst[206] = pSrc[206]; pDst[207] = pSrc[207];
+ pDst[208] = pSrc[208]; pDst[209] = pSrc[209];
+ pDst[210] = pSrc[210]; pDst[211] = pSrc[211];
+ pDst[212] = pSrc[212]; pDst[213] = pSrc[213];
+ pDst[214] = pSrc[214]; pDst[215] = pSrc[215];
+ pDst[216] = pSrc[216]; pDst[217] = pSrc[217];
+ pDst[218] = pSrc[218]; pDst[219] = pSrc[219];
+ pDst[220] = pSrc[220]; pDst[221] = pSrc[221];
+ pDst[222] = pSrc[222]; pDst[223] = pSrc[223];
+ pDst[224] = pSrc[224]; pDst[225] = pSrc[225];
+ pDst[226] = pSrc[226]; pDst[227] = pSrc[227];
+ pDst[228] = pSrc[228]; pDst[229] = pSrc[229];
+ pDst[230] = pSrc[230]; pDst[231] = pSrc[231];
+ pDst[232] = pSrc[232]; pDst[233] = pSrc[233];
+ pDst[234] = pSrc[234]; pDst[235] = pSrc[235];
+ pDst[236] = pSrc[236]; pDst[237] = pSrc[237];
+ pDst[238] = pSrc[238]; pDst[239] = pSrc[239];
+ pDst[240] = pSrc[240]; pDst[241] = pSrc[241];
+ pDst[242] = pSrc[242]; pDst[243] = pSrc[243];
+ pDst[244] = pSrc[244]; pDst[245] = pSrc[245];
+ pDst[246] = pSrc[246]; pDst[247] = pSrc[247];
+ pDst[248] = pSrc[248]; pDst[249] = pSrc[249];
+ pDst[250] = pSrc[250]; pDst[251] = pSrc[251];
+ pDst[252] = pSrc[252]; pDst[253] = pSrc[253];
+ pDst[254] = pSrc[254]; pDst[255] = pSrc[255];
+
+#endif
+
+}
+
+/*
+ * ATIMach64HideCursor --
+ *
+ * Turn off hardware cursor.
+ */
+static void
+ATIMach64HideCursor
+(
+ ScrnInfoPtr pScreenInfo
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (!(pATI->NewHW.gen_test_cntl & GEN_CUR_EN))
+ return;
+
+ pATI->NewHW.gen_test_cntl &= ~GEN_CUR_EN;
+ out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0));
+}
+
+/*
+ * ATIMach64ShowCursor --
+ *
+ * Turn on hardware cursor.
+ */
+static void
+ATIMach64ShowCursor
+(
+ ScrnInfoPtr pScreenInfo
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->NewHW.gen_test_cntl & GEN_CUR_EN)
+ return;
+
+ pATI->NewHW.gen_test_cntl |= GEN_CUR_EN;
+ out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0));
+}
+
+/*
+ * ATIMach64UseHWCursor --
+ *
+ * Notify cursor layer whether a hardware cursor is configured.
+ */
+static Bool
+ATIMach64UseHWCursor
+(
+ ScreenPtr pScreen,
+ CursorPtr pCursor
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (!pATI->CursorBase)
+ return FALSE;
+
+#ifndef AVOID_CPIO
+
+ /*
+ * For some reason, the hardware cursor isn't vertically scaled when a VGA
+ * doublescanned or multiscanned mode is in effect.
+ */
+ if (pATI->NewHW.crtc == ATI_CRTC_MACH64)
+ return TRUE;
+ if ((pScreenInfo->currentMode->Flags & V_DBLSCAN) ||
+ (pScreenInfo->currentMode->VScan > 1))
+ return FALSE;
+
+#endif /* AVOID_CPIO */
+
+ return TRUE;
+}
+
+/*
+ * ATIMach64CursorInit --
+ *
+ * Initialise xf86CursorInfoRec fields with information specific to Mach64
+ * variants.
+ */
+Bool
+ATIMach64CursorInit
+(
+ xf86CursorInfoPtr pCursorInfo
+)
+{
+ /*
+ * For Mach64 variants, toggling hardware cursors on and off causes
+ * display artifacts. Ask the cursor support layers to always paint the
+ * cursor (whether or not it is entirely transparent) and to not hide the
+ * cursor when reloading its image. The three reasons behind turning off
+ * the hardware cursor that remain are when it moves to a different screen,
+ * on a switch to a software cursor or to a different virtual console.
+ */
+ pCursorInfo->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_INVERT_MASK |
+ HARDWARE_CURSOR_SHOW_TRANSPARENT |
+ HARDWARE_CURSOR_UPDATE_UNHIDDEN |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+
+#if X_BYTE_ORDER != X_LITTLE_ENDIAN
+
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+
+#endif /* X_BYTE_ORDER */
+
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
+ pCursorInfo->MaxWidth = pCursorInfo->MaxHeight = 64;
+
+ pCursorInfo->SetCursorColors = ATIMach64SetCursorColours;
+ pCursorInfo->SetCursorPosition = ATIMach64SetCursorPosition;
+ pCursorInfo->LoadCursorImage = ATIMach64LoadCursorImage;
+ pCursorInfo->HideCursor = ATIMach64HideCursor;
+ pCursorInfo->ShowCursor = ATIMach64ShowCursor;
+ pCursorInfo->UseHWCursor = ATIMach64UseHWCursor;
+
+ return TRUE;
+}
diff --git a/src/atimach64.h b/src/atimach64.h
new file mode 100644
index 0000000..e6e1eaa
--- /dev/null
+++ b/src/atimach64.h
@@ -0,0 +1,50 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.h,v 1.16 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIMACH64_H___
+#define ___ATIMACH64_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+#define ATIMach64MaxX 8191
+#define ATIMach64MaxY 32767
+
+extern void ATIMach64PreInit FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+extern void ATIMach64Save FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIMach64Calculate FunctionPrototype((ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIMach64Set FunctionPrototype((ATIPtr, ATIHWPtr));
+
+extern void ATIMach64SaveScreen FunctionPrototype((ATIPtr, int));
+extern void ATIMach64SetDPMSMode FunctionPrototype((ScrnInfoPtr, ATIPtr, int));
+
+extern int ATIMach64AccelInit FunctionPrototype((ATIPtr, XAAInfoRecPtr));
+
+extern Bool ATIMach64CursorInit FunctionPrototype((xf86CursorInfoPtr));
+
+#endif /* ___ATIMACH64_H___ */
diff --git a/src/atimach64io.c b/src/atimach64io.c
new file mode 100644
index 0000000..3197f3c
--- /dev/null
+++ b/src/atimach64io.c
@@ -0,0 +1,100 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.c,v 1.5 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atichip.h"
+#include "atimach64io.h"
+
+/*
+ * ATIAccessMach64PLLReg --
+ *
+ * This function sets up the addressing required to access, for read or write,
+ * a 264xT's PLL registers.
+ */
+void
+ATIAccessMach64PLLReg
+(
+ ATIPtr pATI,
+ const CARD8 Index,
+ const Bool Write
+)
+{
+ CARD8 clock_cntl1 = in8(CLOCK_CNTL + 1) &
+ ~GetByte(PLL_WR_EN | PLL_ADDR, 1);
+
+ /* Set PLL register to be read or written */
+ out8(CLOCK_CNTL + 1, clock_cntl1 |
+ GetByte(SetBits(Index, PLL_ADDR) | SetBits(Write, PLL_WR_EN), 1));
+}
+
+/*
+ * ATIMach64PollEngineStatus --
+ *
+ * This function refreshes the driver's view of the draw engine's status. This
+ * has been moved into a separate compilation unit to prevent inlining.
+ */
+void
+ATIMach64PollEngineStatus
+(
+ ATIPtr pATI
+)
+{
+ CARD32 IOValue;
+ int Count;
+
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ {
+ /*
+ * TODO: Deal with locked engines.
+ */
+ IOValue = inm(FIFO_STAT);
+ pATI->EngineIsLocked = GetBits(IOValue, FIFO_ERR);
+
+ /*
+ * The following counts the number of bits in FIFO_STAT_BITS, and is
+ * derived from miSetVisualTypes() (formerly cfbSetVisualTypes()).
+ */
+ IOValue = GetBits(IOValue, FIFO_STAT_BITS);
+ Count = (IOValue >> 1) & 0x36DBU;
+ Count = IOValue - Count - ((Count >> 1) & 0x36DBU);
+ Count = ((Count + (Count >> 3)) & 0x71C7U) % 0x3FU;
+ Count = pATI->nFIFOEntries - Count;
+ if (Count > pATI->nAvailableFIFOEntries)
+ pATI->nAvailableFIFOEntries = Count;
+
+ /*
+ * If the command FIFO is non-empty, then the engine isn't idle.
+ */
+ if (pATI->nAvailableFIFOEntries < pATI->nFIFOEntries)
+ {
+ pATI->EngineIsBusy = TRUE;
+ return;
+ }
+ }
+
+ IOValue = inm(GUI_STAT);
+ pATI->EngineIsBusy = GetBits(IOValue, GUI_ACTIVE);
+ Count = GetBits(IOValue, GUI_FIFO);
+ if (Count > pATI->nAvailableFIFOEntries)
+ pATI->nAvailableFIFOEntries = Count;
+}
diff --git a/src/atimach64io.h b/src/atimach64io.h
new file mode 100644
index 0000000..b91a882
--- /dev/null
+++ b/src/atimach64io.h
@@ -0,0 +1,269 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.h,v 1.14 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIMACH64IO_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error Missing #include "ati.h" before #include "atimach64io.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIMACH64IO_H___ 1
+
+#include "atiio.h"
+#include "atistruct.h"
+
+/*
+ * A few important notes on some of the I/O statements provided:
+ *
+ * inl/outl 32-bit R/W through PIO space. The register is specified as the
+ * actual PIO address. These are actually defined in compiler.h.
+ *
+ * inw/outw 16-bit counterparts to inl/outl. Not used for Mach64 support.
+ *
+ * inb/outb 8-bit counterparts to inl/outl.
+ *
+ * inm/outm 32-bit R/W through MMIO space. The register is specified as
+ * the actual MMIO offset (with Block 1 following Block 0), which,
+ * in this case, is equivalent to the register's IOPortTag from
+ * atiregs.h. Can be used for those few non-FIFO'ed registers
+ * outside of Block 0's first 256 bytes. inm() can also be used
+ * for FIFO'ed registers if, and only if, it can be guaranteed to
+ * not have been previously FIFO'ed (e.g. when the engine is
+ * idle). pATI->pBlock array elements must have been previously
+ * set up by ATIMapApertures().
+ *
+ * outf 32-bit write through MMIO cache. Identical to outm() but
+ * intended for FIFO'ed registers. There is no inf() provided.
+ *
+ * inr/outr 32-bit R/W through PIO or MMIO. Which one depends on the
+ * machine architecture. The register is specified as a IOPortTag
+ * from atiregs.h. Can only be used for registers in the first
+ * 256 bytes of MMIO space (in Block 0). Note that all of these
+ * registers are non-FIFO'ed.
+ *
+ * in8/out8 8-bit counterparts to inr/outr.
+ *
+ * For portability reasons, inr/outr/in8/out8 should be used in preference to
+ * inl/outl/inb/outb to/from any register space starting with CRTC_H_TOTAL_DISP
+ * but before DST_OFF_PITCH (in the order defined by atiregs.h). None of
+ * inm/outm/outf should ever be used for these registers.
+ *
+ * outf()'s should be grouped together as much as possible, while respecting
+ * any ordering constraints the engine might impose. Groups larger than 16
+ * outf()'s should be split up into two or more groups as needed (but not
+ * necessarily wanted). The outf() groups that result should be immediately
+ * preceeded by an ATIMach64WaitForFIFO(n) call, where "n" is the number of
+ * outf()'s in the group with the exception that groups containing a single
+ * outf() should not be thus preceeded. This means "n" should not be less than
+ * 2, nor larger than 16.
+ */
+
+/*
+ * Cave canem (or it WILL bite you): All Mach64 non-VGA registers are
+ * ================================ little-endian, no matter how they are
+ * accessed (nor by what).
+ */
+
+#define inm(_Register) \
+ MMIO_IN32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \
+ (_Register) & MM_IO_SELECT)
+#define outm(_Register, _Value) \
+ MMIO_OUT32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \
+ (_Register) & MM_IO_SELECT, _Value)
+
+#ifdef AVOID_CPIO
+
+# define inr(_Register) \
+ MMIO_IN32(pATI->pBlock[0], (_Register) & MM_IO_SELECT)
+# define outr(_Register, _Value) \
+ MMIO_OUT32(pATI->pBlock[0], (_Register) & MM_IO_SELECT, _Value)
+
+# define in8(_Register) \
+ MMIO_IN8(pATI->pBlock[0], \
+ (_Register) & (MM_IO_SELECT | IO_BYTE_SELECT))
+# define out8(_Register, _Value) \
+ MMIO_OUT8(pATI->pBlock[0], \
+ (_Register) & (MM_IO_SELECT | IO_BYTE_SELECT), _Value)
+
+/* Cause a cpp syntax error if any of these are used */
+#undef inb
+#undef inw
+#undef inl
+#undef outb
+#undef outw
+#undef outl
+
+#define inb() /* Nothing */
+#define inw() /* Nothing */
+#define inl() /* Nothing */
+#define outb() /* Nothing */
+#define outw() /* Nothing */
+#define outl() /* Nothing */
+
+#else /* AVOID_CPIO */
+
+# define ATIIOPort(_PortTag) \
+ (((pATI->CPIODecoding == SPARSE_IO) ? \
+ ((_PortTag) & (SPARSE_IO_SELECT | IO_BYTE_SELECT)) : \
+ ((_PortTag) & (BLOCK_IO_SELECT | IO_BYTE_SELECT))) | \
+ pATI->CPIOBase)
+
+# define inr(_Register) \
+ inl(ATIIOPort(_Register))
+# define outr(_Register, _Value) \
+ outl(ATIIOPort(_Register), _Value)
+
+# define in8(_Register) \
+ inb(ATIIOPort(_Register))
+# define out8(_Register, _Value) \
+ outb(ATIIOPort(_Register), _Value)
+
+#endif /* AVOID_CPIO */
+
+extern void ATIMach64PollEngineStatus FunctionPrototype((ATIPtr));
+
+/*
+ * MMIO cache definitions.
+ *
+ * Many FIFO'ed registers can be cached by the driver. Registers that qualify
+ * for caching must not contain values that can change without driver
+ * intervention. Thus registers that contain hardware counters, strobe lines,
+ * etc., cannot be cached. This caching is intended to minimise FIFO use.
+ * There is therefore not much point to enable it for non-FIFO'ed registers.
+ *
+ * The cache for a particular 32-bit register is enabled by coding a
+ * CacheRegister() line for that register in the ATIMach64Set() function. The
+ * integrity of the cache for a particular register should be verified by the
+ * ATIMach64Sync() function. This code should be kept in register order, as
+ * defined in atiregs.h.
+ */
+#define CacheByte(___Register) pATI->MMIOCached[CacheSlotOf(___Register) >> 3]
+#define CacheBit(___Register) (0x80U >> (CacheSlotOf(___Register) & 0x07U))
+
+#define RegisterIsCached(__Register) \
+ (CacheByte(__Register) & CacheBit(__Register))
+#define CacheSlot(__Register) pATI->MMIOCache[CacheSlotOf(__Register)]
+
+#define CacheRegister(__Register) \
+ CacheByte(__Register) |= CacheBit(__Register)
+#define UncacheRegister(__Register) \
+ CacheByte(__Register) &= ~CacheBit(__Register)
+
+/* This would be quite a bit slower as a function */
+#define outf(_Register, _Value) \
+ do \
+ { \
+ CARD32 _IOValue = (_Value); \
+ \
+ if (!RegisterIsCached(_Register) || \
+ (_IOValue != CacheSlot(_Register))) \
+ { \
+ while (!pATI->nAvailableFIFOEntries--) \
+ ATIMach64PollEngineStatus(pATI); \
+ MMIO_OUT32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \
+ (_Register) & MM_IO_SELECT, _IOValue); \
+ CacheSlot(_Register) = _IOValue; \
+ pATI->EngineIsBusy = TRUE; \
+ } \
+ } while (0)
+
+/*
+ * This is no longer as critical, especially for _n == 1. However,
+ * there is still a need to ensure _n <= pATI->nFIFOEntries.
+ */
+#define ATIMach64WaitForFIFO(_pATI, _n) \
+ while (pATI->nAvailableFIFOEntries < (_n)) \
+ ATIMach64PollEngineStatus(pATI)
+
+#define ATIMach64WaitForIdle(_pATI) \
+ while (pATI->EngineIsBusy) \
+ ATIMach64PollEngineStatus(pATI)
+
+extern void ATIAccessMach64PLLReg FunctionPrototype((ATIPtr, const CARD8,
+ const Bool));
+
+#define ATIGetMach64PLLReg(_Index) \
+ ( \
+ ATIAccessMach64PLLReg(pATI, _Index, FALSE), \
+ in8(CLOCK_CNTL + 2) \
+ )
+#define ATIPutMach64PLLReg(_Index, _Value) \
+ do \
+ { \
+ ATIAccessMach64PLLReg(pATI, _Index, TRUE); \
+ out8(CLOCK_CNTL + 2, _Value); \
+ } while (0)
+
+#define ATIGetMach64LCDReg(_Index) \
+ ( \
+ out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)), \
+ inr(LCD_DATA) \
+ )
+#define ATIPutMach64LCDReg(_Index, _Value) \
+ do \
+ { \
+ out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)); \
+ outr(LCD_DATA, _Value); \
+ } while (0)
+
+#define ATIGetMach64TVReg(_Index) \
+ ( \
+ out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)), \
+ inr(TV_OUT_DATA) \
+ )
+#define ATIPutMach64TVReg(_Index, _Value) \
+ do \
+ { \
+ out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)); \
+ outr(TV_OUT_DATA, _Value); \
+ } while (0)
+
+/*
+ * Block transfer definitions.
+ */
+
+#if defined(GCCUSESGAS) && \
+ (defined(i386) || defined(__i386) || defined(__i386__))
+
+#define ATIMove32(_pDst, _pSrc, _nCount) \
+ do \
+ { \
+ long d0, d1, d2; \
+ __asm__ __volatile__ \
+ ( \
+ "cld\n\t" \
+ "rep ; movsl" \
+ : "=&c" (d0), \
+ "=&D" (d1), \
+ "=&S" (d2) \
+ : "0" (_nCount), \
+ "1" (_pDst), \
+ "2" (_pSrc) \
+ : "memory" \
+ ); \
+ } while (0)
+
+#endif
+
+#endif /* ___ATIMACH64IO_H___ */
diff --git a/src/atimisc.c b/src/atimisc.c
new file mode 100644
index 0000000..f84240e
--- /dev/null
+++ b/src/atimisc.c
@@ -0,0 +1,104 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimisc.c,v 1.6 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef XFree86LOADER
+
+#include "ati.h"
+#include "atiload.h"
+#include "ativersion.h"
+
+/* Module loader interface for subsidiary driver module */
+
+static XF86ModuleVersionInfo ATIVersionRec =
+{
+ "atimisc",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ ATI_VERSION_MAJOR, ATI_VERSION_MINOR, ATI_VERSION_PATCH,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * ATISetup --
+ *
+ * This function is called every time the module is loaded.
+ */
+static pointer
+ATISetup
+(
+ pointer Module,
+ pointer Options,
+ int *ErrorMajor,
+ int *ErrorMinor
+)
+{
+ static Bool Inited = FALSE;
+
+ if (!Inited)
+ {
+ /* Ensure main driver module is loaded, but not as a submodule */
+ if (!xf86ServerIsOnlyDetecting() && !LoaderSymbol(ATI_NAME))
+ xf86LoadOneModule(ATI_DRIVER_NAME, Options);
+
+ /*
+ * Tell loader about symbols from other modules that this module might
+ * refer to.
+ */
+ xf86LoaderRefSymLists(
+ ATIint10Symbols,
+ ATIddcSymbols,
+ ATIvbeSymbols,
+
+#ifndef AVOID_CPIO
+
+ ATIxf1bppSymbols,
+ ATIxf4bppSymbols,
+
+#endif /* AVOID_CPIO */
+
+ ATIfbSymbols,
+ ATIshadowfbSymbols,
+ ATIxaaSymbols,
+ ATIramdacSymbols,
+ NULL);
+
+ Inited = TRUE;
+ }
+
+ return (pointer)TRUE;
+}
+
+/* The following record must be called atimiscModuleData */
+XF86ModuleData atimiscModuleData =
+{
+ &ATIVersionRec,
+ ATISetup,
+ NULL
+};
+
+#endif /* XFree86LOADER */
diff --git a/src/atimode.c b/src/atimode.c
new file mode 100644
index 0000000..d470ae4
--- /dev/null
+++ b/src/atimode.c
@@ -0,0 +1,1128 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.c,v 1.16 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "atidac.h"
+#include "atidsp.h"
+#include "atimach64.h"
+#include "atimach64io.h"
+#include "atimode.h"
+#include "atiprint.h"
+#include "atirgb514.h"
+#include "ativga.h"
+#include "atiwonder.h"
+#include "atiwonderio.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATICopyVGAMemory --
+ *
+ * This function is called to copy one or all banks of a VGA plane.
+ */
+static void
+ATICopyVGAMemory
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ pointer *saveptr,
+ pointer *from,
+ pointer *to
+)
+{
+ unsigned int iBank;
+
+ for (iBank = 0; iBank < pATIHW->nBank; iBank++)
+ {
+ (*pATIHW->SetBank)(pATI, iBank);
+ (void)memcpy(*to, *from, 0x00010000U);
+ *saveptr = (char *)(*saveptr) + 0x00010000U;
+ }
+}
+
+/*
+ * ATISwap --
+ *
+ * This function saves/restores video memory contents during video mode
+ * switches.
+ */
+static void
+ATISwap
+(
+ int iScreen,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ Bool ToFB
+)
+{
+ pointer save, *from, *to;
+ unsigned int iPlane = 0, PlaneMask = 1;
+ CARD8 seq2, seq4, gra1, gra3, gra4, gra5, gra6, gra8;
+
+ /*
+ * This is only done for non-accelerator modes. If the video state on
+ * server entry was an accelerator mode, the application that relinquished
+ * the console had better do the Right Thing (tm) anyway by saving and
+ * restoring its own video memory contents.
+ */
+ if (pATIHW->crtc != ATI_CRTC_VGA)
+ return;
+
+ if (ToFB)
+ {
+ if (!pATIHW->frame_buffer)
+ return;
+
+ from = &save;
+ to = &pATI->pBank;
+ }
+ else
+ {
+ /* Allocate the memory */
+ if (!pATIHW->frame_buffer)
+ {
+ pATIHW->frame_buffer =
+ (pointer)xalloc(pATIHW->nBank * pATIHW->nPlane * 0x00010000U);
+ if (!pATIHW->frame_buffer)
+ {
+ xf86DrvMsg(iScreen, X_WARNING,
+ "Temporary frame buffer could not be allocated.\n");
+ return;
+ }
+ }
+
+ from = &pATI->pBank;
+ to = &save;
+ }
+
+ /* Turn off screen */
+ ATIVGASaveScreen(pATI, SCREEN_SAVER_ON);
+
+ /* Save register values to be modified */
+ seq2 = GetReg(SEQX, 0x02U);
+ seq4 = GetReg(SEQX, 0x04U);
+ gra1 = GetReg(GRAX, 0x01U);
+ gra3 = GetReg(GRAX, 0x03U);
+ gra4 = GetReg(GRAX, 0x04U);
+ gra5 = GetReg(GRAX, 0x05U);
+ gra6 = GetReg(GRAX, 0x06U);
+ gra8 = GetReg(GRAX, 0x08U);
+
+ save = pATIHW->frame_buffer;
+
+ /* Temporarily normalise the mode */
+ if (gra1 != 0x00U)
+ PutReg(GRAX, 0x01U, 0x00U);
+ if (gra3 != 0x00U)
+ PutReg(GRAX, 0x03U, 0x00U);
+ if (gra6 != 0x05U)
+ PutReg(GRAX, 0x06U, 0x05U);
+ if (gra8 != 0xFFU)
+ PutReg(GRAX, 0x08U, 0xFFU);
+
+ if (seq4 & 0x08U)
+ {
+ /* Setup packed mode memory */
+ if (seq2 != 0x0FU)
+ PutReg(SEQX, 0x02U, 0x0FU);
+ if (seq4 != 0x0AU)
+ PutReg(SEQX, 0x04U, 0x0AU);
+ if (pATI->Chip < ATI_CHIP_264CT)
+ {
+ if (gra5 != 0x00U)
+ PutReg(GRAX, 0x05U, 0x00U);
+ }
+ else
+ {
+ if (gra5 != 0x40U)
+ PutReg(GRAX, 0x05U, 0x40U);
+ }
+
+ ATICopyVGAMemory(pATI, pATIHW, &save, from, to);
+
+ if (seq2 != 0x0FU)
+ PutReg(SEQX, 0x02U, seq2);
+ if (seq4 != 0x0AU)
+ PutReg(SEQX, 0x04U, seq4);
+ if (pATI->Chip < ATI_CHIP_264CT)
+ {
+ if (gra5 != 0x00U)
+ PutReg(GRAX, 0x05U, gra5);
+ }
+ else
+ {
+ if (gra5 != 0x40U)
+ PutReg(GRAX, 0x05U, gra5);
+ }
+ }
+ else
+ {
+ gra4 = GetReg(GRAX, 0x04U);
+
+ /* Setup planar mode memory */
+ if (seq4 != 0x06U)
+ PutReg(SEQX, 0x04U, 0x06U);
+ if (gra5 != 0x00U)
+ PutReg(GRAX, 0x05U, 0x00U);
+
+ for (; iPlane < pATIHW->nPlane; iPlane++)
+ {
+ PutReg(SEQX, 0x02U, PlaneMask);
+ PutReg(GRAX, 0x04U, iPlane);
+ ATICopyVGAMemory(pATI, pATIHW, &save, from, to);
+ PlaneMask <<= 1;
+ }
+
+ PutReg(SEQX, 0x02U, seq2);
+ if (seq4 != 0x06U)
+ PutReg(SEQX, 0x04U, seq4);
+ PutReg(GRAX, 0x04U, gra4);
+ if (gra5 != 0x00U)
+ PutReg(GRAX, 0x05U, gra5);
+ }
+
+ /* Restore registers */
+ if (gra1 != 0x00U)
+ PutReg(GRAX, 0x01U, gra1);
+ if (gra3 != 0x00U)
+ PutReg(GRAX, 0x03U, gra3);
+ if (gra6 != 0x05U)
+ PutReg(GRAX, 0x06U, gra6);
+ if (gra8 != 0xFFU)
+ PutReg(GRAX, 0x08U, gra8);
+
+ /* Back to bank 0 */
+ (*pATIHW->SetBank)(pATI, 0);
+
+ /*
+ * If restoring video memory for a server video mode, free the frame buffer
+ * save area.
+ */
+ if (ToFB && (pATIHW == &pATI->NewHW))
+ {
+ xfree(pATIHW->frame_buffer);
+ pATIHW->frame_buffer = NULL;
+ }
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIModePreInit --
+ *
+ * This function initialises an ATIHWRec with information common to all video
+ * states generated by the driver.
+ */
+void
+ATIModePreInit
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ CARD32 lcd_index;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /* Fill in VGA data */
+ ATIVGAPreInit(pATI, pATIHW);
+
+ /* Fill in VGA Wonder data */
+ if (pATI->CPIO_VGAWonder)
+ ATIVGAWonderPreInit(pATI, pATIHW);
+ }
+
+ /* Fill in Mach64 data */
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+ ATIMach64PreInit(pScreenInfo, pATI, pATIHW);
+
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ /* Ensure proper VCLK source */
+ pATIHW->pll_vclk_cntl = ATIGetMach64PLLReg(PLL_VCLK_CNTL) |
+ (PLL_VCLK_SRC_SEL | PLL_VCLK_RESET);
+
+ /* Set provisional values for other PLL registers */
+ pATIHW->pll_vclk_post_div = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV);
+ pATIHW->pll_vclk0_fb_div = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV);
+ pATIHW->pll_vclk1_fb_div = ATIGetMach64PLLReg(PLL_VCLK1_FB_DIV);
+ pATIHW->pll_vclk2_fb_div = ATIGetMach64PLLReg(PLL_VCLK2_FB_DIV);
+ pATIHW->pll_vclk3_fb_div = ATIGetMach64PLLReg(PLL_VCLK3_FB_DIV);
+ pATIHW->pll_xclk_cntl = ATIGetMach64PLLReg(PLL_XCLK_CNTL);
+
+ /* For now disable extended reference and feedback dividers */
+ if (pATI->Chip >= ATI_CHIP_264LT)
+ pATIHW->pll_ext_vpll_cntl =
+ ATIGetMach64PLLReg(PLL_EXT_VPLL_CNTL) &
+ ~(PLL_EXT_VPLL_EN | PLL_EXT_VPLL_VGA_EN |
+ PLL_EXT_VPLL_INSYNC);
+
+ /* Initialise CRTC data for LCD panels */
+ if (pATI->LCDPanelID >= 0)
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ lcd_index = inr(LCD_INDEX);
+ pATIHW->lcd_index = lcd_index &
+ ~(LCD_REG_INDEX | LCD_DISPLAY_DIS | LCD_SRC_SEL |
+ LCD_CRTC2_DISPLAY_DIS);
+ if (pATI->Chip != ATI_CHIP_264XL)
+ pATIHW->lcd_index |= LCD_CRTC2_DISPLAY_DIS;
+ pATIHW->config_panel =
+ ATIGetMach64LCDReg(LCD_CONFIG_PANEL) |
+ DONT_SHADOW_HEND;
+ pATIHW->lcd_gen_ctrl =
+ ATIGetMach64LCDReg(LCD_GEN_CNTL) & ~CRTC_RW_SELECT;
+ outr(LCD_INDEX, lcd_index);
+ }
+
+ pATIHW->lcd_gen_ctrl &=
+ ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | MCLK_PM_EN |
+ VCLK_DAC_PM_EN | USE_SHADOWED_VEND |
+ USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+ pATIHW->lcd_gen_ctrl |= DONT_SHADOW_VPAR | LOCK_8DOT;
+
+ if (!pATI->OptionPanelDisplay)
+ {
+ /*
+ * Use primary CRTC to drive the CRT. Turn off panel
+ * interface.
+ */
+ pATIHW->lcd_gen_ctrl &= ~LCD_ON;
+ pATIHW->lcd_gen_ctrl |= CRT_ON;
+ }
+ else
+ {
+ /* Use primary CRTC to drive the panel */
+ pATIHW->lcd_gen_ctrl |= LCD_ON;
+
+ /* If requested, also force CRT on */
+ if (pATI->OptionCRTDisplay)
+ pATIHW->lcd_gen_ctrl |= CRT_ON;
+ }
+ }
+ }
+ else if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIRGB514PreInit(pATI, pATIHW);
+ }
+
+ /* Set RAMDAC data */
+ ATIDACPreInit(pScreenInfo, pATI, pATIHW);
+}
+
+/*
+ * ATIModeSave --
+ *
+ * This function saves the current video state.
+ */
+void
+ATIModeSave
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+
+#ifndef AVOID_CPIO
+
+ int Index;
+
+ /* Get bank to bank 0 */
+ (*pATIHW->SetBank)(pATI, 0);
+
+#endif /* AVOID_CPIO */
+
+ /* Save clock data */
+ ATIClockSave(pScreenInfo, pATI, pATIHW);
+
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ pATIHW->pll_vclk_cntl = ATIGetMach64PLLReg(PLL_VCLK_CNTL) |
+ PLL_VCLK_RESET;
+ pATIHW->pll_vclk_post_div = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV);
+ pATIHW->pll_vclk0_fb_div = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV);
+ pATIHW->pll_vclk1_fb_div = ATIGetMach64PLLReg(PLL_VCLK1_FB_DIV);
+ pATIHW->pll_vclk2_fb_div = ATIGetMach64PLLReg(PLL_VCLK2_FB_DIV);
+ pATIHW->pll_vclk3_fb_div = ATIGetMach64PLLReg(PLL_VCLK3_FB_DIV);
+ pATIHW->pll_xclk_cntl = ATIGetMach64PLLReg(PLL_XCLK_CNTL);
+ if (pATI->Chip >= ATI_CHIP_264LT)
+ pATIHW->pll_ext_vpll_cntl = ATIGetMach64PLLReg(PLL_EXT_VPLL_CNTL);
+
+ /* Save LCD registers */
+ if (pATI->LCDPanelID >= 0)
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ pATIHW->horz_stretching = inr(HORZ_STRETCHING);
+ pATIHW->vert_stretching = inr(VERT_STRETCHING);
+ pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ /* Set up to save non-shadow registers */
+ outr(LCD_GEN_CTRL,
+ pATIHW->lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ pATIHW->lcd_index = inr(LCD_INDEX);
+ pATIHW->config_panel = ATIGetMach64LCDReg(LCD_CONFIG_PANEL);
+ pATIHW->lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+ pATIHW->horz_stretching =
+ ATIGetMach64LCDReg(LCD_HORZ_STRETCHING);
+ pATIHW->vert_stretching =
+ ATIGetMach64LCDReg(LCD_VERT_STRETCHING);
+ pATIHW->ext_vert_stretch =
+ ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH);
+
+ /* Set up to save non-shadow registers */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl &
+ ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN));
+ }
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /* Save VGA data */
+ ATIVGASave(pATI, pATIHW);
+
+ /* Save VGA Wonder data */
+ if (pATI->CPIO_VGAWonder)
+ ATIVGAWonderSave(pATI, pATIHW);
+ }
+
+ /* Save Mach64 data */
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+ ATIMach64Save(pATI, pATIHW);
+
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ /* Save DSP data */
+ ATIDSPSave(pATI, pATIHW);
+
+ if (pATI->LCDPanelID >= 0)
+ {
+ /* Switch to shadow registers */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL,
+ pATIHW->lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) |
+ (SHADOW_EN | SHADOW_RW_EN));
+
+#ifndef AVOID_CPIO
+
+ /* Save shadow VGA CRTC registers */
+ for (Index = 0;
+ Index < NumberOf(pATIHW->shadow_vga);
+ Index++)
+ pATIHW->shadow_vga[Index] =
+ GetReg(CRTX(pATI->CPIO_VGABase), Index);
+
+#endif /* AVOID_CPIO */
+
+ /* Save shadow Mach64 CRTC registers */
+ pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
+ pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
+ pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
+ pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
+
+ /* Restore CRTC selection and shadow state */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl);
+ outr(LCD_INDEX, pATIHW->lcd_index);
+ }
+ }
+ }
+ else if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIRGB514Save(pATI, pATIHW);
+ }
+
+#ifndef AVOID_CPIO
+
+ /*
+ * For some unknown reason, CLKDIV2 needs to be turned off to save the
+ * DAC's LUT reliably on VGA Wonder VLB adapters.
+ */
+ if ((pATI->Adapter == ATI_ADAPTER_NONISA) && (pATIHW->seq[1] & 0x08U))
+ PutReg(SEQX, 0x01U, pATIHW->seq[1] & ~0x08U);
+
+#endif /* AVOID_CPIO */
+
+ /* Save RAMDAC state */
+ ATIDACSave(pATI, pATIHW);
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Adapter == ATI_ADAPTER_NONISA) && (pATIHW->seq[1] & 0x08U))
+ PutReg(SEQX, 0x01U, pATIHW->seq[1]);
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * The server has already saved video memory contents when switching out of
+ * its virtual console, so don't do it again.
+ */
+ if (pATIHW != &pATI->NewHW)
+ {
+ pATIHW->FeedbackDivider = 0; /* Don't programme clock */
+
+#ifndef AVOID_CPIO
+
+ /* Save video memory */
+ ATISwap(pScreenInfo->scrnIndex, pATI, pATIHW, FALSE);
+
+#endif /* AVOID_CPIO */
+
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIVGASaveScreen(pATI, SCREEN_SAVER_OFF); /* Turn on screen */
+
+#endif /* AVOID_CPIO */
+
+}
+
+/*
+ * ATIModeCalculate --
+ *
+ * This function fills in an ATIHWRec with all register values needed to enable
+ * a video state. It's important that this be done without modifying the
+ * current video state.
+ */
+Bool
+ATIModeCalculate
+(
+ int iScreen,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ CARD32 lcd_index;
+ int Index, ECPClock, MaxScalerClock;
+
+ /* Clobber mode timings */
+ if ((pATI->LCDPanelID >= 0) && pATI->OptionPanelDisplay &&
+ !pMode->CrtcHAdjusted && !pMode->CrtcVAdjusted &&
+ (!pATI->OptionSync || (pMode->type & M_T_BUILTIN)))
+ {
+ int VScan;
+
+ pMode->Clock = pATI->LCDClock;
+ pMode->Flags &= ~(V_DBLSCAN | V_INTERLACE | V_CLKDIV2);
+
+ /*
+ * Use doublescanning or multiscanning to get around vertical blending
+ * limitations.
+ */
+ VScan = pATI->LCDVertical / pMode->VDisplay;
+ switch (pATIHW->crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ if (VScan > 64)
+ VScan = 64;
+ pMode->VScan = VScan;
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ pMode->VScan = 0;
+ if (VScan <= 1)
+ break;
+ VScan = 2;
+ pMode->Flags |= V_DBLSCAN;
+ break;
+
+ default:
+ break;
+ }
+
+ pMode->HSyncStart = pMode->HDisplay + pATI->LCDHSyncStart;
+ pMode->HSyncEnd = pMode->HSyncStart + pATI->LCDHSyncWidth;
+ pMode->HTotal = pMode->HDisplay + pATI->LCDHBlankWidth;
+
+ pMode->VSyncStart = pMode->VDisplay +
+ ATIDivide(pATI->LCDVSyncStart, VScan, 0, 0);
+ pMode->VSyncEnd = pMode->VSyncStart +
+ ATIDivide(pATI->LCDVSyncWidth, VScan, 0, 1);
+ pMode->VTotal = pMode->VDisplay +
+ ATIDivide(pATI->LCDVBlankWidth, VScan, 0, 0);
+ }
+
+ switch (pATIHW->crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /* Fill in VGA data */
+ ATIVGACalculate(pATI, pATIHW, pMode);
+
+ /* Fill in VGA Wonder data */
+ if (pATI->CPIO_VGAWonder)
+ ATIVGAWonderCalculate(pATI, pATIHW, pMode);
+
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+ {
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ /*
+ * Selected bits of accelerator & VGA CRTC registers are
+ * actually copies of each other.
+ */
+ pATIHW->crtc_h_total_disp =
+ SetBits(pMode->CrtcHTotal, CRTC_H_TOTAL) |
+ SetBits(pMode->CrtcHDisplay, CRTC_H_DISP);
+ pATIHW->crtc_h_sync_strt_wid =
+ SetBits(pMode->CrtcHSyncStart, CRTC_H_SYNC_STRT) |
+ SetBits(pMode->CrtcHSkew, CRTC_H_SYNC_DLY) | /* ? */
+ SetBits(GetBits(pMode->CrtcHSyncStart, 0x0100U),
+ CRTC_H_SYNC_STRT_HI) |
+ SetBits(pMode->CrtcHSyncEnd, CRTC_H_SYNC_WID);
+ if (pMode->Flags & V_NHSYNC)
+ pATIHW->crtc_h_sync_strt_wid |= CRTC_H_SYNC_POL;
+
+ pATIHW->crtc_v_total_disp =
+ SetBits(pMode->CrtcVTotal, CRTC_V_TOTAL) |
+ SetBits(pMode->CrtcVDisplay, CRTC_V_DISP);
+ pATIHW->crtc_v_sync_strt_wid =
+ SetBits(pMode->CrtcVSyncStart, CRTC_V_SYNC_STRT) |
+ SetBits(pMode->CrtcVSyncEnd, CRTC_V_SYNC_WID);
+ if (pMode->Flags & V_NVSYNC)
+ pATIHW->crtc_v_sync_strt_wid |= CRTC_V_SYNC_POL;
+ }
+
+ pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
+ ~(CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN |
+ CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_CSYNC_EN |
+ CRTC_PIX_BY_2_EN | CRTC_DISPLAY_DIS |
+ CRTC_VGA_XOVERSCAN | CRTC_VGA_128KAP_PAGING |
+ CRTC_VFC_SYNC_TRISTATE |
+ CRTC_LOCK_REGS | /* Already off, but ... */
+ CRTC_SYNC_TRISTATE | CRTC_EXT_DISP_EN |
+ CRTC_DISP_REQ_EN | CRTC_VGA_LINEAR | CRTC_VGA_TEXT_132 |
+ CRTC_CUR_B_TEST);
+#if 0 /* This isn't needed, but is kept for reference */
+ if (pMode->Flags & V_DBLSCAN)
+ pATIHW->crtc_gen_cntl |= CRTC_DBL_SCAN_EN;
+#endif
+ if (pMode->Flags & V_INTERLACE)
+ pATIHW->crtc_gen_cntl |= CRTC_INTERLACE_EN;
+ if ((pMode->Flags & (V_CSYNC | V_PCSYNC)) || pATI->OptionCSync)
+ pATIHW->crtc_gen_cntl |= CRTC_CSYNC_EN;
+ if (pATI->depth <= 4)
+ pATIHW->crtc_gen_cntl |= CRTC_EN | CRTC_CNT_EN;
+ else
+ pATIHW->crtc_gen_cntl |=
+ CRTC_EN | CRTC_VGA_LINEAR | CRTC_CNT_EN;
+ }
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ /* Fill in Mach64 data */
+ ATIMach64Calculate(pATI, pATIHW, pMode);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Set up LCD register values */
+ if (pATI->LCDPanelID >= 0)
+ {
+ int VDisplay = pMode->VDisplay;
+
+ if (pMode->Flags & V_DBLSCAN)
+ VDisplay <<= 1;
+ if (pMode->VScan > 1)
+ VDisplay *= pMode->VScan;
+ if (pMode->Flags & V_INTERLACE)
+ VDisplay >>= 1;
+
+ /* Ensure secondary CRTC is completely disabled */
+ pATIHW->crtc_gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ pATIHW->horz_stretching = inr(HORZ_STRETCHING);
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ lcd_index = inr(LCD_INDEX);
+ pATIHW->horz_stretching = ATIGetMach64LCDReg(LCD_HORZ_STRETCHING);
+ pATIHW->ext_vert_stretch =
+ ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH) &
+ ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
+
+ /*
+ * Don't use vertical blending if the mode is too wide or not
+ * vertically stretched.
+ */
+ if (pATI->OptionPanelDisplay &&
+ (pMode->HDisplay <= pATI->LCDVBlendFIFOSize) &&
+ (VDisplay < pATI->LCDVertical))
+ pATIHW->ext_vert_stretch |= VERT_STRETCH_MODE;
+
+ outr(LCD_INDEX, lcd_index);
+ }
+
+ pATIHW->horz_stretching &=
+ ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
+ HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
+ if (pATI->OptionPanelDisplay &&
+ (pMode->HDisplay < pATI->LCDHorizontal))
+ do
+ {
+ /*
+ * The horizontal blender misbehaves when HDisplay is less than a
+ * a certain threshold (440 for a 1024-wide panel). It doesn't
+ * stretch such modes enough. Use pixel replication instead of
+ * blending to stretch modes that can be made to exactly fit the
+ * panel width. The undocumented "NoLCDBlend" option allows the
+ * pixel-replicated mode to be slightly wider or narrower than the
+ * panel width. It also causes a mode that is exactly half as wide
+ * as the panel to be pixel-replicated, rather than blended.
+ */
+ int HDisplay = pMode->HDisplay & ~7;
+ int nStretch = pATI->LCDHorizontal / HDisplay;
+ int Remainder = pATI->LCDHorizontal % HDisplay;
+
+ if ((!Remainder && ((nStretch > 2) || !pATI->OptionBlend)) ||
+ (((HDisplay * 16) / pATI->LCDHorizontal) < 7))
+ {
+ static const char StretchLoops[] = {10, 12, 13, 15, 16};
+ int horz_stretch_loop = -1, BestRemainder;
+ int Numerator = HDisplay, Denominator = pATI->LCDHorizontal;
+
+ ATIReduceRatio(&Numerator, &Denominator);
+
+ BestRemainder = (Numerator * 16) / Denominator;
+ Index = NumberOf(StretchLoops);
+ while (--Index >= 0)
+ {
+ Remainder =
+ ((Denominator - Numerator) * StretchLoops[Index]) %
+ Denominator;
+ if (Remainder < BestRemainder)
+ {
+ horz_stretch_loop = Index;
+ if (!(BestRemainder = Remainder))
+ break;
+ }
+#if 0
+ /*
+ * Enabling this code allows the pixel-replicated mode to
+ * be slightly wider than the panel width.
+ */
+ Remainder = Denominator - Remainder;
+ if (Remainder < BestRemainder)
+ {
+ horz_stretch_loop = Index;
+ BestRemainder = Remainder;
+ }
+#endif
+ }
+
+ if ((horz_stretch_loop >= 0) &&
+ (!BestRemainder || !pATI->OptionBlend))
+ {
+ int horz_stretch_ratio = 0, Accumulator = 0;
+ int reuse_previous = 1;
+
+ Index = StretchLoops[horz_stretch_loop];
+
+ while (--Index >= 0)
+ {
+ if (Accumulator > 0)
+ horz_stretch_ratio |= reuse_previous;
+ else
+ Accumulator += Denominator;
+ Accumulator -= Numerator;
+ reuse_previous <<= 1;
+ }
+
+ pATIHW->horz_stretching |= HORZ_STRETCH_EN |
+ SetBits(horz_stretch_loop, HORZ_STRETCH_LOOP) |
+ SetBits(horz_stretch_ratio, HORZ_STRETCH_RATIO);
+ break; /* Out of the do { ... } while (0) */
+ }
+ }
+
+ pATIHW->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN) |
+ SetBits((HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) /
+ pATI->LCDHorizontal, HORZ_STRETCH_BLEND);
+ } while (0);
+
+ if (!pATI->OptionPanelDisplay || (VDisplay >= pATI->LCDVertical))
+ pATIHW->vert_stretching = 0;
+ else
+ {
+ pATIHW->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN) |
+ SetBits((VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) /
+ pATI->LCDVertical, VERT_STRETCH_RATIO0);
+ }
+
+#ifndef AVOID_CPIO
+
+ /* Copy non-shadow CRTC register values to the shadow set */
+ for (Index = 0; Index < NumberOf(pATIHW->shadow_vga); Index++)
+ pATIHW->shadow_vga[Index] = pATIHW->crt[Index];
+
+#endif /* AVOID_CPIO */
+
+ pATIHW->shadow_h_total_disp = pATIHW->crtc_h_total_disp;
+ pATIHW->shadow_h_sync_strt_wid = pATIHW->crtc_h_sync_strt_wid;
+ pATIHW->shadow_v_total_disp = pATIHW->crtc_v_total_disp;
+ pATIHW->shadow_v_sync_strt_wid = pATIHW->crtc_v_sync_strt_wid;
+ }
+
+ /* Fill in clock data */
+ if (!ATIClockCalculate(iScreen, pATI, pATIHW, pMode))
+ return FALSE;
+
+ /* Setup ECP clock divider */
+ if (pATI->Chip >= ATI_CHIP_264VT)
+ {
+ if (pATI->Chip <= ATI_CHIP_264VT3)
+ MaxScalerClock = 80000;
+ else if (pATI->Chip <= ATI_CHIP_264GT2C)
+ MaxScalerClock = 100000;
+ else if (pATI->Chip == ATI_CHIP_264GTPRO)
+ MaxScalerClock = 125000;
+ else if (pATI->Chip <= ATI_CHIP_MOBILITY)
+ MaxScalerClock = 135000;
+ else
+ MaxScalerClock = 80000; /* Conservative */
+ pATIHW->pll_vclk_cntl &= ~PLL_ECP_DIV;
+ /* XXX Don't do this for TVOut! */
+ ECPClock = pMode->SynthClock;
+ for (Index = 0; (ECPClock > MaxScalerClock) && (Index < 2); Index++)
+ ECPClock >>= 1;
+ pATIHW->pll_vclk_cntl |= SetBits(Index, PLL_ECP_DIV);
+ }
+ else if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIRGB514Calculate(pATI, pATIHW, pMode);
+
+ return TRUE;
+}
+
+/*
+ * ATIModeSet --
+ *
+ * This function sets a video mode. It writes out all video state data that
+ * has been previously calculated or saved.
+ */
+void
+ATIModeSet
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+
+#ifndef AVOID_CPIO
+
+ int Index;
+
+ /* Get back to bank 0 */
+ (*pATIHW->SetBank)(pATI, 0);
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ ATIPutMach64PLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl);
+ ATIPutMach64PLLReg(PLL_VCLK_POST_DIV, pATIHW->pll_vclk_post_div);
+ ATIPutMach64PLLReg(PLL_VCLK0_FB_DIV, pATIHW->pll_vclk0_fb_div);
+ ATIPutMach64PLLReg(PLL_VCLK1_FB_DIV, pATIHW->pll_vclk1_fb_div);
+ ATIPutMach64PLLReg(PLL_VCLK2_FB_DIV, pATIHW->pll_vclk2_fb_div);
+ ATIPutMach64PLLReg(PLL_VCLK3_FB_DIV, pATIHW->pll_vclk3_fb_div);
+ ATIPutMach64PLLReg(PLL_XCLK_CNTL, pATIHW->pll_xclk_cntl);
+ if (pATI->Chip >= ATI_CHIP_264LT)
+ ATIPutMach64PLLReg(PLL_EXT_VPLL_CNTL, pATIHW->pll_ext_vpll_cntl);
+ ATIPutMach64PLLReg(PLL_VCLK_CNTL,
+ pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET);
+
+ /* Load LCD registers */
+ if (pATI->LCDPanelID >= 0)
+ {
+ /* Stop CRTC */
+ outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl &
+ ~(CRTC_EXT_DISP_EN | CRTC_EN));
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ /* Update non-shadow registers first */
+ outr(LCD_GEN_CTRL,
+ pATIHW->lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+
+ /* Temporarily disable stretching */
+ outr(HORZ_STRETCHING, pATIHW->horz_stretching &
+ ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN));
+ outr(VERT_STRETCHING, pATIHW->vert_stretching &
+ ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
+ VERT_STRETCH_USE0 | VERT_STRETCH_EN));
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ /* Update non-shadow registers first */
+ ATIPutMach64LCDReg(LCD_CONFIG_PANEL, pATIHW->config_panel);
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl &
+ ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN));
+
+ /* Temporarily disable stretching */
+ ATIPutMach64LCDReg(LCD_HORZ_STRETCHING,
+ pATIHW->horz_stretching &
+ ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN));
+ ATIPutMach64LCDReg(LCD_VERT_STRETCHING,
+ pATIHW->vert_stretching &
+ ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
+ VERT_STRETCH_USE0 | VERT_STRETCH_EN));
+ }
+ }
+ }
+
+ switch (pATIHW->crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /* Stop CRTC */
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+ outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl & ~CRTC_EN);
+
+ /* Start sequencer reset */
+ PutReg(SEQX, 0x00U, 0x00U);
+
+ /* Set pixel clock */
+ if ((pATIHW->FeedbackDivider > 0) &&
+ (pATI->ProgrammableClock > ATI_CLOCK_FIXED))
+ ATIClockSet(pATI, pATIHW);
+
+ /* Set up RAMDAC */
+ if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIRGB514Set(pATI, pATIHW);
+
+ /* Load VGA Wonder */
+ if (pATI->CPIO_VGAWonder)
+ ATIVGAWonderSet(pATI, pATIHW);
+
+ /* Load VGA device */
+ ATIVGASet(pATI, pATIHW);
+
+ /* Load Mach64 registers */
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+ {
+ outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl);
+ outr(CUR_CLR0, pATIHW->cur_clr0);
+ outr(CUR_CLR1, pATIHW->cur_clr1);
+ outr(CUR_OFFSET, pATIHW->cur_offset);
+ outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn);
+ outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off);
+ outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel);
+ outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel);
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN);
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl);
+ outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN);
+ outr(CONFIG_CNTL, pATIHW->config_cntl);
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp);
+ outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid);
+ outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp);
+ outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid);
+ outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch);
+ outr(BUS_CNTL, pATIHW->bus_cntl);
+ outr(DAC_CNTL, pATIHW->dac_cntl);
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ {
+ outr(MEM_CNTL, pATIHW->mem_cntl);
+ outr(MPP_CONFIG, pATIHW->mpp_config);
+ outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq);
+ outr(TVO_CNTL, pATIHW->tvo_cntl);
+ }
+ }
+ }
+
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ /* Load Mach64 CRTC registers */
+ ATIMach64Set(pATI, pATIHW);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->UseSmallApertures)
+ {
+ /* Oddly enough, these need to be set also, maybe others */
+ PutReg(SEQX, 0x02U, pATIHW->seq[2]);
+ PutReg(SEQX, 0x04U, pATIHW->seq[4]);
+ PutReg(GRAX, 0x06U, pATIHW->gra[6]);
+ if (pATI->CPIO_VGAWonder)
+ ATIModifyExtReg(pATI, 0xB6U, -1, 0x00U, pATIHW->b6);
+ }
+
+#endif /* AVOID_CPIO */
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (pATI->LCDPanelID >= 0)
+ {
+ /* Switch to shadow registers */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ outr(LCD_GEN_CTRL,
+ pATIHW->lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) |
+ (SHADOW_EN | SHADOW_RW_EN));
+
+ /* Restore shadow registers */
+ switch (pATIHW->crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ for (Index = 0;
+ Index < NumberOf(pATIHW->shadow_vga);
+ Index++)
+ PutReg(CRTX(pATI->CPIO_VGABase), Index,
+ pATIHW->shadow_vga[Index]);
+ /* Fall through */
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ outr(CRTC_H_TOTAL_DISP, pATIHW->shadow_h_total_disp);
+ outr(CRTC_H_SYNC_STRT_WID, pATIHW->shadow_h_sync_strt_wid);
+ outr(CRTC_V_TOTAL_DISP, pATIHW->shadow_v_total_disp);
+ outr(CRTC_V_SYNC_STRT_WID, pATIHW->shadow_v_sync_strt_wid);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Restore CRTC selection & shadow state and enable stretching */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl);
+ outr(HORZ_STRETCHING, pATIHW->horz_stretching);
+ outr(VERT_STRETCHING, pATIHW->vert_stretching);
+ }
+ else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY)) */
+ {
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl);
+ ATIPutMach64LCDReg(LCD_HORZ_STRETCHING, pATIHW->horz_stretching);
+ ATIPutMach64LCDReg(LCD_VERT_STRETCHING, pATIHW->vert_stretching);
+ ATIPutMach64LCDReg(LCD_EXT_VERT_STRETCH, pATIHW->ext_vert_stretch);
+ outr(LCD_INDEX, pATIHW->lcd_index);
+ }
+ }
+
+ /*
+ * Set DSP registers. Note that, for some reason, sequencer resets clear
+ * the DSP_CONFIG register on early integrated controllers.
+ */
+ if (pATI->Chip >= ATI_CHIP_264VTB)
+ ATIDSPSet(pATI, pATIHW);
+
+ /* Load RAMDAC */
+ ATIDACSet(pATI, pATIHW);
+
+ /* Reset hardware cursor caching */
+ pATI->CursorXOffset = pATI->CursorYOffset = (CARD16)(-1);
+
+#ifndef AVOID_CPIO
+
+ /* Restore video memory */
+ ATISwap(pScreenInfo->scrnIndex, pATI, pATIHW, TRUE);
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIVGASaveScreen(pATI, SCREEN_SAVER_OFF); /* Turn on screen */
+
+#endif /* AVOID_CPIO */
+
+ if ((xf86GetVerbosity() > 3) && (pATIHW == &pATI->NewHW))
+ {
+ xf86ErrorFVerb(4, "\n After setting mode \"%s\":\n\n",
+ pScreenInfo->currentMode->name);
+ ATIPrintMode(pScreenInfo->currentMode);
+ ATIPrintRegisters(pATI);
+ }
+}
diff --git a/src/atimode.h b/src/atimode.h
new file mode 100644
index 0000000..63cb765
--- /dev/null
+++ b/src/atimode.h
@@ -0,0 +1,41 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.h,v 1.5 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIMODE_H___
+#define ___ATIMODE_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern void ATIModePreInit FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+extern void ATIModeSave FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+extern Bool ATIModeCalculate FunctionPrototype((int, ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIModeSet FunctionPrototype((ScrnInfoPtr, ATIPtr,
+ ATIHWPtr));
+
+#endif /* ___ATIMODE_H___ */
diff --git a/src/atimodule.c b/src/atimodule.c
new file mode 100644
index 0000000..842d659
--- /dev/null
+++ b/src/atimodule.c
@@ -0,0 +1,126 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c,v 1.15 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef XFree86LOADER
+
+#include "ati.h"
+#include "atimodule.h"
+#include "ativersion.h"
+
+/* Module loader interface */
+
+const char *ATISymbols[] =
+{
+ "ATIPreInit",
+ "ATIScreenInit",
+ "ATISwitchMode",
+ "ATIAdjustFrame",
+ "ATIEnterVT",
+ "ATILeaveVT",
+ "ATIFreeScreen",
+ "ATIValidMode",
+ NULL
+};
+
+const char *R128Symbols[] =
+{
+ "R128PreInit",
+ "R128ScreenInit",
+ "R128SwitchMode",
+ "R128AdjustFrame",
+ "R128EnterVT",
+ "R128LeaveVT",
+ "R128FreeScreen",
+ "R128ValidMode",
+ "R128Options",
+ NULL
+};
+
+const char *RADEONSymbols[] =
+{
+ "RADEONPreInit",
+ "RADEONScreenInit",
+ "RADEONSwitchMode",
+ "RADEONAdjustFrame",
+ "RADEONEnterVT",
+ "RADEONLeaveVT",
+ "RADEONFreeScreen",
+ "RADEONValidMode",
+ "RADEONOptions",
+ NULL
+};
+
+static XF86ModuleVersionInfo ATIVersionRec =
+{
+ ATI_DRIVER_NAME,
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ ATI_VERSION_MAJOR, ATI_VERSION_MINOR, ATI_VERSION_PATCH,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * ATISetup --
+ *
+ * This function is called every time the module is loaded.
+ */
+static pointer
+ATISetup
+(
+ pointer Module,
+ pointer Options,
+ int *ErrorMajor,
+ int *ErrorMinor
+)
+{
+ static Bool Inited = FALSE;
+
+ if (!Inited)
+ {
+ Inited = TRUE;
+ xf86AddDriver(&ATI, Module, 0);
+
+ xf86LoaderRefSymLists(
+ ATISymbols,
+ R128Symbols,
+ RADEONSymbols,
+ NULL);
+ }
+
+ return (pointer)1;
+}
+
+/* The following record must be called atiModuleData */
+XF86ModuleData atiModuleData =
+{
+ &ATIVersionRec,
+ ATISetup,
+ NULL
+};
+
+#endif /* XFree86LOADER */
diff --git a/src/atimodule.h b/src/atimodule.h
new file mode 100644
index 0000000..833e421
--- /dev/null
+++ b/src/atimodule.h
@@ -0,0 +1,31 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.h,v 1.9 2003/01/01 19:16:32 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(XFree86LOADER) && !defined(___ATIMODULE_H___)
+#define ___ATIMODULE_H___ 1
+
+extern const char *ATISymbols[];
+extern const char *R128Symbols[];
+extern const char *RADEONSymbols[];
+
+#endif /* ___ATIMODULE_H___ */
diff --git a/src/atimono.h b/src/atimono.h
new file mode 100644
index 0000000..6325cbe
--- /dev/null
+++ b/src/atimono.h
@@ -0,0 +1,43 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimono.h,v 1.7 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIMONO_H___
+#define ___ATIMONO_H___ 1
+
+#ifndef BIT_PLANE
+# define BIT_PLANE 3
+#endif
+
+#ifndef MONO_BLACK
+# define MONO_BLACK 0x00U
+#endif
+
+#ifndef MONO_WHITE
+# define MONO_WHITE 0x3FU
+#endif
+
+#ifndef MONO_OVERSCAN
+# define MONO_OVERSCAN 0x01U
+#endif
+
+#endif /* ___ATIMONO_H___ */
diff --git a/src/atioption.c b/src/atioption.c
new file mode 100644
index 0000000..573bb10
--- /dev/null
+++ b/src/atioption.c
@@ -0,0 +1,150 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.c,v 1.21 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atioption.h"
+#include "atiutil.h"
+
+#include "radeon_probe.h"
+#include "r128_probe.h"
+
+/*
+ * Recognised XF86Config options.
+ */
+const OptionInfoRec ATIPublicOptions[] =
+{
+ {
+ ATI_OPTION_ACCEL,
+ "accel",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_CRT_DISPLAY,
+ "crt_display",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_CSYNC,
+ "composite_sync",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_HWCURSOR,
+ "hw_cursor",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE,
+ },
+
+#ifndef AVOID_CPIO
+
+ {
+ ATI_OPTION_LINEAR,
+ "linear",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+
+#endif /* AVOID_CPIO */
+
+ {
+ ATI_OPTION_MMIO_CACHE,
+ "mmio_cache",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_PANEL_DISPLAY,
+ "panel_display",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_PROBE_CLOCKS,
+ "probe_clocks",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_REFERENCE_CLOCK,
+ "reference_clock",
+ OPTV_FREQ,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_SHADOW_FB,
+ "shadow_fb",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_SWCURSOR,
+ "sw_cursor",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE,
+ },
+ {
+ -1,
+ NULL,
+ OPTV_NONE,
+ {0, },
+ FALSE
+ }
+};
+
+const unsigned long ATIPublicOptionSize = SizeOf(ATIPublicOptions);
+
+/*
+ * ATIAvailableOptions --
+ *
+ * Return recognised options that are intended for public consumption.
+ */
+const OptionInfoRec *
+ATIAvailableOptions
+(
+ int ChipId,
+ int BusId
+)
+{
+ const OptionInfoRec *pOptions;
+
+ if ((pOptions = R128AvailableOptions(ChipId, BusId)))
+ return pOptions;
+
+ if ((pOptions = RADEONAvailableOptions(ChipId, BusId)))
+ return pOptions;
+
+ return ATIPublicOptions;
+}
diff --git a/src/atioption.h b/src/atioption.h
new file mode 100644
index 0000000..ea66018
--- /dev/null
+++ b/src/atioption.h
@@ -0,0 +1,60 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.h,v 1.11 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIOPTION_H___
+#define ___ATIOPTION_H___ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+/*
+ * Documented XF86Config options.
+ */
+typedef enum
+{
+ ATI_OPTION_ACCEL,
+ ATI_OPTION_CRT_DISPLAY,
+ ATI_OPTION_CSYNC,
+ ATI_OPTION_HWCURSOR,
+
+#ifndef AVOID_CPIO
+
+ ATI_OPTION_LINEAR,
+
+#endif /* AVOID_CPIO */
+
+ ATI_OPTION_MMIO_CACHE,
+ ATI_OPTION_PANEL_DISPLAY,
+ ATI_OPTION_PROBE_CLOCKS,
+ ATI_OPTION_REFERENCE_CLOCK,
+ ATI_OPTION_SHADOW_FB,
+ ATI_OPTION_SWCURSOR
+} ATIPublicOptionType;
+
+extern const OptionInfoRec ATIPublicOptions[];
+extern const unsigned long ATIPublicOptionSize;
+
+extern const OptionInfoRec * ATIAvailableOptions FunctionPrototype((int, int));
+
+#endif /* ___ATIOPTION_H___ */
diff --git a/src/atipreinit.c b/src/atipreinit.c
new file mode 100644
index 0000000..675b036
--- /dev/null
+++ b/src/atipreinit.c
@@ -0,0 +1,3090 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atipreinit.c,v 1.65 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atiadjust.h"
+#include "atibus.h"
+#include "atichip.h"
+#include "aticonfig.h"
+#include "aticursor.h"
+#include "atidac.h"
+#include "atidsp.h"
+#include "atiident.h"
+#include "atiload.h"
+#include "atilock.h"
+#include "atimach64.h"
+#include "atimach64io.h"
+#include "atimode.h"
+#include "atipreinit.h"
+#include "atiprint.h"
+#include "atividmem.h"
+#include "atiwonderio.h"
+
+#include "vbe.h"
+#include "xf86RAC.h"
+
+#ifndef AVOID_CPIO
+
+typedef CARD16 Colour; /* The correct spelling should be OK :-) */
+
+/*
+ * Bit patterns which are extremely unlikely to show up when reading from
+ * nonexistant memory (which normally shows up as either all bits set or all
+ * bits clear).
+ */
+static const Colour Test_Pixel[] = {0x5AA5U, 0x55AAU, 0xA55AU, 0xCA53U};
+
+static const struct
+{
+ int videoRamSize;
+ int Miscellaneous_Options_Setting;
+ struct
+ {
+ short int x, y;
+ }
+ Coordinates[NumberOf(Test_Pixel) + 1];
+}
+Test_Case[] =
+{
+ /*
+ * Given the engine settings used, only a 4M card will have enough memory
+ * to back up the 1025th line of the display. Since the pixel coordinates
+ * are zero-based, line 1024 will be the first one which is only backed on
+ * 4M cards.
+ *
+ * <Mark_Weaver@brown.edu>:
+ * In case memory is being wrapped, (0,0) and (0,1024) to make sure they
+ * can each hold a unique value.
+ */
+ {4096, MEM_SIZE_4M, {{0,0}, {0,1024}, {-1,-1}}},
+
+ /*
+ * This card has 2M or less. On a 1M card, the first 2M of the card's
+ * memory will have even doublewords backed by physical memory and odd
+ * doublewords unbacked.
+ *
+ * Pixels 0 and 1 of a row will be in the zeroth doubleword, while pixels 2
+ * and 3 will be in the first. Check both pixels 2 and 3 in case this is a
+ * pseudo-1M card (one chip pulled to turn a 2M card into a 1M card).
+ *
+ * <Mark_Weaver@brown.edu>:
+ * I don't have a 1M card, so I'm taking a stab in the dark. Maybe memory
+ * wraps every 512 lines, or maybe odd doublewords are aliases of their
+ * even doubleword counterparts. I try everything here.
+ */
+ {2048, MEM_SIZE_2M, {{0,0}, {0,512}, {2,0}, {3,0}, {-1,-1}}},
+
+ /*
+ * This is a either a 1M card or a 512k card. Test pixel 1, since it is an
+ * odd word in an even doubleword.
+ *
+ * <Mark_Weaver@brown.edu>:
+ * This is the same idea as the test above.
+ */
+ {1024, MEM_SIZE_1M, {{0,0}, {0,256}, {1,0}, {-1,-1}}},
+
+ /*
+ * Assume it is a 512k card by default, since that is the minimum
+ * configuration.
+ */
+ {512, MEM_SIZE_512K, {{-1,-1}}}
+};
+
+/*
+ * ATIMach32ReadPixel --
+ *
+ * Return the colour of the specified screen location. Called from
+ * ATIMach32videoRam function below.
+ */
+static Colour
+ATIMach32ReadPixel
+(
+ const short int X,
+ const short int Y
+)
+{
+ Colour Pixel_Colour;
+
+ /* Wait for idle engine */
+ ProbeWaitIdleEmpty();
+
+ /* Set up engine for pixel read */
+ ATIWaitQueue(7);
+ outw(RD_MASK, (CARD16)(~0));
+ outw(DP_CONFIG, FG_COLOR_SRC_BLIT | DATA_WIDTH | DRAW | DATA_ORDER);
+ outw(CUR_X, X);
+ outw(CUR_Y, Y);
+ outw(DEST_X_START, X);
+ outw(DEST_X_END, X + 1);
+ outw(DEST_Y_END, Y + 1);
+
+ /* Wait for data to become ready */
+ ATIWaitQueue(16);
+ WaitDataReady();
+
+ /* Read pixel colour */
+ Pixel_Colour = inw(PIX_TRANS);
+ ProbeWaitIdleEmpty();
+ return Pixel_Colour;
+}
+
+/*
+ * ATIMach32WritePixel --
+ *
+ * Set the colour of the specified screen location. Called from
+ * ATIMach32videoRam function below.
+ */
+static void
+ATIMach32WritePixel
+(
+ const short int X,
+ const short int Y,
+ const Colour Pixel_Colour
+)
+{
+ /* Set up engine for pixel write */
+ ATIWaitQueue(9);
+ outw(WRT_MASK, (CARD16)(~0));
+ outw(DP_CONFIG, FG_COLOR_SRC_FG | DRAW | READ_WRITE);
+ outw(ALU_FG_FN, MIX_FN_PAINT);
+ outw(FRGD_COLOR, Pixel_Colour);
+ outw(CUR_X, X);
+ outw(CUR_Y, Y);
+ outw(DEST_X_START, X);
+ outw(DEST_X_END, X + 1);
+ outw(DEST_Y_END, Y + 1);
+}
+
+/*
+ * ATIMach32videoRam --
+ *
+ * Determine the amount of video memory installed on an 68800-6 based adapter.
+ * This is done because these chips exhibit a bug that causes their
+ * MISC_OPTIONS register to report 1M rather than the true amount of memory.
+ *
+ * This function is adapted from a similar function in mach32mem.c written by
+ * Robert Wolff, David Dawes and Mark Weaver.
+ */
+static int
+ATIMach32videoRam
+(
+ void
+)
+{
+ CARD16 clock_sel, mem_bndry, misc_options, ext_ge_config;
+ Colour saved_Pixel[NumberOf(Test_Pixel)];
+ unsigned int Case_Number, Pixel_Number;
+ Bool AllPixelsOK;
+
+ /* Save register values to be modified */
+ clock_sel = inw(CLOCK_SEL);
+ mem_bndry = inw(MEM_BNDRY);
+ misc_options = inw(MISC_OPTIONS) & ~MEM_SIZE_ALIAS;
+ ext_ge_config = inw(R_EXT_GE_CONFIG);
+
+ /* Wait for enough FIFO entries */
+ ATIWaitQueue(7);
+
+ /* Enable accelerator */
+ outw(CLOCK_SEL, clock_sel | DISABPASSTHRU);
+
+ /* Make accelerator and VGA share video memory */
+ outw(MEM_BNDRY, mem_bndry & ~(MEM_PAGE_BNDRY | MEM_BNDRY_ENA));
+
+ /* Prevent video memory wrap */
+ outw(MISC_OPTIONS, misc_options | MEM_SIZE_4M);
+
+ /*
+ * Set up the drawing engine for a pitch of 1024 at 16 bits per pixel. No
+ * need to mess with the CRT because the results of this test are not
+ * intended to be seen.
+ */
+ outw(EXT_GE_CONFIG, PIXEL_WIDTH_16 | ORDER_16BPP_565 | MONITOR_8514 |
+ ALIAS_ENA);
+ outw(GE_PITCH, 1024 >> 3);
+ outw(GE_OFFSET_HI, 0);
+ outw(GE_OFFSET_LO, 0);
+
+ for (Case_Number = 0;
+ Case_Number < (NumberOf(Test_Case) - 1);
+ Case_Number++)
+ {
+ /* Reduce redundancy as per Mark_Weaver@brown.edu */
+# define TestPixel Test_Case[Case_Number].Coordinates[Pixel_Number]
+# define ForEachTestPixel \
+ for (Pixel_Number = 0; TestPixel.x >= 0; Pixel_Number++)
+
+ /* Save pixel colours that will be clobbered */
+ ForEachTestPixel
+ saved_Pixel[Pixel_Number] =
+ ATIMach32ReadPixel(TestPixel.x, TestPixel.y);
+
+ /* Write test patterns */
+ ForEachTestPixel
+ ATIMach32WritePixel(TestPixel.x, TestPixel.y,
+ Test_Pixel[Pixel_Number]);
+
+ /* Test for lost pixels */
+ AllPixelsOK = TRUE;
+ ForEachTestPixel
+ if (ATIMach32ReadPixel(TestPixel.x, TestPixel.y) !=
+ Test_Pixel[Pixel_Number])
+ {
+ AllPixelsOK = FALSE;
+ break;
+ }
+
+ /* Restore clobbered pixels */
+ ForEachTestPixel
+ ATIMach32WritePixel(TestPixel.x, TestPixel.y,
+ saved_Pixel[Pixel_Number]);
+
+ /* End test on success */
+ if (AllPixelsOK)
+ break;
+
+ /* Completeness */
+# undef ForEachTestPixel
+# undef TestPixel
+ }
+
+ /* Restore what was changed and correct MISC_OPTIONS register */
+ ATIWaitQueue(4);
+ outw(EXT_GE_CONFIG, ext_ge_config);
+ misc_options |= Test_Case[Case_Number].Miscellaneous_Options_Setting;
+ outw(MISC_OPTIONS, misc_options);
+ outw(MEM_BNDRY, mem_bndry);
+ outw(CLOCK_SEL, clock_sel);
+
+ /* Wait for activity to die down */
+ ProbeWaitIdleEmpty();
+
+ /* Tell ATIPreInit the REAL story */
+ return Test_Case[Case_Number].videoRamSize;
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIReportMemory --
+ *
+ * This function reports on the amount and type of video memory found.
+ */
+static void
+ATIReportMemory
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ const char *MemoryTypeName
+)
+{
+ char Buffer[128], *Message;
+
+ Message = Buffer +
+ snprintf(Buffer, SizeOf(Buffer), "%d kB of %s detected",
+ pATI->VideoRAM, MemoryTypeName);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth == 1)
+ {
+ /* 1bpp only uses one plane of four */
+ pScreenInfo->videoRam /= 4;
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ " (using %d kB)", pScreenInfo->videoRam);
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->VideoRAM > pScreenInfo->videoRam)
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ " (using %d kB)", pScreenInfo->videoRam);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
+}
+
+static const int videoRamSizes[] =
+ {0, 256, 512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024, 0};
+static const rgb defaultWeight = {0, 0, 0};
+static const Gamma defaultGamma = {0.0, 0.0, 0.0};
+
+/*
+ * ATIMapMach64 --
+ *
+ * This function attempts to mmap() a Mach64's MMIO aperture.
+ */
+static void
+ATIMapMach64
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ (void)ATIMapApertures(iScreen, pATI);
+ if (!pATI->pBlock[0] ||
+ (pATI->config_chip_id != inr(CONFIG_CHIP_ID)))
+ ATIUnmapApertures(iScreen, pATI);
+}
+
+/*
+ * ATIPrintNoiseIfRequested --
+ *
+ * This function formats debugging information on the server's stderr when
+ * requested by the user through the server's verbosity setting.
+ */
+static void
+ATIPrintNoiseIfRequested
+(
+ ATIPtr pATI,
+ CARD8 *BIOS,
+ unsigned int BIOSSize
+)
+{
+ if (xf86GetVerbosity() <= 3)
+ return;
+
+ if (BIOSSize > 0)
+ ATIPrintBIOS(BIOS, BIOSSize);
+ xf86ErrorFVerb(4, "\n On server entry:\n");
+ ATIPrintRegisters(pATI);
+}
+
+/*
+ * ATIPreInit --
+ *
+ * This function is only called once per screen at the start of the first
+ * server generation.
+ */
+Bool
+ATIPreInit
+(
+ ScrnInfoPtr pScreenInfo,
+ int flags
+)
+{
+# define BIOS_SIZE 0x00010000U /* 64kB */
+ CARD8 BIOS[BIOS_SIZE];
+# define BIOSByte(_n) ((CARD8)(BIOS[_n]))
+# define BIOSWord(_n) ((CARD16)(BIOS[_n] | \
+ (BIOS[(_n) + 1] << 8)))
+# define BIOSLong(_n) ((CARD32)(BIOS[_n] | \
+ (BIOS[(_n) + 1] << 8) | \
+ (BIOS[(_n) + 2] << 16) | \
+ (BIOS[(_n) + 3] << 24)))
+ unsigned int BIOSSize = 0;
+ unsigned int ROMTable = 0, ClockTable = 0, FrequencyTable = 0;
+ unsigned int LCDTable = 0, LCDPanelInfo = 0;
+
+ char Buffer[128], *Message;
+ ATIPtr pATI;
+ GDevPtr pGDev;
+ EntityInfoPtr pEntity;
+ resPtr pResources;
+ pciVideoPtr pVideo;
+ DisplayModePtr pMode;
+ unsigned long Block0Base;
+ CARD32 IOValue;
+ int i, j, AcceleratorVideoRAM = 0, ServerVideoRAM;
+ int Numerator, Denominator;
+ int MinX, MinY;
+ ClockRange ATIClockRange = {NULL, 0, 80000, 0, TRUE, TRUE, 1, 1, 0};
+ int DefaultmaxClock = 0;
+ int minPitch, maxPitch = 0xFFU, maxHeight = 0;
+ int ApertureSize = 0x00010000U;
+ LookupModeFlags Strategy = LOOKUP_CLOSEST_CLOCK;
+
+# define pATIHW (&pATI->OldHW)
+
+#ifndef AVOID_CPIO
+
+ xf86Int10InfoPtr pInt10Info = NULL;
+ vbeInfoPtr pVBE;
+ pointer pInt10Module, pDDCModule = NULL, pVBEModule = NULL;
+ int VGAVideoRAM = 0;
+ resRange Resources[2] = {{0, 0, 0}, _END};
+
+#endif /* AVOID_CPIO */
+
+ if (pScreenInfo->numEntities != 1)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Logic error: Number of attached entities not 1.\n");
+ return FALSE;
+ }
+
+ pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->iEntity != pScreenInfo->entityList[0])
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Logic error: Entity mismatch.\n");
+ return FALSE;
+ }
+
+ /* Register resources */
+ pEntity = xf86GetEntityInfo(pATI->iEntity);
+ pGDev = pEntity->device;
+ pResources = pEntity->resources;
+ xfree(pEntity);
+ if (!pResources)
+ pResources = xf86RegisterResources(pATI->iEntity, NULL,
+ pATI->SharedAccelerator ? ResShared : ResExclusive);
+ if (pResources)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Unable to register the following bus resources:\n");
+ xf86PrintResList(0, pResources);
+ xf86FreeResList(pResources);
+ return FALSE;
+ }
+
+ ConfiguredMonitor = NULL;
+ (void)memset(BIOS, 0, SizeOf(BIOS));
+
+ if (!(flags & PROBE_DETECT))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex,
+ pATI->Chipset ? X_CONFIG : X_DEFAULT,
+ "Chipset: \"%s\".\n", ATIChipsetNames[pATI->Chipset]);
+
+ /* Promote chipset specification */
+ switch (pATI->Chipset)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CHIPSET_IBMVGA:
+ if (pATI->Adapter == ATI_ADAPTER_VGA)
+ break; /* XXX */
+ /* Fall through */
+
+ case ATI_CHIPSET_VGAWONDER:
+ pATI->Chipset = ATI_CHIPSET_ATIVGA;
+ break;
+
+ case ATI_CHIPSET_IBM8514:
+ if (pATI->Adapter == ATI_ADAPTER_8514A)
+ break; /* XXX */
+ /* Fall through */
+
+ case ATI_CHIPSET_MACH8:
+ case ATI_CHIPSET_MACH32:
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CHIPSET_MACH64:
+ case ATI_CHIPSET_RAGE128:
+ case ATI_CHIPSET_RADEON:
+ pATI->Chipset = ATI_CHIPSET_ATI;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Set monitor */
+ pScreenInfo->monitor = pScreenInfo->confScreen->monitor;
+
+ /* Set depth, bpp, etc. */
+ if ((pATI->Chipset != ATI_CHIPSET_ATI) ||
+ (pATI->Chip < ATI_CHIP_264CT))
+ i = NoDepth24Support; /* No support for >8bpp either */
+ else
+ i = Support24bppFb | Support32bppFb;
+ if (!xf86SetDepthBpp(pScreenInfo, 8, 8, 8, i))
+ return FALSE;
+
+ for (j = 0; ; j++)
+ {
+ static const CARD8 AllowedDepthBpp[][2] =
+ {
+
+#ifndef AVOID_CPIO
+
+ { 1, 1},
+ { 4, 4},
+ { 4, 8},
+
+#endif /* AVOID_CPIO */
+
+ { 8, 8},
+ {15, 16},
+ {16, 16},
+ {24, 24},
+ {24, 32}
+ };
+
+ if (j < NumberOf(AllowedDepthBpp))
+ {
+ if (pScreenInfo->depth > AllowedDepthBpp[j][0])
+ continue;
+
+ if (pScreenInfo->depth == AllowedDepthBpp[j][0])
+ {
+ if (pScreenInfo->bitsPerPixel > AllowedDepthBpp[j][1])
+ continue;
+
+ if (pScreenInfo->bitsPerPixel == AllowedDepthBpp[j][1])
+ break;
+ }
+ }
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Driver does not support depth %d at fbbpp %d.\n",
+ pScreenInfo->depth, pScreenInfo->bitsPerPixel);
+ return FALSE;
+ }
+
+ xf86PrintDepthBpp(pScreenInfo);
+
+ if ((i == NoDepth24Support) && (pScreenInfo->depth > 8))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Depth %d is not supported through this adapter.\n",
+ pScreenInfo->depth);
+ return FALSE;
+ }
+
+ /* Pick up XF86Config options */
+ ATIProcessOptions(pScreenInfo, pATI);
+ }
+
+#ifdef AVOID_CPIO
+
+ else /* if (flags & PROBE_DETECT) */
+ return TRUE;
+
+#else /* AVOID_CPIO */
+
+ /*
+ * If there is an ix86-style BIOS, ensure its initialisation entry point
+ * has been executed, and retrieve DDC and VBE information from it.
+ */
+ if (!(pInt10Module = ATILoadModule(pScreenInfo, "int10", ATIint10Symbols)))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to load int10 module.\n");
+ else if (!(pInt10Info = xf86InitInt10(pATI->iEntity)))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to initialise int10 interface.\n");
+ else
+ {
+ if (!(pDDCModule = ATILoadModule(pScreenInfo, "ddc", ATIddcSymbols)))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to load ddc module.\n");
+ else
+ if (!(pVBEModule = ATILoadModule(pScreenInfo, "vbe", ATIvbeSymbols)))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to load vbe module.\n");
+ else
+ {
+ if ((pVBE = VBEInit(pInt10Info, pATI->iEntity)))
+ {
+ ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule);
+ vbeFree(pVBE);
+ }
+ xf86UnloadSubModule(pVBEModule);
+ }
+
+ if (!(flags & PROBE_DETECT))
+ {
+ /* Validate, then make a private copy of, the initialised BIOS */
+ CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4);
+
+ if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2])
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to correctly retrieve adapter BIOS.\n");
+ else
+ {
+ BIOSSize = pBIOS[2] << 9;
+ if (BIOSSize > BIOS_SIZE)
+ BIOSSize = BIOS_SIZE;
+ (void)memcpy(BIOS, pBIOS, BIOSSize);
+ }
+ }
+ }
+
+ /* De-activate int10 */
+ xf86FreeInt10(pInt10Info);
+ xf86UnloadSubModule(pInt10Module);
+
+ if (flags & PROBE_DETECT)
+ {
+ xf86UnloadSubModule(pDDCModule);
+ return TRUE;
+ }
+
+ if (ConfiguredMonitor)
+ {
+ xf86PrintEDID(ConfiguredMonitor);
+ xf86SetDDCproperties(pScreenInfo, ConfiguredMonitor);
+ }
+
+ /* DDC module is no longer needed at this point */
+ xf86UnloadSubModule(pDDCModule);
+
+#endif /* AVOID_CPIO */
+
+ pATI->Block0Base = 0; /* Might no longer be valid */
+ if ((pVideo = pATI->PCIInfo))
+ {
+ if (pATI->CPIODecoding == BLOCK_IO)
+ pATI->CPIOBase = pVideo->ioBase[1];
+
+ /* Set MMIO address from PCI configuration space, if available */
+ if ((pATI->Block0Base = pVideo->memBase[2]))
+ {
+ if (pATI->Block0Base >= (CARD32)(-1 << pVideo->size[2]))
+ pATI->Block0Base = 0;
+ else
+ pATI->Block0Base += 0x0400U;
+ }
+ }
+
+#ifdef AVOID_CPIO
+
+ pScreenInfo->racMemFlags =
+ RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
+
+#else /* AVOID_CPIO */
+
+ pScreenInfo->racIoFlags =
+ RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
+ pScreenInfo->racMemFlags = RAC_FB | RAC_CURSOR;
+
+#endif /* AVOID_CPIO */
+
+ /* Deal with ChipID & ChipRev overrides */
+ if (pGDev->chipID >= 0)
+ {
+ ATIChipType Chip;
+
+ Chip = ATIChipID(pGDev->chipID,
+ (pGDev->chipRev < 0) ? pATI->ChipRev : pGDev->chipRev);
+ if (Chip != pATI->Chip)
+ {
+ pATI->Chip = Chip;
+ pATI->ChipType = pGDev->chipID;
+ if (pGDev->chipRev < 0)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
+ "Driver messages reflect ChipID 0x%04X override.\n",
+ pATI->ChipType);
+ }
+ else
+ {
+ pATI->ChipRev = pGDev->chipRev;
+ pATI->ChipVersion = GetBits(pATI->ChipRev,
+ GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV));
+ pATI->ChipFoundry = GetBits(pATI->ChipRev,
+ GetBits(CFG_CHIP_FOUNDRY, CFG_CHIP_REV));
+ pATI->ChipRevision = GetBits(pATI->ChipRev,
+ GetBits(CFG_CHIP_REVISION, CFG_CHIP_REV));
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
+ "Driver messages reflect ChipID 0x%04X and ChipRev 0x%02X"
+ " overrides.\n", pATI->ChipType, pATI->ChipRev);
+ }
+ }
+ }
+
+ /* Finish private area initialisation */
+ pATI->DAC = ATI_DAC_GENERIC;
+
+#ifndef AVOID_CPIO
+
+ pATI->NewHW.SetBank = ATIx8800SetBank;
+ pATI->BankInfo.SetSourceBank = ATIx8800SetRead;
+ pATI->BankInfo.SetDestinationBank = ATIx8800SetWrite;
+ pATI->BankInfo.SetSourceAndDestinationBanks = ATIx8800SetReadWrite;
+ pATI->BankInfo.BankSize = 0x00010000U; /* 64kB */
+
+#endif /* AVOID_CPIO */
+
+ pATI->LCDPanelID = -1;
+ pATI->nFIFOEntries = 16; /* For now */
+
+ /* Finish probing the adapter */
+ switch (pATI->Adapter)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_ADAPTER_NONE:
+ case ATI_ADAPTER_EGA:
+ case ATI_ADAPTER_EGA_PLUS:
+ case ATI_ADAPTER_VGA:
+ case ATI_ADAPTER_BASIC:
+ pATI->NewHW.SetBank = (ATIBankProcPtr)NoopDDA;
+ pATI->BankInfo.SetSourceBank =
+ pATI->BankInfo.SetDestinationBank =
+ pATI->BankInfo.SetSourceAndDestinationBanks =
+ (miBankProcPtr)NoopDDA;
+ break;
+
+ case ATI_ADAPTER_V3:
+ pATI->NewHW.SetBank = ATIV3SetBank;
+ pATI->BankInfo.SetSourceBank = ATIV3SetRead;
+ pATI->BankInfo.SetDestinationBank = ATIV3SetWrite;
+ pATI->BankInfo.SetSourceAndDestinationBanks = ATIV3SetReadWrite;
+ break;
+
+ case ATI_ADAPTER_V4:
+ case ATI_ADAPTER_V5:
+ pATI->NewHW.SetBank = ATIV4V5SetBank;
+ pATI->BankInfo.SetSourceBank = ATIV4V5SetRead;
+ pATI->BankInfo.SetDestinationBank = ATIV4V5SetWrite;
+ pATI->BankInfo.SetSourceAndDestinationBanks = ATIV4V5SetReadWrite;
+ break;
+
+ case ATI_ADAPTER_XL:
+ pATI->DAC = ATI_DAC_SC11483;
+ break;
+
+ case ATI_ADAPTER_8514A:
+ pATI->VideoRAM =
+ videoRamSizes[GetBits(inw(SUBSYS_STAT), _8PLANE) + 2];
+ break;
+
+ case ATI_ADAPTER_MACH8:
+ pATI->VideoRAM =
+ videoRamSizes[GetBits(inw(CONFIG_STATUS_1), MEM_INSTALLED) + 2];
+ break;
+
+ case ATI_ADAPTER_MACH32:
+ IOValue = inw(CONFIG_STATUS_1);
+ pATI->DAC = ATI_DAC(GetBits(IOValue, DACTYPE), 0);
+ pATI->MemoryType = GetBits(IOValue, MEM_TYPE);
+
+ IOValue = inw(MISC_OPTIONS);
+ pATI->VideoRAM =
+ videoRamSizes[GetBits(IOValue, MEM_SIZE_ALIAS) + 2];
+
+ /*
+ * The 68800-6 doesn't necessarily report the correct video memory
+ * size.
+ */
+ if ((pATI->Chip == ATI_CHIP_68800_6) && (pATI->VideoRAM == 1024))
+ pATI->VideoRAM = ATIMach32videoRam();
+
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_ADAPTER_MACH64:
+ do
+ {
+ /*
+ * Find and mmap() MMIO area. Allow only auxiliary aperture if
+ * it exists.
+ */
+ if (!(Block0Base = pATI->Block0Base))
+ {
+ if (pVideo)
+ {
+ /* Check tail end of linear (8MB or 4MB) aperture */
+ if ((pATI->Block0Base = pVideo->memBase[0]))
+ {
+ pATI->Block0Base += 0x007FFC00U;
+ ATIMapMach64(pScreenInfo->scrnIndex, pATI);
+ if (pATI->pBlock[0])
+ break;
+
+ pATI->Block0Base -= 0x00400000U;
+ ATIMapMach64(pScreenInfo->scrnIndex, pATI);
+ if (pATI->pBlock[0])
+ break;
+ }
+ }
+
+ /* Check VGA MMIO aperture */
+ pATI->Block0Base = 0x000BFC00U;
+ }
+
+ ATIMapMach64(pScreenInfo->scrnIndex, pATI);
+ } while (0);
+ pATI->Block0Base = Block0Base;
+
+#ifdef AVOID_CPIO
+
+ if (!pATI->pBlock[0])
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Unable to mmap() adapter registers.\n");
+ return FALSE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+ if (!(pATIHW->crtc_gen_cntl & CRTC_EN) &&
+ (pATI->Chip >= ATI_CHIP_264CT))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Adapter has not been initialised.\n");
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+#ifdef AVOID_CPIO
+
+ if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Adapters found to be in VGA mode on server entry are not"
+ " supported by the MMIO-only version of this driver.\n");
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ pATIHW->mem_cntl = inr(MEM_CNTL);
+ if (pATI->Chip < ATI_CHIP_264VTB)
+ pATI->VideoRAM =
+ videoRamSizes[GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE) + 2];
+ else
+ {
+ pATI->nFIFOEntries = /* Don't care */
+ (unsigned int)(-1) >> 1;
+
+ IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZEB);
+ if (IOValue < 8)
+ pATI->VideoRAM = (IOValue + 1) * 512;
+ else if (IOValue < 12)
+ pATI->VideoRAM = (IOValue - 3) * 1024;
+ else
+ pATI->VideoRAM = (IOValue - 7) * 2048;
+ }
+
+ pATI->DAC = GetBits(inr(DAC_CNTL), DAC_TYPE);
+
+ IOValue = inr(CONFIG_STATUS64_0);
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T);
+
+ /* Get LCD panel id and set LCD & TV I/O port numbers */
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
+
+ pATIHW->horz_stretching = inr(HORZ_STRETCHING);
+ pATIHW->vert_stretching = inr(VERT_STRETCHING);
+ pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+ }
+ else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY))
+ {
+ pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
+
+ pATIHW->lcd_index = inr(LCD_INDEX);
+ pATIHW->horz_stretching =
+ ATIGetMach64LCDReg(LCD_HORZ_STRETCHING);
+ pATI->LCDHorizontal =
+ GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE);
+ if (pATI->LCDHorizontal)
+ {
+ if (pATI->LCDHorizontal == MaxBits(HORZ_PANEL_SIZE))
+ pATI->LCDHorizontal = 0;
+ else
+ pATI->LCDHorizontal =
+ (pATI->LCDHorizontal + 1) << 3;
+ }
+ pATIHW->ext_vert_stretch =
+ ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH);
+ pATI->LCDVertical =
+ GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE);
+ if (pATI->LCDVertical)
+ {
+ if (pATI->LCDVertical == MaxBits(VERT_PANEL_SIZE))
+ pATI->LCDVertical = 0;
+ else
+ pATI->LCDVertical++;
+ }
+ pATIHW->vert_stretching =
+ ATIGetMach64LCDReg(LCD_VERT_STRETCHING);
+ pATIHW->lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+ outr(LCD_INDEX, pATIHW->lcd_index);
+ }
+
+ /*
+ * Don't bother with panel support if it hasn't been previously
+ * enabled.
+ */
+ if ((pATI->LCDPanelID >= 0) &&
+ !(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
+ !(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
+ !(pATIHW->lcd_gen_ctrl & LCD_ON))
+ {
+ /*
+ * At this point, if an XL or Mobility BIOS hasn't set
+ * panel dimensions, then there is no panel. Otherwise,
+ * keep any panel disabled to allow for modes greater than
+ * the panel's dimensions.
+ */
+ if ((pATI->Chip >= ATI_CHIP_264XL) &&
+ (!pATI->LCDHorizontal || !pATI->LCDVertical))
+ pATI->LCDPanelID = -1;
+ else
+ pATI->OptionPanelDisplay = FALSE;
+ }
+ }
+ else
+ {
+ pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE);
+
+ /* Factor in what the BIOS says the DAC is */
+ pATI->DAC = ATI_DAC(pATI->DAC,
+ GetBits(inr(SCRATCH_REG1), BIOS_INIT_DAC_SUBTYPE));
+ }
+
+ /*
+ * RAMDAC types 0 & 1 for Mach64's are different than those for
+ * Mach32's.
+ */
+ if (pATI->DAC < ATI_DAC_ATI68875)
+ pATI->DAC += ATI_DAC_INTERNAL;
+
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * For Mach64 adapters, pick up, from the BIOS, the type of programmable
+ * clock generator (if any), and various information about it.
+ */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+ CARD16 ClockDac;
+
+ /* Set up non-zero defaults */
+ pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_FIXED];
+ pATI->ClockNumberToProgramme = -1;
+
+ ROMTable = BIOSWord(0x48U);
+ if ((ROMTable + 0x12U) > BIOSSize)
+ ROMTable = 0;
+
+ if (ROMTable > 0)
+ {
+ ClockTable = BIOSWord(ROMTable + 0x10U);
+ if ((ClockTable + 0x20U) > BIOSSize)
+ ClockTable = 0;
+ }
+
+ if (ClockTable > 0)
+ {
+ FrequencyTable = BIOSWord(ClockTable - 0x02U);
+ if ((FrequencyTable > 0) &&
+ ((FrequencyTable + 0x20U) <= BIOSSize))
+ {
+ for (i = 0; i < 16; i++)
+ {
+ pATI->BIOSClocks[i] = BIOSWord(FrequencyTable);
+ FrequencyTable += 2;
+ }
+ }
+ pATI->ProgrammableClock = BIOSByte(ClockTable);
+ pATI->ClockNumberToProgramme = BIOSByte(ClockTable + 0x06U);
+ switch (BIOSWord(ClockTable + 0x08U) / 10)
+ {
+ case 143:
+ pATI->ReferenceNumerator = 157500;
+ pATI->ReferenceDenominator = 11;
+ break;
+
+ case 286:
+ pATI->ReferenceNumerator = 315000;
+ pATI->ReferenceDenominator = 11;
+ break;
+
+ default:
+ pATI->ReferenceNumerator =
+ BIOSWord(ClockTable + 0x08U) * 10;
+ pATI->ReferenceDenominator = 1;
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * Compensate for BIOS absence. Note that the reference
+ * frequency has already been set by option processing.
+ */
+ if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
+ pATI->ProgrammableClock = ATI_CLOCK_INTERNAL;
+ else switch (pATI->DAC)
+ {
+ case ATI_DAC_STG1703:
+ pATI->ProgrammableClock = ATI_CLOCK_STG1703;
+ break;
+
+ case ATI_DAC_CH8398:
+ pATI->ProgrammableClock = ATI_CLOCK_CH8398;
+ break;
+
+ case ATI_DAC_ATT20C408:
+ pATI->ProgrammableClock = ATI_CLOCK_ATT20C408;
+ break;
+
+ case ATI_DAC_IBMRGB514:
+ pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
+ break;
+
+ default: /* Provisional */
+ pATI->ProgrammableClock = ATI_CLOCK_ICS2595;
+ break;
+ }
+
+ /* This should be safe for all generators except IBM's RGB514 */
+ pATI->ClockNumberToProgramme = 3;
+ }
+
+ if ((pATI->ProgrammableClock > ATI_CLOCK_FIXED) &&
+ (pATI->ProgrammableClock < ATI_CLOCK_MAX))
+ {
+ /*
+ * Graphics PRO TURBO 1600's are unusual in that an ICS2595 is used
+ * to generate clocks for VGA modes, and an IBM RGB514 is used for
+ * accelerator modes.
+ */
+ if ((pATI->ProgrammableClock == ATI_CLOCK_ICS2595) &&
+ (pATI->DAC == ATI_DAC_IBMRGB514) &&
+ (pScreenInfo->depth >= 8) &&
+ (pATI->Chipset == ATI_CHIPSET_ATI))
+ pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
+
+ pATI->ClockDescriptor =
+ ATIClockDescriptors[pATI->ProgrammableClock];
+ }
+
+ ClockDac = pATI->DAC;
+ switch (pATI->ProgrammableClock)
+ {
+ case ATI_CLOCK_ICS2595:
+ /*
+ * Pick up reference divider (43 or 46) appropriate to the chip
+ * revision level.
+ */
+ if (ClockTable > 0)
+ pATI->ClockDescriptor.MinM =
+ pATI->ClockDescriptor.MaxM =
+ BIOSWord(ClockTable + 0x0AU);
+ else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-0"))
+ pATI->ClockDescriptor.MinM =
+ pATI->ClockDescriptor.MaxM = 43;
+ else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-1"))
+ pATI->ClockDescriptor.MinM =
+ pATI->ClockDescriptor.MaxM = 46;
+ else
+ pATI->ProgrammableClock = ATI_CLOCK_UNKNOWN;
+ break;
+
+ case ATI_CLOCK_STG1703:
+ /* This one's also a RAMDAC */
+ ClockDac = ATI_DAC_STG1703;
+ break;
+
+ case ATI_CLOCK_CH8398:
+ /* This one's also a RAMDAC */
+ ClockDac = ATI_DAC_CH8398;
+ break;
+
+ case ATI_CLOCK_INTERNAL:
+ /*
+ * The reference divider has already been programmed by BIOS
+ * initialisation. Because, there is only one reference
+ * divider for all generated frequencies (including MCLK), it
+ * cannot be changed without reprogramming all clocks every
+ * time one of them needs a different reference divider.
+ *
+ * Besides, it's not a good idea to change the reference
+ * divider. BIOS initialisation sets it to a value that
+ * effectively prevents generating frequencies beyond the
+ * graphics controller's tolerance.
+ */
+ pATI->ClockDescriptor.MinM = pATI->ClockDescriptor.MaxM =
+ ATIGetMach64PLLReg(PLL_REF_DIV);
+
+ /* The DAC is also integrated */
+ if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL)
+ ClockDac = ATI_DAC_INTERNAL;
+
+ break;
+
+ case ATI_CLOCK_ATT20C408:
+ /* This one's also a RAMDAC */
+ ClockDac = ATI_DAC_ATT20C408;
+ break;
+
+ case ATI_CLOCK_IBMRGB514:
+ /* This one's also a RAMDAC */
+ ClockDac = ATI_DAC_IBMRGB514;
+ pATI->ClockNumberToProgramme = 7;
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * We now have up to two indications of what RAMDAC the adapter uses.
+ * They should be the same. The following test and corresponding
+ * action are under construction.
+ */
+ if (pATI->DAC != ClockDac)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Mach64 RAMDAC probe discrepancy detected:\n"
+ " DAC=0x%02X; ClockDac=0x%02X.\n",
+ pATI->DAC, ClockDac);
+
+ if (pATI->DAC == ATI_DAC_IBMRGB514)
+ {
+ pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
+ pATI->ClockDescriptor =
+ ATIClockDescriptors[ATI_CLOCK_IBMRGB514];
+ pATI->ClockNumberToProgramme = 7;
+ }
+ else
+ pATI->DAC = ClockDac; /* For now */
+ }
+
+ /* Determine panel dimensions */
+ if (pATI->LCDPanelID >= 0)
+ {
+ LCDTable = BIOSWord(0x78U);
+ if ((LCDTable + BIOSByte(LCDTable + 5)) > BIOSSize)
+ LCDTable = 0;
+
+ if (LCDTable > 0)
+ {
+ LCDPanelInfo = BIOSWord(LCDTable + 0x0AU);
+ if (((LCDPanelInfo + 0x1DU) > BIOSSize) ||
+ ((BIOSByte(LCDPanelInfo) != pATI->LCDPanelID) &&
+ (pATI->LCDPanelID || (BIOSByte(LCDPanelInfo) > 0x1FU) ||
+ (pATI->Chip <= ATI_CHIP_264LTPRO))))
+ LCDPanelInfo = 0;
+ }
+
+ if (!LCDPanelInfo)
+ {
+ /*
+ * Scan BIOS for panel info table.
+ */
+ for (i = 0; i <= (int)(BIOSSize - 0x1DU); i++)
+ {
+ /* Look for panel ID ... */
+ if ((BIOSByte(i) != pATI->LCDPanelID) &&
+ (pATI->LCDPanelID || (BIOSByte(i) > 0x1FU) ||
+ (pATI->Chip <= ATI_CHIP_264LTPRO)))
+ continue;
+
+ /* ... followed by 24-byte panel model name ... */
+ for (j = 0; j < 24; j++)
+ if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU)
+ {
+ i += j;
+ goto NextBIOSByte;
+ }
+
+ /* ... verify panel width ... */
+ if (pATI->LCDHorizontal &&
+ (pATI->LCDHorizontal != BIOSWord(i + 0x19U)))
+ continue;
+
+ /* ... and verify panel height */
+ if (pATI->LCDVertical &&
+ (pATI->LCDVertical != BIOSWord(i + 0x1BU)))
+ continue;
+
+ if (LCDPanelInfo)
+ {
+ /*
+ * More than one possibility, but don't care if all
+ * tables describe panels of the same size.
+ */
+ if ((BIOSByte(LCDPanelInfo + 0x19U) ==
+ BIOSByte(i + 0x19U)) &&
+ (BIOSByte(LCDPanelInfo + 0x1AU) ==
+ BIOSByte(i + 0x1AU)) &&
+ (BIOSByte(LCDPanelInfo + 0x1BU) ==
+ BIOSByte(i + 0x1BU)) &&
+ (BIOSByte(LCDPanelInfo + 0x1CU) ==
+ BIOSByte(i + 0x1CU)))
+ continue;
+
+ LCDPanelInfo = 0;
+ break;
+ }
+
+ LCDPanelInfo = i;
+
+ NextBIOSByte: ;
+ }
+ }
+
+ if (LCDPanelInfo > 0)
+ {
+ pATI->LCDPanelID = BIOSByte(LCDPanelInfo);
+ pATI->LCDHorizontal = BIOSWord(LCDPanelInfo + 0x19U);
+ pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU);
+ }
+ }
+ }
+
+ ATIUnlock(pATI); /* Unlock registers */
+
+#ifndef AVOID_CPIO
+
+ /* Sometimes, the BIOS lies about the chip */
+ if ((pATI->Chip >= ATI_CHIP_28800_4) && (pATI->Chip <= ATI_CHIP_28800_6))
+ {
+ IOValue = GetBits(ATIGetExtReg(0xAAU), 0x0FU) +
+ (ATI_CHIP_28800_4 - 4);
+ if ((IOValue <= ATI_CHIP_28800_6) && (IOValue > pATI->Chip))
+ pATI->Chip = IOValue;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Report what was found */
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s graphics controller detected.\n", ATIChipNames[pATI->Chip]);
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Chip >= ATI_CHIP_68800) && (pATI->Chip != ATI_CHIP_68800_3))
+
+#endif /* AVOID_CPIO */
+
+ {
+ Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X",
+ pATI->ChipType);
+ if (!(pATI->ChipType & ~(CHIP_CODE_0 | CHIP_CODE_1)))
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ " (%c%c)",
+ GetBits(pATI->ChipType, CHIP_CODE_1) + 0x41U,
+ GetBits(pATI->ChipType, CHIP_CODE_0) + 0x41U);
+ else if ((pATI->ChipType & 0x4040U) == 0x4040U)
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ " \"%c%c\"",
+ GetByte(pATI->ChipType, 1), GetByte(pATI->ChipType, 0));
+ if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chip != ATI_CHIP_Mach64))
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ ", version %d, foundry %s",
+ pATI->ChipVersion, ATIFoundryNames[pATI->ChipFoundry]);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s, class %d, revision 0x%02X.\n",
+ Buffer, pATI->ChipClass, pATI->ChipRevision);
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH8)
+
+#endif /* AVOID_CPIO */
+
+ {
+ Message = Buffer + snprintf(Buffer, SizeOf(Buffer),
+ "%s bus interface detected", ATIBusNames[pATI->BusType]);
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH64)
+
+ {
+ Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
+ "; %s I/O base is 0x%04lX",
+ (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block",
+ pATI->CPIOBase);
+ }
+
+#endif /* AVOID_CPIO */
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->CPIO_VGAWonder)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "VGA Wonder registers at I/O port 0x%04X.\n",
+ pATI->CPIO_VGAWonder);
+
+ if (pATI->Coprocessor != ATI_CHIP_NONE)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s graphics accelerator detected,\n with %d kB of coprocessor"
+ " memory.\n",
+ ATIChipNames[pATI->Coprocessor], pATI->VideoRAM);
+
+#endif /* AVOID_CPIO */
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s adapter detected.\n", ATIAdapterNames[pATI->Adapter]);
+
+ if (pATI->Chip >= ATI_CHIP_264GT)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "For information on using the multimedia capabilities\n of this"
+ " adapter, please see http://gatos.sf.net.\n");
+
+ if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU);
+ else
+ {
+ const SymTabRec *DAC;
+
+ for (DAC = ATIDACDescriptors; ; DAC++)
+ {
+ if (pATI->DAC == DAC->token)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%s RAMDAC detected.\n", DAC->name);
+ break;
+ }
+
+ if (pATI->DAC < DAC->token)
+ {
+ xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
+ "Unknown RAMDAC type 0x%02X detected.\n", pATI->DAC);
+ break;
+ }
+ }
+ }
+
+#ifdef AVOID_CPIO
+
+ if (!xf86LinearVidMem())
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "A linear aperture is not available.\n");
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Set colour weights.
+ */
+
+ if (pATI->Chip < ATI_CHIP_264CT)
+ pScreenInfo->rgbBits = 6;
+ else
+ pScreenInfo->rgbBits = 8;
+ pATI->rgbBits = pScreenInfo->rgbBits;
+ if (!xf86SetWeight(pScreenInfo, defaultWeight, defaultWeight))
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ if ((pScreenInfo->depth > 8) &&
+ ((pScreenInfo->weight.red != pScreenInfo->weight.blue) ||
+ (pScreenInfo->weight.red != (CARD32)(pScreenInfo->depth / 3)) ||
+ ((CARD32)pScreenInfo->depth != (pScreenInfo->weight.red +
+ pScreenInfo->weight.green +
+ pScreenInfo->weight.blue))))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Driver does not support weight %d%d%d for depth %d.\n",
+ pScreenInfo->weight.red, pScreenInfo->weight.green,
+ pScreenInfo->weight.blue, pScreenInfo->depth);
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ /*
+ * Set default visual.
+ */
+
+ if (!xf86SetDefaultVisual(pScreenInfo, -1))
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ if ((pScreenInfo->depth > 8) &&
+ (((pScreenInfo->defaultVisual | DynamicClass) != DirectColor) ||
+ ((pScreenInfo->defaultVisual == DirectColor) &&
+ (pATI->DAC == ATI_DAC_INTERNAL))))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Driver does not support default visual %s for depth %d.\n",
+ xf86GetVisualName(pScreenInfo->defaultVisual),
+ pScreenInfo->depth);
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ /*
+ * Set colour gamma.
+ */
+
+#ifndef AVOID_CPIO
+
+ if (pScreenInfo->depth > 1)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (!xf86SetGamma(pScreenInfo, defaultGamma))
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+ }
+
+ pATI->depth = pScreenInfo->depth;
+ pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
+ pATI->weight = pScreenInfo->weight;
+ pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
+
+ /*
+ * Determine which CRT controller to use for video modes.
+ */
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Chip >= ATI_CHIP_88800GXC) &&
+ (pATI->depth >= 8) &&
+ (pATI->Chipset == ATI_CHIPSET_ATI))
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->NewHW.crtc = ATI_CRTC_MACH64;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using Mach64 accelerator CRTC.\n");
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /*
+ * No need for VGA I/O resources during operating state (but they
+ * are still decoded).
+ */
+ pResources =
+ xf86SetOperatingState(resVgaIo, pATI->iEntity, ResUnusedOpr);
+ if (pResources)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Logic error setting operating state for VGA I/O.\n");
+ xf86FreeResList(pResources);
+ }
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ pResources = xf86SetOperatingState(pATI->VGAWonderResources,
+ pATI->iEntity, ResUnusedOpr);
+ if (pResources)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Logic error setting operating state for"
+ " VGAWonder I/O.\n");
+ xf86FreeResList(pResources);
+ }
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ }
+
+#ifndef AVOID_CPIO
+
+ else
+ {
+ pATI->NewHW.crtc = ATI_CRTC_VGA;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using VGA CRTC.\n");
+ }
+
+ /* Complain if VGA is needed but not there */
+ if ((pATI->NewHW.crtc == ATI_CRTC_VGA) || !pATI->OptionLinear)
+ {
+ /* VGA is required at this point */
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "VGA is not available through this adapter.\n");
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ if (pATI->Coprocessor != ATI_CHIP_NONE)
+ {
+ /* Ignore any 8514/A or Mach8 accelerator from this point on */
+ pATI->Adapter = pATI->VGAAdapter;
+
+ /* Accelerator and VGA cannot share memory */
+ pATI->VideoRAM = 0;
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Decide between the CRT and the panel.
+ */
+ if (pATI->LCDPanelID >= 0)
+ {
+ if (!pATI->OptionPanelDisplay)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
+ "Using CRT interface and disabling digital flat panel.\n");
+ }
+ else
+ {
+ int HDisplay, VDisplay;
+ CARD8 ClockMask, PostMask;
+
+ /*
+ * Determine porch data. The following is inaccurate (but still
+ * good enough) when BIOS initialisation has set things up so that
+ * the registers read here are not the ones actually in use by the
+ * panel. Thus, a further refinement here would be to flip back
+ * and forth between shadow and non-shadow registers as dictated by
+ * the various LCD_GEN_CNTL and CONFIG_PANEL bits involved.
+ *
+ * This groks the mode on entry to extract the width and position
+ * of its sync and blanking pulses, and considers any overscan as
+ * part of the displayed area, given that the overscan is also
+ * stretched.
+ *
+ * This also attempts to determine panel dimensions but cannot do
+ * so for one that is "auto-stretched".
+ */
+
+#ifndef AVOID_CPIO
+
+ if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ {
+ pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2;
+
+ pATIHW->crt[0] = GetReg(CRTX(pATI->CPIO_VGABase), 0x00U);
+ pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
+ pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
+ pATIHW->crt[4] = GetReg(CRTX(pATI->CPIO_VGABase), 0x04U);
+ pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
+ pATIHW->crt[6] = GetReg(CRTX(pATI->CPIO_VGABase), 0x06U);
+ pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
+ pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
+ pATIHW->crt[16] = GetReg(CRTX(pATI->CPIO_VGABase), 0x10U);
+ pATIHW->crt[17] = GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
+ pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
+ pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
+
+ pATI->LCDHSyncWidth =
+ (pATIHW->crt[5] - pATIHW->crt[4]) & 0x1FU;
+ pATI->LCDHBlankWidth = (((pATIHW->crt[3] & 0x1FU) |
+ ((pATIHW->crt[5] >> 2) & 0x20U)) -
+ pATIHW->crt[2]) & 0x3FU;
+ pATI->LCDVSyncWidth =
+ (pATIHW->crt[17] - pATIHW->crt[16]) & 0x0FU;
+ pATI->LCDVBlankWidth =
+ ((pATIHW->crt[22] - pATIHW->crt[21]) & 0xFFU) + 1;
+
+ pATI->LCDHSyncStart =
+ ((pATIHW->crt[4] - pATIHW->crt[2]) & 0xFFU) + 1;
+ pATI->LCDVSyncStart = (((((pATIHW->crt[7] << 2) & 0x0200U) |
+ ((pATIHW->crt[7] << 6) & 0x0100U) |
+ pATIHW->crt[16]) -
+ (((pATIHW->crt[9] << 4) & 0x0200U) |
+ ((pATIHW->crt[7] << 5) & 0x0100U) |
+ pATIHW->crt[21])) & 0xFFU) + 1;
+
+ HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth -
+ pATI->LCDHBlankWidth;
+ if (HDisplay > 0)
+ pATI->LCDHBlankWidth += (HDisplay + 0x3FU) & ~0x3FU;
+ VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth -
+ pATI->LCDVBlankWidth;
+ if (VDisplay > 0)
+ pATI->LCDVBlankWidth += (VDisplay + 0xFFU) & ~0xFFU;
+
+ HDisplay = pATIHW->crt[0] + 5 - pATI->LCDHBlankWidth;
+ VDisplay = (((pATIHW->crt[7] << 4) & 0x0200U) |
+ ((pATIHW->crt[7] << 8) & 0x0100U) |
+ pATIHW->crt[6]) + 3 - pATI->LCDVBlankWidth;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->clock = inr(CLOCK_CNTL) & 0x03U;
+
+ pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
+ pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
+ pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
+ pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
+ pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
+ pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
+
+ HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) +
+ GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) +
+ GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT);
+ VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP) +
+ GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_TOP) +
+ GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_BOTTOM);
+
+ pATI->LCDHSyncStart =
+ (GetBits(pATIHW->crtc_h_sync_strt_wid,
+ CRTC_H_SYNC_STRT_HI) *
+ (MaxBits(CRTC_H_SYNC_STRT) + 1)) +
+ GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT) -
+ HDisplay;
+ pATI->LCDHSyncWidth =
+ GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
+ pATI->LCDHBlankWidth =
+ GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL) -
+ HDisplay;
+ pATI->LCDVSyncStart =
+ GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT) -
+ VDisplay;
+ pATI->LCDVSyncWidth =
+ GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID);
+ pATI->LCDVBlankWidth =
+ GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL) -
+ VDisplay;
+
+ HDisplay++;
+ VDisplay++;
+ }
+
+ HDisplay <<= 3;
+ pATI->LCDHSyncStart <<= 3;
+ pATI->LCDHSyncWidth <<= 3;
+ pATI->LCDHBlankWidth <<= 3;
+
+ /* Calculate panel dimensions implied by the input timing */
+ if ((pATIHW->horz_stretching &
+ (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) ==
+ HORZ_STRETCH_EN)
+ {
+ if (pATIHW->horz_stretching & HORZ_STRETCH_MODE)
+ {
+ if (pATIHW->horz_stretching & HORZ_STRETCH_BLEND)
+ {
+ HDisplay =
+ (HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) /
+ GetBits(pATIHW->horz_stretching,
+ HORZ_STRETCH_BLEND);
+ }
+ }
+ else if (((pATIHW->horz_stretching & HORZ_STRETCH_LOOP) >
+ HORZ_STRETCH_LOOP15) ||
+ (pATIHW->horz_stretching &
+ SetBits(1, HORZ_STRETCH_RATIO)))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Ignoring invalid horizontal stretch ratio in mode on"
+ " server entry.\n");
+ }
+ else
+ {
+ IOValue =
+ GetBits(pATIHW->horz_stretching, HORZ_STRETCH_RATIO);
+
+ switch (GetBits(pATIHW->horz_stretching,
+ HORZ_STRETCH_LOOP))
+ {
+ case GetBits(HORZ_STRETCH_LOOP09, HORZ_STRETCH_LOOP):
+ i = 9;
+ IOValue &= (1 << 9) - 1;
+ break;
+
+ case GetBits(HORZ_STRETCH_LOOP11, HORZ_STRETCH_LOOP):
+ i = 11;
+ IOValue &= (1 << 11) - 1;
+ break;
+
+ case GetBits(HORZ_STRETCH_LOOP12, HORZ_STRETCH_LOOP):
+ i = 12;
+ IOValue &= (1 << 12) - 1;
+ break;
+
+ case GetBits(HORZ_STRETCH_LOOP14, HORZ_STRETCH_LOOP):
+ i = 14;
+ IOValue &= (1 << 14) - 1;
+ break;
+
+ case GetBits(HORZ_STRETCH_LOOP15, HORZ_STRETCH_LOOP):
+ default: /* Muffle compiler */
+ i = 15;
+ IOValue &= (1 << 15) - 1;
+ break;
+ }
+
+ if (IOValue)
+ {
+ /* Count the number of bits in IOValue */
+ j = (IOValue >> 1) & 0x36DBU;
+ j = IOValue - j - ((j >> 1) & 0x36DBU);
+ j = ((j + (j >> 3)) & 0x71C7U) % 0x3FU;
+
+ HDisplay = (HDisplay * i) / j;
+ }
+ }
+ }
+
+ if ((pATIHW->vert_stretching & VERT_STRETCH_EN) &&
+ !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
+ {
+ if ((pATIHW->vert_stretching & VERT_STRETCH_USE0) ||
+ (VDisplay <= 350))
+ IOValue =
+ GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO0);
+ else if (VDisplay <= 400)
+ IOValue =
+ GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO1);
+ else if ((VDisplay <= 480) ||
+ !(pATIHW->ext_vert_stretch & VERT_STRETCH_RATIO3))
+ IOValue =
+ GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO2);
+ else
+ IOValue =
+ GetBits(pATIHW->ext_vert_stretch, VERT_STRETCH_RATIO3);
+
+ if (IOValue)
+ VDisplay =
+ (VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) /
+ IOValue;
+ }
+
+ /* Match calculated dimensions to probed dimensions */
+ if (!pATI->LCDHorizontal)
+ {
+ if ((pATIHW->horz_stretching &
+ (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
+ (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
+ pATI->LCDHorizontal = HDisplay;
+ }
+ else if (pATI->LCDHorizontal != HDisplay)
+ {
+ if ((pATIHW->horz_stretching &
+ (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
+ (HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Inconsistent panel horizontal dimension:"
+ " %d and %d.\n", pATI->LCDHorizontal, HDisplay);
+ HDisplay = pATI->LCDHorizontal;
+ }
+
+ if (!pATI->LCDVertical)
+ {
+ if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
+ !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
+ pATI->LCDVertical = VDisplay;
+ }
+ else if (pATI->LCDVertical != VDisplay)
+ {
+ if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
+ !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Inconsistent panel vertical dimension: %d and %d.\n",
+ pATI->LCDVertical, VDisplay);
+ VDisplay = pATI->LCDVertical;
+ }
+
+ if (!pATI->LCDHorizontal || !pATI->LCDVertical)
+ {
+ if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Unable to determine dimensions of panel (ID %d).\n",
+ pATI->LCDPanelID);
+ else
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Unable to determine dimensions of panel.\n");
+
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ /* If the mode on entry wasn't stretched, adjust timings */
+ if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
+ ((HDisplay = pATI->LCDHorizontal - HDisplay) > 0))
+ {
+ pATI->LCDHSyncStart -= HDisplay;
+ if (pATI->LCDHSyncStart < 0)
+ pATI->LCDHSyncStart = 0;
+ pATI->LCDHBlankWidth -= HDisplay;
+ HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth;
+ if (pATI->LCDHBlankWidth < HDisplay)
+ pATI->LCDHBlankWidth = HDisplay;
+ }
+
+ if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
+ ((VDisplay = pATI->LCDVertical - VDisplay) > 0))
+ {
+ pATI->LCDVSyncStart -= VDisplay;
+ if (pATI->LCDVSyncStart < 0)
+ pATI->LCDVSyncStart = 0;
+ pATI->LCDVBlankWidth -= VDisplay;
+ VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth;
+ if (pATI->LCDVBlankWidth < VDisplay)
+ pATI->LCDVBlankWidth = VDisplay;
+ }
+
+ if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%dx%d panel (ID %d) detected.\n",
+ pATI->LCDHorizontal, pATI->LCDVertical, pATI->LCDPanelID);
+ else
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "%dx%d panel detected.\n",
+ pATI->LCDHorizontal, pATI->LCDVertical);
+
+ if (LCDPanelInfo)
+ {
+ for (i = 0; i < 24; i++)
+ Buffer[i] = BIOSByte(LCDPanelInfo + 1 + i);
+ for (; --i >= 0; )
+ if (Buffer[i] && Buffer[i] != ' ')
+ {
+ Buffer[i + 1] = '\0';
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "Panel model %s.\n", Buffer);
+ break;
+ }
+ }
+
+ /*
+ * Determine panel clock. This must be done after option
+ * processing so that the adapter's reference frequency is always
+ * available.
+ *
+ * Get post divider. A GCC bug has caused the following expression
+ * to be broken down into its individual components.
+ */
+ ClockMask = PLL_VCLK0_XDIV << pATIHW->clock;
+ PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2);
+ i = GetBits(ATIGetMach64PLLReg(PLL_XCLK_CNTL), ClockMask);
+ i *= MaxBits(PLL_VCLK0_POST_DIV) + 1;
+ i |= GetBits(ATIGetMach64PLLReg(PLL_VCLK_POST_DIV), PostMask);
+
+ /* Calculate clock of mode on entry */
+ Numerator = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) *
+ pATI->ReferenceNumerator;
+ Denominator = pATI->ClockDescriptor.MinM *
+ pATI->ReferenceDenominator *
+ pATI->ClockDescriptor.PostDividers[i];
+ pATI->LCDClock = ATIDivide(Numerator, Denominator, 1, 0);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
+ "Panel clock is %.3f MHz.\n",
+ (double)(pATI->LCDClock) / 1000.0);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using digital flat panel interface%s.\n",
+ pATI->OptionCRTDisplay ?
+ " to display on both CRT and panel" : "");
+ }
+ }
+
+ /*
+ * Finish detecting video RAM size.
+ */
+ pScreenInfo->videoRam = pATI->VideoRAM;
+
+#ifndef AVOID_CPIO
+
+ AcceleratorVideoRAM = pScreenInfo->videoRam;
+ if (pATI->Chip == ATI_CHIP_VGA)
+ {
+ if (pATI->depth <= 4)
+ VGAVideoRAM = 256;
+ else
+ VGAVideoRAM = 64;
+
+ /* For VGA, allow a lower override */
+ if ((pGDev->videoRam > 0) && (pGDev->videoRam < VGAVideoRAM))
+ VGAVideoRAM = pGDev->videoRam;
+ }
+ else if (pATI->CPIO_VGAWonder)
+ {
+ /*
+ * XXX There's an assumption here that the values retrieved are those
+ * set by BIOS initialisation.
+ */
+ if (pATI->Chip <= ATI_CHIP_18800_1)
+ {
+ VGAVideoRAM =
+ videoRamSizes[GetBits(ATIGetExtReg(0xBBU), 0x20U) + 1];
+ if (AcceleratorVideoRAM > 512)
+ AcceleratorVideoRAM = 512;
+ }
+ else
+ {
+ IOValue = ATIGetExtReg(0xB0U);
+ if (IOValue & 0x08U)
+ VGAVideoRAM = 1024;
+ else if (IOValue & 0x10U)
+ VGAVideoRAM = 512;
+ else
+ VGAVideoRAM = 256;
+ if (AcceleratorVideoRAM > 1024)
+ AcceleratorVideoRAM = 1024;
+ }
+ }
+
+ /* Check for hardware limitations */
+ if (!AcceleratorVideoRAM)
+ {
+ pScreenInfo->videoRam = pATI->VideoRAM = VGAVideoRAM;
+
+ /*
+ * VGA Wonder V3's, V4's and V5's don't appear to support banking in
+ * planar modes.
+ */
+ if ((pATI->depth <= 4) &&
+ (pATI->Chip <= ATI_CHIP_18800_1) &&
+ (VGAVideoRAM > 256))
+ {
+ if (pATI->OptionDevel)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Virtual resolutions requiring more than %s kB\n of video"
+ " memory might not function properly.\n",
+ (pATI->depth == 1) ? "64" : "256");
+ }
+ else
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "VideoRAM reduced to 256 kB due to hardware"
+ " limitations.\n");
+ pScreenInfo->videoRam = 256;
+ }
+ }
+ }
+ else if ((pATI->NewHW.crtc == ATI_CRTC_MACH64) ||
+ (pATI->Chip >= ATI_CHIP_264CT))
+
+#endif /* AVOID_CPIO */
+
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth >= 8)
+
+#endif /* AVOID_CPIO */
+
+ {
+ /* Get adapter's linear aperture configuration */
+ pATIHW->config_cntl = inr(CONFIG_CNTL);
+ pATI->LinearBase =
+ GetBits(pATIHW->config_cntl, CFG_MEM_AP_LOC) << 22;
+ if ((pATIHW->config_cntl & CFG_MEM_AP_SIZE) != CFG_MEM_AP_SIZE)
+ {
+ pATI->LinearSize =
+ GetBits(pATIHW->config_cntl, CFG_MEM_AP_SIZE) << 22;
+
+ /*
+ * Linear aperture could have been disabled (but still
+ * assigned) by BIOS initialisation.
+ */
+ if (pATI->LinearBase && !pATI->LinearSize)
+ {
+ if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
+ (pATI->VideoRAM < 4096))
+ pATI->LinearSize = 4 * 1024 * 1024;
+ else
+ pATI->LinearSize = 8 * 1024 * 1024;
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ /* Except for PCI & AGP, allow for user override */
+ if (!pVideo)
+ {
+ if (pATI->Chip == ATI_CHIP_88800CX)
+ IOValue = ~((CARD32)((1 << 23) - 1));
+ else if (pATI->Chip >= ATI_CHIP_88800GXE)
+ IOValue = ~((CARD32)((1 << 24) - 1));
+ else if (pATI->VideoRAM >= 4096)
+ IOValue = ~((CARD32)((1 << 23) - 1));
+ else
+ IOValue = ~((CARD32)((1 << 22) - 1));
+
+ if ((IOValue &= pGDev->MemBase) &&
+ (IOValue <= (MaxBits(CFG_MEM_AP_LOC) << 22)))
+ pATI->LinearBase = IOValue;
+
+ if (!pATI->LinearBase)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Linear aperture not configured. Specify \"MemBase\""
+ " override in XF86Config \"Device\" section.\n");
+ else
+ {
+ if (!pATI->LinearSize)
+ {
+ if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
+ (pATI->VideoRAM < 4096))
+ pATI->LinearSize = 4 * 1024 * 1024;
+ else
+ pATI->LinearSize = 8 * 1024 * 1024;
+ }
+
+ Resources[0].type = ResExcMemBlock | ResBus;
+ Resources[0].rBegin = pATI->LinearBase;
+ Resources[0].rEnd =
+ pATI->LinearBase + pATI->LinearSize - 1;
+ if (xf86RegisterResources(pATI->iEntity, Resources,
+ ResNone))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to register %d MB linear aperture at"
+ " 0x%08X.\n", pATI->LinearSize >> 10,
+ pATI->LinearBase);
+
+ pATI->LinearSize = 0;
+ }
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->LinearBase && pATI->LinearSize)
+ {
+ /*
+ * Unless specified in PCI configuration space, set MMIO
+ * address to tail end of linear aperture.
+ */
+ if (!pATI->Block0Base)
+ {
+ pATI->Block0Base =
+ pATI->LinearBase + pATI->LinearSize - 0x00000400U;
+ pATI->MMIOInLinear = pATI->OptionAccel;
+ }
+
+ AcceleratorVideoRAM = pATI->LinearSize >> 10;
+
+ /*
+ * Account for MMIO area at the tail end of the linear
+ * aperture, if it is needed or if it cannot be disabled.
+ */
+ if (pATI->MMIOInLinear || (pATI->Chip < ATI_CHIP_264VTB))
+ AcceleratorVideoRAM -= 2;
+
+ ServerVideoRAM = pATI->VideoRAM;
+
+ if (pATI->Cursor > ATI_CURSOR_SOFTWARE)
+ {
+ /*
+ * Allocate a 1 kB cursor image area at the top of the
+ * little-endian aperture, just before any MMIO area that
+ * might also be there.
+ */
+ if (ServerVideoRAM > AcceleratorVideoRAM)
+ ServerVideoRAM = AcceleratorVideoRAM;
+
+ ServerVideoRAM--;
+ pATI->CursorOffset = ServerVideoRAM << 10;
+ pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Storing hardware cursor image at 0x%08X.\n",
+ pATI->CursorBase);
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->OptionLinear)
+
+#endif /* AVOID_CPIO */
+
+ {
+ CARD32 PageSize = getpagesize() >> 10;
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+
+ /*
+ * MMIO areas must be mmap()'ed separately to avoid write
+ * combining them. Thus, they might not end up still
+ * adjacent with the little-endian linear aperture after
+ * mmap()'ing. So, round down the linear aperture size to
+ * avoid an overlap. Any hardware cursor image area might
+ * not end up being write combined, but this seems
+ * preferable to further reducing the video memory size
+ * advertised to the server.
+ *
+ * XXX Ideally this should be dealt with in the os-support
+ * layer, i.e., it should be possible to reset a
+ * subarea's write combining after it has been
+ * mmap()'ed, but doing so currently causes the removal
+ * of write combining for the entire aperture.
+ */
+ if (pATI->MMIOInLinear)
+ AcceleratorVideoRAM -= AcceleratorVideoRAM % PageSize;
+
+#else /* if X_BYTE_ORDER != X_LITTLE_ENDIAN */
+
+ /*
+ * Big-endian apertures are 8 MB higher and don't contain
+ * an MMIO area.
+ */
+ pATI->LinearBase += 0x00800000U;
+ AcceleratorVideoRAM = pATI->LinearSize >> 10;
+
+#endif /* X_BYTE_ORDER */
+
+ if (ServerVideoRAM > AcceleratorVideoRAM)
+ ServerVideoRAM = AcceleratorVideoRAM;
+ else if (AcceleratorVideoRAM > pATI->VideoRAM)
+ AcceleratorVideoRAM = pATI->VideoRAM;
+
+ PageSize--;
+ AcceleratorVideoRAM =
+ (AcceleratorVideoRAM + PageSize) & ~PageSize;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using %d MB linear aperture at 0x%08X.\n",
+ pATI->LinearSize >> 20, pATI->LinearBase);
+
+ /* Only mmap what is needed */
+ ApertureSize = pATI->LinearSize =
+ AcceleratorVideoRAM << 10;
+ }
+
+ if (ServerVideoRAM < pATI->VideoRAM)
+ {
+ pScreenInfo->videoRam = ServerVideoRAM;
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Virtual resolutions will be limited to %d kB\n due to"
+ " linear aperture size and/or placement of hardware"
+ " cursor image area.\n",
+ ServerVideoRAM);
+ }
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ /* Set up for a banked aperture */
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ pATI->UseSmallApertures = TRUE;
+
+ /* Set banking functions */
+ if (pATI->depth <= 4)
+ {
+ pATI->NewHW.SetBank = ATIMach64SetBankPlanar;
+ pATI->BankInfo.SetSourceBank = ATIMach64SetReadPlanar;
+ pATI->BankInfo.SetDestinationBank = ATIMach64SetWritePlanar;
+ pATI->BankInfo.SetSourceAndDestinationBanks =
+ ATIMach64SetReadWritePlanar;
+ }
+ else
+ {
+ pATI->NewHW.SetBank = ATIMach64SetBankPacked;
+ pATI->BankInfo.SetSourceBank = ATIMach64SetReadPacked;
+ pATI->BankInfo.SetDestinationBank = ATIMach64SetWritePacked;
+ pATI->BankInfo.SetSourceAndDestinationBanks =
+ ATIMach64SetReadWritePacked;
+ }
+
+ /*
+ * Unless specified in PCI configuration space, or at the top of
+ * of a little-endian linear aperture, set MMIO address to the one
+ * just above the VGA aperture. This does not work on the CT
+ * (maybe others).
+ */
+ if (!pATI->Block0Base &&
+ ((pATI->Chip < ATI_CHIP_264CT) ||
+ (pATI->Chip >= ATI_CHIP_264VT) ||
+ pATI->OptionDevel))
+ pATI->Block0Base = 0x000BFC00U;
+ }
+
+ if (!pATI->OptionLinear)
+ pATI->LinearBase = 0; /* Not needed */
+
+#endif /* AVOID_CPIO */
+
+ if (!pATI->LinearBase || !pATI->LinearSize)
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+
+#endif /* AVOID_CPIO */
+
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "Linear aperture not available.\n");
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+#ifndef AVOID_CPIO
+
+ /* Insurance */
+ pATI->LinearBase = pATI->LinearSize = 0;
+
+#endif /* AVOID_CPIO */
+
+ }
+
+#ifndef AVOID_CPIO
+
+ if (!pATI->OptionAccel)
+ {
+ pATI->Block0Base = 0; /* Not needed */
+ pATI->MMIOInLinear = FALSE;
+ }
+ else
+
+#endif
+
+ if (pATI->Block0Base)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using Block 0 MMIO aperture at 0x%08X.\n", pATI->Block0Base);
+
+ /* Set Block1 MMIO address if supported */
+ if (pATI->Chip >= ATI_CHIP_264VT)
+ {
+ pATI->Block1Base = pATI->Block0Base - 0x00000400U;
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using Block 1 MMIO aperture at 0x%08X.\n",
+ pATI->Block1Base);
+ }
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ else
+ /*
+ * After BIOS initialisation, the accelerator (if any) and the VGA won't
+ * necessarily agree on the amount of video memory, depending on whether or
+ * where the memory boundary is configured. Any discrepancy will be
+ * resolved by ATIModePreInit().
+ *
+ * However, it's possible that there is more video memory than VGA Wonder
+ * can architecturally handle.
+ */
+ if (((pATI->Chip < ATI_CHIP_68800) || (pATI->Chip > ATI_CHIP_68800AX)) &&
+ (AcceleratorVideoRAM < pScreenInfo->videoRam))
+ {
+ if (pATI->OptionDevel)
+ {
+ if (pATI->depth == 1)
+ AcceleratorVideoRAM /= 4;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Virtual resolutions requiring more than %d kB\n of video"
+ " memory might not function correctly.\n",
+ AcceleratorVideoRAM);
+ }
+ else
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "VideoRAM reduced to %d kB due to hardware limitations.\n",
+ AcceleratorVideoRAM);
+
+ pScreenInfo->videoRam = AcceleratorVideoRAM;
+ }
+ }
+
+ if (pATI->OptionLinear)
+ {
+ if (!pATI->LinearBase)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Linear aperture not supported in this configuration.\n");
+ pATI->OptionLinear = FALSE;
+ }
+ else
+ {
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /*
+ * Free VGA memory aperture during operating state (but it is
+ * still decoded).
+ */
+ pResources = xf86SetOperatingState(resVgaMem,
+ pATI->iEntity, ResUnusedOpr);
+ if (pResources)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Logic error setting operating state for VGA memory"
+ " aperture.\n");
+ xf86FreeResList(pResources);
+ }
+ }
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ if ((pATI->Cursor > ATI_CURSOR_SOFTWARE) && !pATI->CursorBase)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unable to store hardware cursor image. Reverting to software"
+ " cursor.\n");
+ pATI->Cursor = ATI_CURSOR_SOFTWARE;
+ }
+
+ /*
+ * Remap apertures. Must lock and re-unlock around this in case the
+ * remapping fails.
+ */
+ ATILock(pATI);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
+ return FALSE;
+
+ ATIUnlock(pATI);
+
+ if (pATI->OptionAccel)
+ {
+
+#ifndef AVOID_CPIO
+
+ if (!pATI->Block0Base || (pATI->NewHW.crtc == ATI_CRTC_VGA))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Acceleration not supported in this configuration.\n");
+ pATI->OptionAccel = FALSE;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "MMIO write caching %sabled.\n",
+ pATI->OptionMMIOCache ? "en" : "dis");
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH32)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ ATIReportMemory(pScreenInfo, pATI,
+ ATIMemoryTypeNames_264xT[pATI->MemoryType]);
+ else if (pATI->Chip == ATI_CHIP_88800CX)
+ ATIReportMemory(pScreenInfo, pATI,
+ ATIMemoryTypeNames_88800CX[pATI->MemoryType]);
+ else
+ ATIReportMemory(pScreenInfo, pATI,
+ ATIMemoryTypeNames_Mach[pATI->MemoryType]);
+ }
+
+#ifndef AVOID_CPIO
+
+ else if (pATI->Adapter >= ATI_ADAPTER_V3)
+ ATIReportMemory(pScreenInfo, pATI,
+ (ATIGetExtReg(0xB7U) & 0x04U) ? "DRAM" : "VRAM");
+ else
+ ATIReportMemory(pScreenInfo, pATI, "video memory");
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Finish banking setup. This needs to be fixed to not assume the mode on
+ * entry is a VGA mode. XXX
+ */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATIHW->crtc = pATI->NewHW.crtc;
+
+#ifndef AVOID_CPIO
+
+ pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
+ pATI->BankInfo.BankSize = 0; /* No banking */
+
+#endif /* AVOID_CPIO */
+
+ }
+
+#ifndef AVOID_CPIO
+
+ else
+ {
+ pATIHW->crtc = ATI_CRTC_VGA;
+#if 0 /* ___NOT_YET___ */
+ if (pATI->ChipHasSUBSYS_CNTL)
+ {
+ }
+ else
+#endif
+ if ((pATI->Chip >= ATI_CHIP_88800GXC) &&
+ (pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ pATIHW->crtc = ATI_CRTC_MACH64;
+
+ if (pATI->depth <= 4)
+ {
+ pATI->BankInfo.nBankDepth = 1;
+ pATI->NewHW.nPlane = 4;
+ }
+ else
+ {
+ pATI->BankInfo.nBankDepth = pATI->depth;
+ pATI->NewHW.nPlane = 1;
+ }
+
+ if ((pATIHW->crtc != ATI_CRTC_VGA) || (GetReg(SEQX, 0x04U) & 0x08U))
+ pATIHW->nPlane = 1;
+ else
+ pATIHW->nPlane = 4;
+
+ pATIHW->nBank = ATIDivide(pATI->VideoRAM,
+ pATIHW->nPlane * pATI->BankInfo.BankSize, 10, 1);
+ pATI->NewHW.nBank = ATIDivide(pATI->VideoRAM,
+ pATI->NewHW.nPlane * pATI->BankInfo.BankSize, 10, 1);
+
+ if (pATI->VGAAdapter == ATI_ADAPTER_VGA)
+ {
+ pATIHW->SetBank = pATI->NewHW.SetBank =
+ (ATIBankProcPtr)NoopDDA;
+ pATIHW->nBank = pATI->NewHW.nBank = 1;
+ }
+ else if (!pATI->UseSmallApertures)
+ pATIHW->SetBank = pATI->NewHW.SetBank;
+ else if ((pATIHW->crtc == ATI_CRTC_VGA) &&
+ !(pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN))
+ {
+ pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
+ pATIHW->nBank = 1;
+ }
+ else if (pATIHW->nPlane == 1)
+ pATIHW->SetBank = ATIMach64SetBankPacked;
+ else
+ pATIHW->SetBank = ATIMach64SetBankPlanar;
+
+ if (((ApertureSize * pATI->depth) / pATI->BankInfo.nBankDepth) >=
+ (unsigned)(pScreenInfo->videoRam * 1024))
+ pATI->BankInfo.BankSize = 0; /* No banking */
+ }
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->OptionShadowFB)
+ {
+ /* Until ShadowFB becomes a true screen wrapper, if it ever does... */
+
+#ifndef AVOID_CPIO
+
+ if (pATI->BankInfo.BankSize)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Cannot shadow a banked frame buffer.\n");
+ pATI->OptionShadowFB = FALSE;
+ }
+ else if (pATI->depth < 8)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Cannot shadow a planar frame buffer.\n");
+ pATI->OptionShadowFB = FALSE;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->OptionAccel)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Cannot shadow an accelerated frame buffer.\n");
+ pATI->OptionShadowFB = FALSE;
+ }
+ else
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Using shadow frame buffer.\n");
+ }
+
+ /* 264VT-B's and later have DSP registers */
+ if ((pATI->Chip >= ATI_CHIP_264VTB) &&
+ !ATIDSPPreInit(pScreenInfo->scrnIndex, pATI))
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ /*
+ * Determine minClock and maxClock. For adapters with supported
+ * programmable clock generators, start with an absolute maximum.
+ */
+ if (pATI->ClockDescriptor.MaxN > 0)
+ {
+ Numerator = pATI->ClockDescriptor.MaxN * pATI->ReferenceNumerator;
+ Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator *
+ pATI->ClockDescriptor.PostDividers[0];
+
+ /*
+ * An integrated PLL behaves as though the reference frequency were
+ * doubled. It also does not appear to care about the colour depth.
+ */
+ if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
+ Numerator <<= 1;
+ else if (pATI->depth > 8)
+ Denominator *= (pATI->bitsPerPixel / 8);
+
+ ATIClockRange.maxClock = (Numerator / (Denominator * 1000)) * 1000;
+
+ Numerator = pATI->ClockDescriptor.MinN * pATI->ReferenceNumerator;
+ Denominator = pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator *
+ pATI->ClockDescriptor.PostDividers[pATI->ClockDescriptor.NumD - 1];
+
+ if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
+ Numerator <<= 1;
+
+ ATIClockRange.minClock = (Numerator / (Denominator * 1000)) * 1000;
+
+ if (pATI->XCLKFeedbackDivider)
+ {
+ /* Possibly reduce maxClock due to memory bandwidth */
+ Numerator = pATI->XCLKFeedbackDivider * 2 *
+ pATI->ReferenceNumerator;
+ Denominator = pATI->ClockDescriptor.MinM *
+ pATI->XCLKReferenceDivider * pATI->ReferenceDenominator;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth >= 8)
+
+#endif /* AVOID_CPIO */
+
+ {
+ Denominator *= pATI->bitsPerPixel / 4;
+ }
+
+ i = (6 - 2) - pATI->XCLKPostDivider;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ i--;
+
+#endif /* AVOID_CPIO */
+
+ i = (ATIDivide(Numerator, Denominator, i, -1) / 1000) * 1000;
+ if (i < ATIClockRange.maxClock)
+ ATIClockRange.maxClock = i;
+ }
+ }
+
+ /*
+ * Assume an internal DAC can handle whatever frequency the internal PLL
+ * can produce (with the reference divider set by BIOS initialisation), but
+ * default maxClock to a lower chip-specific default.
+ */
+ if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
+ {
+ int DacSpeed;
+ switch (pATI->bitsPerPixel)
+ {
+ case 15:
+ case 16:
+ DacSpeed = pGDev->dacSpeeds[DAC_BPP16];
+ break;
+
+ case 24:
+ DacSpeed = pGDev->dacSpeeds[DAC_BPP24];
+ break;
+
+ case 32:
+ DacSpeed = pGDev->dacSpeeds[DAC_BPP32];
+ break;
+
+ default:
+ DacSpeed = 0;
+ break;
+ }
+ if (!DacSpeed)
+ DacSpeed = pGDev->dacSpeeds[DAC_BPP8];
+ if (DacSpeed < ATIClockRange.maxClock)
+ {
+ DefaultmaxClock = 135000;
+
+ if (pATI->depth > 8)
+ DefaultmaxClock = 80000;
+
+ if ((pATI->Chip >= ATI_CHIP_264VTB) &&
+ (pATI->Chip != ATI_CHIP_Mach64))
+ {
+ if ((pATI->Chip >= ATI_CHIP_264VT4) &&
+ (pATI->Chip != ATI_CHIP_264LTPRO))
+ DefaultmaxClock = 230000;
+ else if (pATI->Chip >= ATI_CHIP_264VT3)
+ DefaultmaxClock = 200000;
+ else
+ DefaultmaxClock = 170000;
+ }
+ if (DacSpeed > DefaultmaxClock)
+ ATIClockRange.maxClock = DacSpeed;
+ else if (DefaultmaxClock < ATIClockRange.maxClock)
+ ATIClockRange.maxClock = DefaultmaxClock;
+ }
+ }
+ else
+ {
+ switch(pATI->DAC)
+ {
+ case ATI_DAC_STG1700:
+ case ATI_DAC_STG1702:
+ case ATI_DAC_STG1703:
+ DefaultmaxClock = 110000;
+ break;
+
+ case ATI_DAC_IBMRGB514:
+ pATI->maxClock = 220000;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ DefaultmaxClock = 100000;
+ else
+
+#endif /* AVOID_CPIO */
+
+ DefaultmaxClock = 220000;
+ break;
+
+ default:
+
+#ifndef AVOID_CPIO
+
+ /*
+ * 80 MHz is too high in some cases. Limit 18800-x's to 40
+ * MHz. Don't exceed the memory clock on VGA Wonder capables
+ * with less than 1 MB, if using a packed mode.
+ */
+ if ((pATI->Chip == ATI_CHIP_18800) ||
+ (pATI->Chip == ATI_CHIP_18800_1))
+ DefaultmaxClock = 40000;
+ else if (pATI->CPIO_VGAWonder &&
+ (pATI->VideoRAM < 1024) &&
+ (pATI->depth >= 8))
+ DefaultmaxClock =
+ (GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000;
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ DefaultmaxClock = 80000;
+ }
+
+ break;
+ }
+
+ if (DefaultmaxClock < ATIClockRange.maxClock)
+ ATIClockRange.maxClock = DefaultmaxClock;
+ }
+
+ if (pATI->ClockDescriptor.MaxN <= 0)
+ {
+ ATIClockRange.maxClock = DefaultmaxClock;
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Maximum pixel clock: %.3f MHz.\n",
+ (double)ATIClockRange.maxClock / 1000.0);
+ }
+
+ /*
+ * Determine available pixel clock frequencies.
+ */
+
+ ATIClockPreInit(pScreenInfo, pATI, pGDev, &ATIClockRange);
+ if (pATI->ProgrammableClock > ATI_CLOCK_FIXED)
+ Strategy = LOOKUP_BEST_REFRESH;
+
+ /*
+ * Mode validation.
+ */
+
+#ifdef AVOID_CPIO
+
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ minPitch = 8;
+
+#else /* AVOID_CPIO */
+
+ if ((pATI->depth >= 8) && (pATI->Chip >= ATI_CHIP_264CT))
+ minPitch = 8;
+ else if (pATI->CPIO_VGAWonder &&
+ (pATI->Chip <= ATI_CHIP_18800_1) &&
+ (pATI->VideoRAM == 256) &&
+ (pATI->depth >= 8))
+ {
+ minPitch = 32; /* Very strange, but true */
+ maxPitch = 0x3FU;
+ }
+
+#endif /* AVOID_CPIO */
+
+ else
+ minPitch = 16;
+
+ pATI->pitchInc = minPitch;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->depth >= 8)
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->pitchInc *= pATI->bitsPerPixel;
+ }
+
+ switch (pATI->NewHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /*
+ * IBM's VGA doesn't allow for interlaced modes.
+ */
+ if (pATI->Adapter <= ATI_ADAPTER_VGA)
+ ATIClockRange.interlaceAllowed = FALSE;
+
+ pScreenInfo->maxHValue = (0xFFU + 1) << 3; /* max HTotal */
+
+ /*
+ * The maximum VTotal value set here applies to all modes,
+ * including interlaced, doublescanned or multiscanned modes.
+ * Finer-grained checks are done in ATIValidateMode().
+ */
+ pScreenInfo->maxVValue = 0x03FFU + 1;
+ if (pATI->Adapter > ATI_ADAPTER_VGA)
+ {
+ pScreenInfo->maxVValue <<= 1;
+ if (ATIClockRange.interlaceAllowed &&
+ (pATI->Chip < ATI_CHIP_264CT))
+ pScreenInfo->maxVValue <<= 1;
+ }
+
+ /*
+ * 18800-x and 28800-x do not support interlaced modes when the
+ * scanline pitch is 2048 pixels or more. For 18800-x's with 256
+ * kB of video memory, the limit for 8bpp is 1024.
+ */
+ if (ATIClockRange.interlaceAllowed &&
+ (pATI->Chip <= ATI_CHIP_28800_6))
+ {
+ if (minPitch == 32)
+ pATI->MaximumInterlacedPitch = 0x1FU * 32;
+ else
+ pATI->MaximumInterlacedPitch = 0x7FU * minPitch;
+ }
+
+ Strategy |= LOOKUP_CLKDIV2;
+
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ pScreenInfo->maxHValue = (MaxBits(CRTC_H_TOTAL) + 1) << 3;
+
+ if (pATI->Chip < ATI_CHIP_264VT)
+ {
+ /*
+ * ATI finally fixed accelerated doublescanning in the 264VT
+ * and later. On 88800's, the bit is documented to exist, but
+ * only doubles the vertical timings. On the 264CT and 264ET,
+ * the bit is ignored.
+ */
+ ATIClockRange.doubleScanAllowed = FALSE;
+
+ /* CRTC_H_TOTAL is one bit narrower */
+ pScreenInfo->maxHValue >>= 1;
+ }
+
+ pScreenInfo->maxVValue = MaxBits(CRTC_V_TOTAL) + 1;
+
+ maxPitch = MaxBits(CRTC_PITCH);
+
+ break;
+
+ default:
+ break;
+ }
+
+ maxPitch *= minPitch;
+
+ if (pATI->OptionAccel)
+ {
+ /*
+ * Set engine restrictions on coordinate space. Use maxPitch for the
+ * horizontal and maxHeight for the vertical.
+ */
+ if (maxPitch > (ATIMach64MaxX / pATI->XModifier))
+ maxPitch = ATIMach64MaxX / pATI->XModifier;
+ maxHeight = ATIMach64MaxY;
+
+ /*
+ * For SGRAM & WRAM adapters, the display engine limits the pitch to
+ * multiples of 64 bytes.
+ */
+ if ((pATI->Chip >= ATI_CHIP_264CT) &&
+ ((pATI->Chip >= ATI_CHIP_264VTB) ||
+ (pATI->MemoryType >= MEM_264_SGRAM)))
+ pATI->pitchInc = pATI->XModifier * (64 * 8);
+ }
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ {
+ /*
+ * Given LCD modes are more tightly controlled than CRT modes, allow
+ * the user the option of not specifying a panel's horizontal sync
+ * and/or vertical refresh tolerances.
+ */
+ Strategy |= LOOKUP_OPTIONAL_TOLERANCES;
+
+ /*
+ * Add a mode to the end of the monitor's list for the panel's native
+ * resolution.
+ */
+ pMode = (DisplayModePtr)xnfcalloc(1, SizeOf(DisplayModeRec));
+ pMode->name = "Native panel mode";
+ pMode->type = M_T_BUILTIN;
+ pMode->Clock = pATI->LCDClock;
+ pMode->HDisplay = pATI->LCDHorizontal;
+ pMode->VDisplay = pATI->LCDVertical;
+
+ /*
+ * These timings are bogus, but enough to survive sync tolerance
+ * checks.
+ */
+ pMode->HSyncStart = pMode->HDisplay;
+ pMode->HSyncEnd = pMode->HSyncStart + minPitch;
+ pMode->HTotal = pMode->HSyncEnd + minPitch;
+ pMode->VSyncStart = pMode->VDisplay;
+ pMode->VSyncEnd = pMode->VSyncStart + 1;
+ pMode->VTotal = pMode->VSyncEnd + 1;
+
+ pMode->CrtcHDisplay = pMode->HDisplay;
+ pMode->CrtcHBlankStart = pMode->HDisplay;
+ pMode->CrtcHSyncStart = pMode->HSyncStart;
+ pMode->CrtcHSyncEnd = pMode->HSyncEnd;
+ pMode->CrtcHBlankEnd = pMode->HTotal;
+ pMode->CrtcHTotal = pMode->HTotal;
+
+ pMode->CrtcVDisplay = pMode->VDisplay;
+ pMode->CrtcVBlankStart = pMode->VDisplay;
+ pMode->CrtcVSyncStart = pMode->VSyncStart;
+ pMode->CrtcVSyncEnd = pMode->VSyncEnd;
+ pMode->CrtcVBlankEnd = pMode->VTotal;
+ pMode->CrtcVTotal = pMode->VTotal;
+
+ if (!pScreenInfo->monitor->Modes)
+ pScreenInfo->monitor->Modes = pMode;
+ else
+ {
+ pScreenInfo->monitor->Last->next = pMode;
+ pMode->prev = pScreenInfo->monitor->Last;
+ }
+
+ pScreenInfo->monitor->Last = pMode;
+
+ /*
+ * Defeat Xconfigurator brain damage. Ignore all HorizSync and
+ * VertRefresh specifications. For now, this does not take
+ * SYNC_TOLERANCE into account.
+ */
+ if (pScreenInfo->monitor->nHsync > 0)
+ {
+ double hsync = (double)pMode->Clock /
+ (pATI->LCDHorizontal + pATI->LCDHBlankWidth);
+
+ for (i = 0; ; i++)
+ {
+ if (i >= pScreenInfo->monitor->nHsync)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Conflicting XF86Config HorizSync specification(s)"
+ " ignored.\n");
+ break;
+ }
+
+ if ((hsync >= pScreenInfo->monitor->hsync[i].lo) &&
+ (hsync <= pScreenInfo->monitor->hsync[i].hi))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Extraneous XF86Config HorizSync specification(s)"
+ " ignored.\n");
+ break;
+ }
+ }
+
+ pScreenInfo->monitor->nHsync = 0;
+ }
+
+ if (pScreenInfo->monitor->nVrefresh > 0)
+ {
+ double vrefresh = ((double)pMode->Clock * 1000.0) /
+ ((pATI->LCDHorizontal + pATI->LCDHBlankWidth) *
+ (pATI->LCDVertical + pATI->LCDVBlankWidth));
+
+ for (i = 0; ; i++)
+ {
+ if (i >= pScreenInfo->monitor->nVrefresh)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
+ "Conflicting XF86Config VertRefresh specification(s)"
+ " ignored.\n");
+ break;
+ }
+
+ if ((vrefresh >= pScreenInfo->monitor->vrefresh[i].lo) &&
+ (vrefresh <= pScreenInfo->monitor->vrefresh[i].hi))
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Extraneous XF86Config VertRefresh specification(s)"
+ " ignored.\n");
+ break;
+ }
+ }
+
+ pScreenInfo->monitor->nVrefresh = 0;
+ }
+ }
+
+ i = xf86ValidateModes(pScreenInfo,
+ pScreenInfo->monitor->Modes, pScreenInfo->display->modes,
+ &ATIClockRange, NULL, minPitch, maxPitch,
+ pATI->pitchInc, 0, maxHeight,
+ pScreenInfo->display->virtualX, pScreenInfo->display->virtualY,
+ ApertureSize, Strategy);
+ if (i <= 0)
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ /* Remove invalid modes */
+ xf86PruneDriverModes(pScreenInfo);
+
+ /* Set current mode to the first in the list */
+ pScreenInfo->currentMode = pScreenInfo->modes;
+
+ /* Print mode list */
+ xf86PrintModes(pScreenInfo);
+
+ /* Set display resolution */
+ xf86SetDpi(pScreenInfo, 0, 0);
+
+ /* Load required modules */
+ if (!ATILoadModules(pScreenInfo, pATI))
+ {
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+ return FALSE;
+ }
+
+ pATI->displayWidth = pScreenInfo->displayWidth;
+
+ /* Initialise for panning */
+ ATIAdjustPreInit(pATI);
+
+ /*
+ * Warn about modes that are too small, or not aligned, to scroll to the
+ * bottom right corner of the virtual screen.
+ */
+ MinX = pScreenInfo->virtualX - pATI->AdjustMaxX;
+ MinY = pScreenInfo->virtualY - pATI->AdjustMaxY;
+
+ pMode = pScreenInfo->modes;
+ do
+ {
+ if ((pMode->VDisplay <= MinY) &&
+ ((pMode->VDisplay < MinY) || (pMode->HDisplay < MinX)))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Mode \"%s\" too small to scroll to bottom right corner of"
+ " virtual resolution.\n", pMode->name);
+ else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Mode \"%s\" cannot scroll to bottom right corner of virtual"
+ " resolution.\n Horizontal dimension not a multiple of %d.\n",
+ pMode->name, ~pATI->AdjustMask + 1);
+ } while ((pMode = pMode->next) != pScreenInfo->modes);
+
+ /* Initialise CRTC code */
+ ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
+
+ if (!pScreenInfo->chipset || !*pScreenInfo->chipset)
+ pScreenInfo->chipset = (char *)ATIChipsetNames[0];
+
+ ATILock(pATI);
+ ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
+ ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
+
+ return TRUE;
+}
diff --git a/src/atipreinit.h b/src/atipreinit.h
new file mode 100644
index 0000000..5404c2c
--- /dev/null
+++ b/src/atipreinit.h
@@ -0,0 +1,33 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atipreinit.h,v 1.6 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIPREINIT_H___
+#define ___ATIPREINIT_H___ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIPreInit FunctionPrototype((ScrnInfoPtr, int));
+
+#endif /* ___ATIPREINIT_H___ */
diff --git a/src/atiprint.c b/src/atiprint.c
new file mode 100644
index 0000000..9644404
--- /dev/null
+++ b/src/atiprint.c
@@ -0,0 +1,823 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprint.c,v 1.25 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "atidac.h"
+#include "atimach64io.h"
+#include "atiprint.h"
+#include "atiwonderio.h"
+
+/*
+ * ATIPrintBIOS --
+ *
+ * Display various parts of the BIOS when the server is invoked with -verbose.
+ */
+void
+ATIPrintBIOS
+(
+ const CARD8 *BIOS,
+ const unsigned int Length /* A multiple of 512 */
+)
+{
+ unsigned char *Char = NULL;
+ unsigned int Index;
+ unsigned char Printable[17];
+
+ if (xf86GetVerbosity() <= 4)
+ return;
+
+ (void)memset(Printable, 0, SizeOf(Printable));
+
+ xf86ErrorFVerb(5, "\n BIOS image:");
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ if (!(Index & (4U - 1U)))
+ {
+ if (!(Index & (16U - 1U)))
+ {
+ if (Printable[0])
+ xf86ErrorFVerb(5, " |%s|", Printable);
+ Char = Printable;
+ xf86ErrorFVerb(5, "\n 0x%08X: ", Index);
+ }
+ xf86ErrorFVerb(5, " ");
+ }
+ xf86ErrorFVerb(5, "%02X", BIOS[Index]);
+ if (isprint(BIOS[Index]))
+ *Char++ = BIOS[Index];
+ else
+ *Char++ = '.';
+ }
+
+ xf86ErrorFVerb(5, " |%s|\n", Printable);
+}
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIPrintIndexedRegisters --
+ *
+ * Display a set of indexed byte-size registers when the server is invoked with
+ * -verbose.
+ */
+static void
+ATIPrintIndexedRegisters
+(
+ const IOADDRESS Port,
+ const CARD8 StartIndex,
+ const CARD8 EndIndex,
+ const char *Name,
+ const IOADDRESS GenS1
+)
+{
+ int Index;
+
+ xf86ErrorFVerb(4, "\n %s register values:", Name);
+ for (Index = StartIndex; Index < EndIndex; Index++)
+ {
+ if (!(Index & (4U - 1U)))
+ {
+ if (!(Index & (16U - 1U)))
+ xf86ErrorFVerb(4, "\n 0x%02X: ", Index);
+ xf86ErrorFVerb(4, " ");
+ }
+ if (Port == ATTRX)
+ (void)inb(GenS1); /* Reset flip-flop */
+ xf86ErrorFVerb(4, "%02X", GetReg(Port, Index));
+ }
+
+ if (Port == ATTRX)
+ {
+ (void)inb(GenS1); /* Reset flip-flop */
+ outb(ATTRX, 0x20U); /* Turn on PAS bit */
+ }
+
+ xf86ErrorFVerb(4, "\n");
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIPrintMach64Registers --
+ *
+ * Display a Mach64's main register bank when the server is invoked with
+ * -verbose.
+ */
+static void
+ATIPrintMach64Registers
+(
+ ATIPtr pATI,
+ CARD8 *crtc,
+ const char *Description
+)
+{
+ CARD32 IOValue;
+ CARD8 dac_read, dac_mask, dac_data, dac_write;
+ int Index, Limit;
+
+#ifndef AVOID_CPIO
+
+ int Step;
+
+#endif /* AVOID_CPIO */
+
+ xf86ErrorFVerb(4, "\n Mach64 %s register values:", Description);
+
+#ifdef AVOID_CPIO
+
+ if (pATI->pBlock[1])
+ Limit = DWORD_SELECT;
+ else
+ Limit = MM_IO_SELECT;
+
+ for (Index = 0; Index <= Limit; Index += UnitOf(MM_IO_SELECT))
+ {
+ if (!(Index & SetBits(3, MM_IO_SELECT)))
+ xf86ErrorFVerb(4, "\n 0x%04X: ", Index);
+ if (Index == (DAC_REGS & DWORD_SELECT))
+ {
+ dac_read = in8(DAC_REGS + 3);
+ DACDelay;
+ dac_mask = in8(DAC_REGS + 2);
+ DACDelay;
+ dac_data = in8(DAC_REGS + 1);
+ DACDelay;
+ dac_write = in8(DAC_REGS + 0);
+ DACDelay;
+
+ xf86ErrorFVerb(4, " %02X%02X%02X%02X",
+ dac_read, dac_mask, dac_data, dac_write);
+
+ out8(DAC_REGS + 2, dac_mask);
+ DACDelay;
+ out8(DAC_REGS + 3, dac_read);
+ DACDelay;
+ }
+ else
+ {
+ IOValue = inm(Index);
+
+ if ((Index == (CRTC_GEN_CNTL & DWORD_SELECT)) &&
+ (IOValue & CRTC_EXT_DISP_EN))
+ *crtc = ATI_CRTC_MACH64;
+
+ xf86ErrorFVerb(4, " %08X", IOValue);
+ }
+ }
+
+#else /* AVOID_CPIO */
+
+ Limit = ATIIOPort(IOPortTag(0x1FU, 0x3FU));
+ Step = ATIIOPort(IOPortTag(0x01U, 0x01U)) - pATI->CPIOBase;
+ for (Index = pATI->CPIOBase; Index <= Limit; Index += Step)
+ {
+ if (!(((Index - pATI->CPIOBase) / Step) & 0x03U))
+ xf86ErrorFVerb(4, "\n 0x%04X: ", Index);
+ if (Index == (int)ATIIOPort(DAC_REGS))
+ {
+ dac_read = in8(DAC_REGS + 3);
+ DACDelay;
+ dac_mask = in8(DAC_REGS + 2);
+ DACDelay;
+ dac_data = in8(DAC_REGS + 1);
+ DACDelay;
+ dac_write = in8(DAC_REGS + 0);
+ DACDelay;
+
+ xf86ErrorFVerb(4, " %02X%02X%02X%02X",
+ dac_read, dac_mask, dac_data, dac_write);
+
+ out8(DAC_REGS + 2, dac_mask);
+ DACDelay;
+ out8(DAC_REGS + 3, dac_read);
+ DACDelay;
+ }
+ else
+ {
+ IOValue = inl(Index);
+
+ if ((Index == (int)ATIIOPort(CRTC_GEN_CNTL)) &&
+ (IOValue & CRTC_EXT_DISP_EN))
+ *crtc = ATI_CRTC_MACH64;
+
+ xf86ErrorFVerb(4, " %08X", IOValue);
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ xf86ErrorFVerb(4, "\n");
+}
+
+/*
+ * ATIPrintMach64PLLRegisters --
+ *
+ * Display an integrated Mach64's PLL registers when the server is invoked with
+ * -verbose.
+ */
+static void
+ATIPrintMach64PLLRegisters
+(
+ ATIPtr pATI
+)
+{
+ int Index, Limit;
+ CARD8 PLLReg[MaxBits(PLL_ADDR) + 1];
+
+ for (Limit = 0; Limit < SizeOf(PLLReg); Limit++)
+ PLLReg[Limit] = ATIGetMach64PLLReg(Limit);
+
+ /* Determine how many PLL registers there really are */
+ while ((Limit = Limit >> 1))
+ for (Index = 0; Index < Limit; Index++)
+ if (PLLReg[Index] != PLLReg[Index + Limit])
+ goto FoundLimit;
+FoundLimit:
+ Limit <<= 1;
+
+ xf86ErrorFVerb(4, "\n Mach64 PLL register values:");
+ for (Index = 0; Index < Limit; Index++)
+ {
+ if (!(Index & 3))
+ {
+ if (!(Index & 15))
+ xf86ErrorFVerb(4, "\n 0x%02X: ", Index);
+ xf86ErrorFVerb(4, " ");
+ }
+ xf86ErrorFVerb(4, "%02X", PLLReg[Index]);
+ }
+
+ xf86ErrorFVerb(4, "\n");
+}
+
+/*
+ * ATIPrintRGB514Registers --
+ *
+ * Display IBM RGB 514 registers when the server is invoked with -verbose.
+ */
+static void
+ATIPrintRGB514Registers
+(
+ ATIPtr pATI
+)
+{
+ CARD32 crtc_gen_cntl, dac_cntl;
+ CARD8 index_lo, index_hi, index_ctl;
+ int Index;
+
+ /* Temporarily switch to Mach64 CRTC */
+ crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
+
+ /* Temporarily switch to IBM RGB 514 registers */
+ dac_cntl = inr(DAC_CNTL);
+ outr(DAC_CNTL, (dac_cntl & ~DAC_EXT_SEL_RS3) | DAC_EXT_SEL_RS2);
+
+ index_lo = in8(M64_DAC_WRITE);
+ index_hi = in8(M64_DAC_DATA);
+ index_ctl = in8(M64_DAC_READ);
+
+ out8(M64_DAC_WRITE, 0x00U);
+ out8(M64_DAC_DATA, 0x00U);
+ out8(M64_DAC_READ, 0x01U); /* Auto-increment */
+
+ xf86ErrorFVerb(4, "\n IBM RGB 514 registers:");
+ for (Index = 0; Index < 0x0800; Index++)
+ {
+ if (!(Index & 3))
+ {
+ if (!(Index & 15))
+ {
+ xf86ErrorFVerb(4, "\n 0x%04X: ", Index);
+
+ /* Need to rewrite index every so often... */
+ if ((Index == 0x0100) || (Index == 0x0500))
+ {
+ out8(M64_DAC_WRITE, 0x00U);
+ out8(M64_DAC_DATA, Index >> 8);
+ }
+ }
+
+ xf86ErrorFVerb(4, " ");
+ }
+
+ xf86ErrorFVerb(4, "%02X", in8(M64_DAC_MASK));
+ }
+
+ /* Restore registers */
+ out8(M64_DAC_WRITE, index_lo);
+ out8(M64_DAC_DATA, index_hi);
+ out8(M64_DAC_READ, index_ctl);
+ outr(DAC_CNTL, dac_cntl);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl);
+
+ xf86ErrorFVerb(4, "\n");
+}
+
+/*
+ * ATIPrintRegisters --
+ *
+ * Display various registers when the server is invoked with -verbose.
+ */
+void
+ATIPrintRegisters
+(
+ ATIPtr pATI
+)
+{
+ pciVideoPtr pVideo;
+ pciConfigPtr pPCI;
+ int Index;
+ CARD32 lcd_index, tv_out_index, lcd_gen_ctrl;
+ CARD8 dac_read, dac_mask, dac_write;
+ CARD8 crtc;
+
+#ifndef AVOID_CPIO
+
+ CARD8 genmo, seq1 = 0;
+
+ crtc = ATI_CRTC_VGA;
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ xf86ErrorFVerb(4, "\n Miscellaneous output register value: 0x%02X.\n",
+ genmo = inb(R_GENMO));
+
+ if (genmo & 0x01U)
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64,
+ "Non-shadow colour CRT controller", 0);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64,
+ "Shadow colour CRT controller", 0);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ }
+ else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY))
+ {
+ lcd_index = inr(LCD_INDEX);
+ lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64,
+ "Non-shadow colour CRT controller", 0);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64,
+ "Shadow colour CRT controller", 0);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+ outr(LCD_INDEX, lcd_index);
+ }
+ else
+ {
+ ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64,
+ "Colour CRT controller", 0);
+ }
+
+ ATIPrintIndexedRegisters(ATTRX, 0, 32, "Attribute controller",
+ GENS1(ColourIOBase));
+ }
+ else
+ {
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64,
+ "Non-shadow monochrome CRT controller", 0);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64,
+ "Shadow monochrome CRT controller", 0);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+ }
+ else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY))
+ {
+ lcd_index = inr(LCD_INDEX);
+ lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64,
+ "Non-shadow monochrome CRT controller", 0);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64,
+ "Shadow monochrome CRT controller", 0);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+ outr(LCD_INDEX, lcd_index);
+ }
+ else
+ {
+ ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64,
+ "Monochrome CRT controller", 0);
+ }
+
+ ATIPrintIndexedRegisters(ATTRX, 0, 32, "Attribute controller",
+ GENS1(MonochromeIOBase));
+ }
+
+ ATIPrintIndexedRegisters(GRAX, 0, 16, "Graphics controller", 0);
+ ATIPrintIndexedRegisters(SEQX, 0, 8, "Sequencer", 0);
+
+ if (pATI->CPIO_VGAWonder)
+ ATIPrintIndexedRegisters(pATI->CPIO_VGAWonder,
+ xf86ServerIsOnlyProbing() ? 0x80U : pATI->VGAOffset, 0xC0U,
+ "ATI extended VGA", 0);
+ }
+
+ if (pATI->ChipHasSUBSYS_CNTL)
+ {
+ xf86ErrorFVerb(4, "\n 8514/A register values:");
+ for (Index = 0x02E8U; Index <= 0x0FEE8; Index += 0x0400U)
+ {
+ if (!((Index - 0x02E8U) & 0x0C00U))
+ xf86ErrorFVerb(4, "\n 0x%04X: ", Index);
+ xf86ErrorFVerb(4, " %04X", inw(Index));
+ }
+
+ if (pATI->Adapter >= ATI_ADAPTER_MACH8)
+ {
+ xf86ErrorFVerb(4, "\n\n Mach8/Mach32 register values:");
+ for (Index = 0x02EEU; Index <= 0x0FEEE; Index += 0x0400U)
+ {
+ if (!((Index - 0x02EEU) & 0x0C00U))
+ xf86ErrorFVerb(4, "\n 0x%04X: ", Index);
+ xf86ErrorFVerb(4, " %04X", inw(Index));
+ }
+ }
+
+ xf86ErrorFVerb(4, "\n");
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->Chip == ATI_CHIP_264LT)
+ {
+ lcd_gen_ctrl = inr(LCD_GEN_CTRL);
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintMach64Registers(pATI, &crtc, "non-shadow");
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintMach64Registers(pATI, &crtc, "shadow");
+
+ outr(LCD_GEN_CTRL, lcd_gen_ctrl);
+
+ ATIPrintMach64PLLRegisters(pATI);
+ }
+ else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
+ (pATI->Chip == ATI_CHIP_264XL) ||
+ (pATI->Chip == ATI_CHIP_MOBILITY))
+ {
+ lcd_index = inr(LCD_INDEX);
+ lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintMach64Registers(pATI, &crtc, "non-shadow");
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL,
+ (lcd_gen_ctrl & ~CRTC_RW_SELECT) | (SHADOW_EN | SHADOW_RW_EN));
+ ATIPrintMach64Registers(pATI, &crtc, "shadow");
+
+ if (pATI->Chip != ATI_CHIP_264XL)
+ {
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl | CRTC_RW_SELECT);
+ ATIPrintMach64Registers(pATI, &crtc, "secondary");
+ }
+
+ ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
+
+ ATIPrintMach64PLLRegisters(pATI);
+
+ xf86ErrorFVerb(4, "\n LCD register values:");
+ for (Index = 0; Index < 64; Index++)
+ {
+ if (!(Index & 3))
+ xf86ErrorFVerb(4, "\n 0x%02X: ", Index);
+ xf86ErrorFVerb(4, " %08X", ATIGetMach64LCDReg(Index));
+ }
+
+ outr(LCD_INDEX, lcd_index);
+
+ tv_out_index = inr(TV_OUT_INDEX);
+
+ xf86ErrorFVerb(4, "\n\n TV_OUT register values:");
+ for (Index = 0; Index < 256; Index++)
+ {
+ if (!(Index & 3))
+ xf86ErrorFVerb(4, "\n 0x%02X: ", Index);
+ xf86ErrorFVerb(4, " %08X", ATIGetMach64TVReg(Index));
+ }
+
+ outr(TV_OUT_INDEX, tv_out_index);
+
+ xf86ErrorFVerb(4, "\n");
+ }
+ else
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Chip >= ATI_CHIP_88800GXC)
+
+#endif /* AVOID_CPIO */
+
+ {
+
+#ifdef AVOID_CPIO
+
+ ATIPrintMach64Registers(pATI, &crtc, "MMIO");
+
+#else /* AVOID_CPIO */
+
+ ATIPrintMach64Registers(pATI, &crtc,
+ (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block");
+
+#endif /* AVOID_CPIO */
+
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ ATIPrintMach64PLLRegisters(pATI);
+
+ if (pATI->DAC == ATI_DAC_IBMRGB514)
+ ATIPrintRGB514Registers(pATI);
+ }
+
+#ifdef AVOID_CPIO
+
+ dac_read = in8(M64_DAC_READ);
+ DACDelay;
+ dac_write = in8(M64_DAC_WRITE);
+ DACDelay;
+ dac_mask = in8(M64_DAC_MASK);
+ DACDelay;
+
+ xf86ErrorFVerb(4, "\n"
+ " DAC read index: 0x%02X\n"
+ " DAC write index: 0x%02X\n"
+ " DAC mask: 0x%02X\n\n"
+ " DAC colour lookup table:",
+ dac_read, dac_write, dac_mask);
+
+ out8(M64_DAC_MASK, 0xFFU);
+ DACDelay;
+ out8(M64_DAC_READ, 0x00U);
+ DACDelay;
+
+ for (Index = 0; Index < 256; Index++)
+ {
+ if (!(Index & 3))
+ xf86ErrorFVerb(4, "\n 0x%02X:", Index);
+ xf86ErrorFVerb(4, " %02X", in8(M64_DAC_DATA));
+ DACDelay;
+ xf86ErrorFVerb(4, " %02X", in8(M64_DAC_DATA));
+ DACDelay;
+ xf86ErrorFVerb(4, " %02X", in8(M64_DAC_DATA));
+ DACDelay;
+ }
+
+ out8(M64_DAC_MASK, dac_mask);
+ DACDelay;
+ out8(M64_DAC_READ, dac_read);
+ DACDelay;
+
+#else /* AVOID_CPIO */
+
+ ATISetDACIOPorts(pATI, crtc);
+
+ /* Temporarily turn off CLKDIV2 while reading DAC's LUT */
+ if (pATI->Adapter == ATI_ADAPTER_NONISA)
+ {
+ seq1 = GetReg(SEQX, 0x01U);
+ if (seq1 & 0x08U)
+ PutReg(SEQX, 0x01U, seq1 & ~0x08U);
+ }
+
+ dac_read = inb(pATI->CPIO_DAC_READ);
+ DACDelay;
+ dac_write = inb(pATI->CPIO_DAC_WRITE);
+ DACDelay;
+ dac_mask = inb(pATI->CPIO_DAC_MASK);
+ DACDelay;
+
+ xf86ErrorFVerb(4, "\n"
+ " DAC read index: 0x%02X\n"
+ " DAC write index: 0x%02X\n"
+ " DAC mask: 0x%02X\n\n"
+ " DAC colour lookup table:",
+ dac_read, dac_write, dac_mask);
+
+ outb(pATI->CPIO_DAC_MASK, 0xFFU);
+ DACDelay;
+ outb(pATI->CPIO_DAC_READ, 0x00U);
+ DACDelay;
+
+ for (Index = 0; Index < 256; Index++)
+ {
+ if (!(Index & 3))
+ xf86ErrorFVerb(4, "\n 0x%02X:", Index);
+ xf86ErrorFVerb(4, " %02X", inb(pATI->CPIO_DAC_DATA));
+ DACDelay;
+ xf86ErrorFVerb(4, " %02X", inb(pATI->CPIO_DAC_DATA));
+ DACDelay;
+ xf86ErrorFVerb(4, " %02X", inb(pATI->CPIO_DAC_DATA));
+ DACDelay;
+ }
+
+ outb(pATI->CPIO_DAC_MASK, dac_mask);
+ DACDelay;
+ outb(pATI->CPIO_DAC_READ, dac_read);
+ DACDelay;
+
+ if ((pATI->Adapter == ATI_ADAPTER_NONISA) && (seq1 & 0x08U))
+ PutReg(SEQX, 0x01U, seq1);
+
+#endif /* AVOID_CPIO */
+
+ if ((pVideo = pATI->PCIInfo))
+ {
+ pPCI = pVideo->thisCard;
+ xf86ErrorFVerb(4, "\n\n PCI configuration register values:");
+ for (Index = 0; Index < 256; Index+= 4)
+ {
+ if (!(Index & 15))
+ xf86ErrorFVerb(4, "\n 0x%02X: ", Index);
+ xf86ErrorFVerb(4, " 0x%08X", pciReadLong(pPCI->tag, Index));
+ }
+ }
+
+ xf86ErrorFVerb(4, "\n");
+
+#ifndef AVOID_CPIO
+
+ if (pATI->pBank)
+ xf86ErrorFVerb(4, "\n Banked aperture at 0x%0lX.",
+ pATI->pBank);
+ else
+ xf86ErrorFVerb(4, "\n No banked aperture.");
+
+ if (pATI->pMemory == pATI->pBank)
+ xf86ErrorFVerb(4, "\n No linear aperture.\n");
+ else
+
+#else /* AVOID_CPIO */
+
+ if (pATI->pMemory)
+
+#endif /* AVOID_CPIO */
+
+ {
+ xf86ErrorFVerb(4, "\n Linear aperture at 0x%0lX.\n", pATI->pMemory);
+ }
+
+ if (pATI->pBlock[0])
+ {
+ xf86ErrorFVerb(4, " Block 0 aperture at 0x%0lX.\n", pATI->pBlock[0]);
+ if (inr(CONFIG_CHIP_ID) == pATI->config_chip_id)
+ xf86ErrorFVerb(4, " MMIO registers are correctly mapped.\n");
+ else
+ xf86ErrorFVerb(4, " MMIO mapping is in error!\n");
+ if (pATI->pBlock[1])
+ xf86ErrorFVerb(4, " Block 1 aperture at 0x%0lX.\n",
+ pATI->pBlock[1]);
+ }
+ else
+ xf86ErrorFVerb(4, " No MMIO aperture.\n");
+
+ if (pATI->pCursorImage)
+ xf86ErrorFVerb(4, " Hardware cursor image aperture at 0x%0lX.\n",
+ pATI->pCursorImage);
+ else
+ xf86ErrorFVerb(4, " No hardware cursor image aperture.\n");
+
+ xf86ErrorFVerb(4, "\n");
+}
+
+/*
+ * A table to associate mode attributes with character strings.
+ */
+static const SymTabRec ModeAttributeNames[] =
+{
+ {V_PHSYNC, "+hsync"},
+ {V_NHSYNC, "-hsync"},
+ {V_PVSYNC, "+vsync"},
+ {V_NVSYNC, "-vsync"},
+ {V_PCSYNC, "+csync"},
+ {V_NCSYNC, "-csync"},
+ {V_INTERLACE, "interlace"},
+ {V_DBLSCAN, "doublescan"},
+ {V_CSYNC, "composite"},
+ {V_DBLCLK, "dblclk"},
+ {V_CLKDIV2, "clkdiv2"},
+ {0, NULL}
+};
+
+/*
+ * ATIPrintMode --
+ *
+ * This function displays a mode's timing information.
+ */
+void
+ATIPrintMode
+(
+ DisplayModePtr pMode
+)
+{
+ const SymTabRec *pSymbol = ModeAttributeNames;
+ int flags = pMode->Flags;
+ double mClock, hSync, vRefresh;
+
+ mClock = (double)pMode->SynthClock;
+ if (pMode->HSync > 0.0)
+ hSync = pMode->HSync;
+ else
+ hSync = mClock / pMode->HTotal;
+ if (pMode->VRefresh > 0.0)
+ vRefresh = pMode->VRefresh;
+ else
+ {
+ vRefresh = (hSync * 1000.0) / pMode->VTotal;
+ if (flags & V_INTERLACE)
+ vRefresh *= 2.0;
+ if (flags & V_DBLSCAN)
+ vRefresh /= 2.0;
+ if (pMode->VScan > 1)
+ vRefresh /= pMode->VScan;
+ }
+
+ xf86ErrorFVerb(4, " Dot clock: %7.3f MHz\n", mClock / 1000.0);
+ xf86ErrorFVerb(4, " Horizontal sync: %7.3f kHz\n", hSync);
+ xf86ErrorFVerb(4, " Vertical refresh: %7.3f Hz (%s)\n", vRefresh,
+ (flags & V_INTERLACE) ? "I" : "NI");
+ if ((pMode->ClockIndex >= 0) && (pMode->ClockIndex < MAXCLOCKS))
+ xf86ErrorFVerb(4, " Clock index: %d\n", pMode->ClockIndex);
+ xf86ErrorFVerb(4, " Horizontal timings: %4d %4d %4d %4d\n"
+ " Vertical timings: %4d %4d %4d %4d\n",
+ pMode->HDisplay, pMode->HSyncStart, pMode->HSyncEnd, pMode->HTotal,
+ pMode->VDisplay, pMode->VSyncStart, pMode->VSyncEnd, pMode->VTotal);
+
+ if (flags & V_HSKEW)
+ {
+ flags &= ~V_HSKEW;
+ xf86ErrorFVerb(4, " Horizontal skew: %4d\n", pMode->HSkew);
+ }
+
+ if (pMode->VScan >= 1)
+ xf86ErrorFVerb(4, " Vertical scan: %4d\n", pMode->VScan);
+
+ xf86ErrorFVerb(4, " Flags: ");
+ for (; pSymbol->token; pSymbol++)
+ {
+ if (flags & pSymbol->token)
+ {
+ xf86ErrorFVerb(4, " %s", pSymbol->name);
+ if (!(flags &= ~pSymbol->token))
+ break;
+ }
+ }
+
+ xf86ErrorFVerb(4, "\n");
+}
diff --git a/src/atiprint.h b/src/atiprint.h
new file mode 100644
index 0000000..d44cbdf
--- /dev/null
+++ b/src/atiprint.h
@@ -0,0 +1,37 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprint.h,v 1.10 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIPRINT_H___
+#define ___ATIPRINT_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern void ATIPrintBIOS FunctionPrototype((const CARD8 *,
+ const unsigned int));
+extern void ATIPrintRegisters FunctionPrototype((ATIPtr));
+extern void ATIPrintMode FunctionPrototype((DisplayModePtr));
+
+#endif /* ___ATIPRINT_H___ */
diff --git a/src/atipriv.h b/src/atipriv.h
new file mode 100644
index 0000000..69341ba
--- /dev/null
+++ b/src/atipriv.h
@@ -0,0 +1,31 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atipriv.h,v 1.5 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIPRIV_H___
+#define ___ATIPRIV_H___ 1
+
+/* Forward pointer definitions */
+typedef struct _ATIHWRec *ATIHWPtr;
+typedef struct _ATIRec *ATIPtr;
+
+#endif /* ___ATIPRIV_H___ */
diff --git a/src/atiprobe.c b/src/atiprobe.c
new file mode 100644
index 0000000..05d2f34
--- /dev/null
+++ b/src/atiprobe.c
@@ -0,0 +1,2353 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.54 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atiadjust.h"
+#include "atibus.h"
+#include "atichip.h"
+#include "aticonsole.h"
+#include "atiident.h"
+#include "atimach64io.h"
+#include "atimodule.h"
+#include "atipreinit.h"
+#include "atiprobe.h"
+#include "atiscreen.h"
+#include "ativalid.h"
+#include "ativersion.h"
+#include "atividmem.h"
+#include "atiwonderio.h"
+
+#include "radeon_probe.h"
+#include "radeon_version.h"
+#include "r128_probe.h"
+#include "r128_version.h"
+
+/*
+ * NOTES:
+ *
+ * - The driver private structures (ATIRec's) are allocated here, rather than
+ * in ATIPreInit(). This allows ATIProbe() to pass information to later
+ * stages.
+ * - A minor point, perhaps, is that XF86Config Chipset names denote functional
+ * levels, rather than specific graphics controller chips.
+ * - ATIProbe() does not call xf86MatchPciInstances(), because ATIProbe()
+ * should be able to match a mix of PCI and non-PCI devices to XF86Config
+ * Device sections. Also, PCI configuration space for Mach32's is to be
+ * largely ignored.
+ */
+
+#ifdef XFree86LOADER
+
+/*
+ * The following exists to prevent the compiler from considering entry points
+ * defined in a separate module from being constants.
+ */
+static xf86PreInitProc * const volatile PreInitProc = ATIPreInit;
+static xf86ScreenInitProc * const volatile ScreenInitProc = ATIScreenInit;
+static xf86SwitchModeProc * const volatile SwitchModeProc = ATISwitchMode;
+static xf86AdjustFrameProc * const volatile AdjustFrameProc = ATIAdjustFrame;
+static xf86EnterVTProc * const volatile EnterVTProc = ATIEnterVT;
+static xf86LeaveVTProc * const volatile LeaveVTProc = ATILeaveVT;
+static xf86FreeScreenProc * const volatile FreeScreenProc = ATIFreeScreen;
+static xf86ValidModeProc * const volatile ValidModeProc = ATIValidMode;
+
+#define ATIPreInit PreInitProc
+#define ATIScreenInit ScreenInitProc
+#define ATISwitchMode SwitchModeProc
+#define ATIAdjustFrame AdjustFrameProc
+#define ATIEnterVT EnterVTProc
+#define ATILeaveVT LeaveVTProc
+#define ATIFreeScreen FreeScreenProc
+#define ATIValidMode ValidModeProc
+
+#endif
+
+/* Used as a temporary buffer */
+#define Identifier ((char *)(pATI->MMIOCache))
+
+/*
+ * An internal structure definition to facilitate the matching of detected
+ * adapters to XF86Config Device sections.
+ */
+typedef struct _ATIGDev
+{
+ GDevPtr pGDev;
+ int iATIPtr;
+ CARD8 Chipset;
+} ATIGDev, *ATIGDevPtr;
+
+#ifndef AVOID_CPIO
+
+/*
+ * Definitions for I/O conflict avoidance.
+ */
+#define LongPort(_Port) GetBits(_Port, PCIGETIO(SPARSE_IO_BASE))
+#define DetectedVGA (1 << 0)
+#define Detected8514A (1 << 1)
+#define DetectedMach64 (1 << 2)
+#define Allowed (1 << 3)
+#define DoProbe (1 << 4)
+typedef struct
+{
+ IOADDRESS Base;
+ CARD8 Size;
+ CARD8 Flag;
+} PortRec, *PortPtr;
+
+/*
+ * ATIScanPCIBases --
+ *
+ * This function loops though a device's PCI registered bases and accumulates
+ * a list of block I/O bases in use in the system.
+ */
+static void
+ATIScanPCIBases
+(
+ PortPtr *PCIPorts,
+ int *nPCIPort,
+ const CARD32 *pBase,
+ const int *pSize,
+ const CARD8 ProbeFlag
+)
+{
+ IOADDRESS Base;
+ int i, j;
+
+ for (i = 6; --i >= 0; pBase++, pSize++)
+ {
+ if (*pBase & PCI_MAP_IO)
+ {
+ Base = *pBase & ~IO_BYTE_SELECT;
+ for (j = 0; ; j++)
+ {
+ if (j >= *nPCIPort)
+ {
+ (*nPCIPort)++;
+ *PCIPorts = (PortPtr)xnfrealloc(*PCIPorts,
+ *nPCIPort * SizeOf(PortRec));
+ (*PCIPorts)[j].Base = Base;
+ (*PCIPorts)[j].Size = (CARD8)*pSize;
+ (*PCIPorts)[j].Flag = ProbeFlag;
+ break;
+ }
+
+ if (Base == (*PCIPorts)[j].Base)
+ break;
+ }
+
+ continue;
+ }
+
+ /* Allow for 64-bit addresses */
+ if (!PCI_MAP_IS64BITMEM(*pBase))
+ continue;
+
+ i--;
+ pBase++;
+ pSize++;
+ }
+}
+
+/*
+ * ATICheckSparseIOBases --
+ *
+ * This function checks whether a sparse I/O base can safely be probed.
+ */
+static CARD8
+ATICheckSparseIOBases
+(
+ pciVideoPtr pVideo,
+ CARD8 *ProbeFlags,
+ const IOADDRESS IOBase,
+ const int Count,
+ const Bool Override
+)
+{
+ CARD32 FirstPort, LastPort;
+
+ if (!pVideo || !xf86IsPrimaryPci(pVideo))
+ {
+ FirstPort = LongPort(IOBase);
+ LastPort = LongPort(IOBase + Count - 1);
+
+ for (; FirstPort <= LastPort; FirstPort++)
+ {
+ CARD8 ProbeFlag = ProbeFlags[FirstPort];
+
+ if (ProbeFlag & DoProbe)
+ continue;
+
+ if (!(ProbeFlag & Allowed))
+ return ProbeFlag;
+
+ if (Override)
+ continue;
+
+ /* User might wish to override this decision */
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Sparse I/O base 0x%04X not probed.\n", IOBase);
+ return Allowed;
+ }
+ }
+
+ return DoProbe;
+}
+
+/*
+ * ATIClaimSparseIOBases --
+ *
+ * This function updates the sparse I/O base table with information from the
+ * hardware probes.
+ */
+static void
+ATIClaimSparseIOBases
+(
+ CARD8 *ProbeFlags,
+ const IOADDRESS IOBase,
+ const int Count,
+ const CARD8 ProbeFlag
+)
+{
+ CARD32 FirstPort = LongPort(IOBase),
+ LastPort = LongPort(IOBase + Count - 1);
+
+ for (; FirstPort <= LastPort; FirstPort++)
+ ProbeFlags[FirstPort] = ProbeFlag;
+}
+
+/*
+ * ATIVGAProbe --
+ *
+ * This function looks for an IBM standard VGA, or clone, and sets
+ * pATI->VGAAdapter if one is found.
+ */
+static ATIPtr
+ATIVGAProbe
+(
+ ATIPtr pVGA
+)
+{
+ CARD8 IOValue1, IOValue2, IOValue3;
+
+ if (!pVGA)
+ pVGA = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
+
+ /*
+ * VGA has one more attribute register than EGA. See if it can be read and
+ * written. Note that the CRTC registers are not used here, so there's no
+ * need to unlock them.
+ */
+ ATISetVGAIOBase(pVGA, inb(R_GENMO));
+ (void)inb(GENS1(pVGA->CPIO_VGABase));
+ IOValue1 = inb(ATTRX);
+ (void)inb(GENS1(pVGA->CPIO_VGABase));
+ IOValue2 = GetReg(ATTRX, 0x14U | 0x20U);
+ outb(ATTRX, IOValue2 ^ 0x0FU);
+ IOValue3 = GetReg(ATTRX, 0x14U | 0x20U);
+ outb(ATTRX, IOValue2);
+ outb(ATTRX, IOValue1);
+ (void)inb(GENS1(pVGA->CPIO_VGABase));
+ if (IOValue3 == (IOValue2 ^ 0x0FU))
+ {
+ /* VGA device detected */
+ if (pVGA->Chip == ATI_CHIP_NONE)
+ pVGA->Chip = ATI_CHIP_VGA;
+ if (pVGA->VGAAdapter == ATI_ADAPTER_NONE)
+ pVGA->VGAAdapter = ATI_ADAPTER_VGA;
+ if (pVGA->Adapter == ATI_ADAPTER_NONE)
+ pVGA->Adapter = ATI_ADAPTER_VGA;
+ }
+ else
+ pVGA->VGAAdapter = ATI_ADAPTER_NONE;
+
+ return pVGA;
+}
+
+/*
+ * ATIVGAWonderProbe --
+ *
+ * This function determines if ATI extended VGA registers can be accessed
+ * through the I/O port specified by pATI->CPIO_VGAWonder. If not, the
+ * function resets pATI->CPIO_VGAWonder to zero.
+ */
+static void
+ATIVGAWonderProbe
+(
+ pciVideoPtr pVideo,
+ ATIPtr pATI,
+ ATIPtr p8514,
+ CARD8 *ProbeFlags
+)
+{
+ CARD8 IOValue1, IOValue2, IOValue3, IOValue4, IOValue5, IOValue6;
+
+ switch (ATICheckSparseIOBases(pVideo, ProbeFlags,
+ pATI->CPIO_VGAWonder, 2, TRUE))
+ {
+ case 0:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Expected VGA Wonder capability could not be"
+ " detected at I/O port 0x%04X because it would conflict with"
+ " a non-video PCI/AGP device.\n", pATI->CPIO_VGAWonder);
+ pATI->CPIO_VGAWonder = 0;
+ break;
+
+ case Detected8514A:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Expected VGA Wonder capability could not be"
+ " detected at I/O port 0x%04X because it would conflict with"
+ " a %s %s.\n", pATI->CPIO_VGAWonder,
+ ATIBusNames[p8514->BusType], ATIAdapterNames[p8514->Adapter]);
+ pATI->CPIO_VGAWonder = 0;
+ break;
+
+ case DetectedMach64:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Expected VGA Wonder capability could not be"
+ " detected at I/O port 0x%04X because it would conflict with"
+ " a Mach64.\n", pATI->CPIO_VGAWonder);
+ pATI->CPIO_VGAWonder = 0;
+ break;
+
+ case DetectedVGA:
+ default: /* Must be DoProbe */
+ if (pVideo && !xf86IsPrimaryPci(pVideo) &&
+ (pATI->Chip <= ATI_CHIP_88800GXD))
+ {
+ /* Set up extended VGA register addressing */
+ PutReg(GRAX, 0x50U, GetByte(pATI->CPIO_VGAWonder, 0));
+ PutReg(GRAX, 0x51U,
+ GetByte(pATI->CPIO_VGAWonder, 1) | pATI->VGAOffset);
+ }
+ /*
+ * Register 0xBB is used by the BIOS to keep track of various
+ * things (monitor type, etc.). Except for 18800-x's, register
+ * 0xBC must be zero and causes the adapter to enter a test mode
+ * when written to with a non-zero value.
+ */
+ IOValue1 = inb(pATI->CPIO_VGAWonder);
+ IOValue2 = ATIGetExtReg(IOValue1);
+ IOValue3 = ATIGetExtReg(0xBBU);
+ ATIPutExtReg(0xBBU, IOValue3 ^ 0xAAU);
+ IOValue4 = ATIGetExtReg(0xBBU);
+ ATIPutExtReg(0xBBU, IOValue3 ^ 0x55U);
+ IOValue5 = ATIGetExtReg(0xBBU);
+ ATIPutExtReg(0xBBU, IOValue3);
+ if (pATI->Chip <= ATI_CHIP_18800_1)
+ IOValue6 = 0;
+ else
+ IOValue6 = ATIGetExtReg(0xBCU);
+ ATIPutExtReg(IOValue1, IOValue2);
+
+ if ((IOValue4 == (IOValue3 ^ 0xAAU)) &&
+ (IOValue5 == (IOValue3 ^ 0x55U)) &&
+ (IOValue6 == 0))
+ {
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": VGA Wonder at I/O port 0x%04X detected.\n",
+ pATI->CPIO_VGAWonder);
+ }
+ else
+ {
+ xf86Msg(X_WARNING,
+ ATI_NAME ": Expected VGA Wonder capability at I/O port"
+ " 0x%04X was not detected.\n", pATI->CPIO_VGAWonder);
+ pATI->CPIO_VGAWonder = 0;
+ }
+ break;
+ }
+}
+
+/*
+ * ATI8514Probe --
+ *
+ * This function looks for an 8514/A compatible and returns an ATIRec if one is
+ * found. The function also determines whether or not the detected 8514/A
+ * compatible device is actually a Mach8 or Mach32, and sets pATI->Adapter
+ * accordingly.
+ */
+static ATIPtr
+ATI8514Probe
+(
+ pciVideoPtr pVideo
+)
+{
+ ATIPtr pATI = NULL;
+ CARD16 IOValue1, IOValue2;
+
+ /*
+ * Save register value to be modified, just in case there is no 8514/A
+ * compatible accelerator. Note that, in more ways than one,
+ * SUBSYS_STAT == SUBSYS_CNTL.
+ */
+ IOValue1 = inw(SUBSYS_STAT);
+ IOValue2 = IOValue1 & _8PLANE;
+
+ /* Reset any 8514/A compatible adapter that might be present */
+ outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_RESET | CHPTEST_NORMAL));
+ outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_ENAB | CHPTEST_NORMAL |
+ RVBLNKFLG | RPICKFLAG | RINVALIDIO | RGPIDLE));
+
+ /* Probe for an 8514/A compatible */
+ IOValue2 = inw(ERR_TERM);
+ outw(ERR_TERM, 0x5A5AU);
+ ProbeWaitIdleEmpty();
+ if (inw(ERR_TERM) == 0x5A5AU)
+ {
+ outw(ERR_TERM, 0x2525U);
+ if (inw(ERR_TERM) == 0x2525U)
+ {
+ pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
+ pATI->Adapter = ATI_ADAPTER_8514A;
+ pATI->ChipHasSUBSYS_CNTL = TRUE;
+ pATI->PCIInfo = pVideo;
+ }
+ }
+ outw(ERR_TERM, IOValue2);
+
+ /* Restore register value clobbered by 8514/A reset attempt */
+ if (!pATI)
+ {
+ outw(SUBSYS_CNTL, IOValue1);
+ return NULL;
+ }
+
+ /* Ensure any Mach8 or Mach32 is not in 8514/A emulation mode */
+ IOValue1 = inw(CLOCK_SEL);
+ outw(CLOCK_SEL, IOValue1);
+ ProbeWaitIdleEmpty();
+
+ IOValue1 = IOValue2 = inw(ROM_ADDR_1);
+ outw(ROM_ADDR_1, 0x5555U);
+ ProbeWaitIdleEmpty();
+ if (inw(ROM_ADDR_1) == 0x5555U)
+ {
+ outw(ROM_ADDR_1, 0x2A2AU);
+ ProbeWaitIdleEmpty();
+ if (inw(ROM_ADDR_1) == 0x2A2AU)
+ pATI->Adapter = ATI_ADAPTER_MACH8;
+ }
+ outw(ROM_ADDR_1, IOValue1);
+
+ if (pATI->Adapter == ATI_ADAPTER_MACH8)
+ {
+ /* A Mach8 or Mach32 has been detected */
+ IOValue1 = inw(READ_SRC_X);
+ outw(DESTX_DIASTP, 0xAAAAU);
+ ProbeWaitIdleEmpty();
+ if (inw(READ_SRC_X) == 0x02AAU)
+ pATI->Adapter = ATI_ADAPTER_MACH32;
+
+ outw(DESTX_DIASTP, 0x5555U);
+ ProbeWaitIdleEmpty();
+ if (inw(READ_SRC_X) == 0x0555U)
+ {
+ if (pATI->Adapter != ATI_ADAPTER_MACH32)
+ pATI->Adapter = ATI_ADAPTER_8514A;
+ }
+ else
+ {
+ if (pATI->Adapter != ATI_ADAPTER_MACH8)
+ pATI->Adapter = ATI_ADAPTER_8514A;
+ }
+ outw(DESTX_DIASTP, IOValue1);
+ }
+
+ switch (pATI->Adapter)
+ {
+ case ATI_ADAPTER_8514A:
+ pATI->Coprocessor = ATI_CHIP_8514A;
+ IOValue1 = inb(EXT_CONFIG_3);
+ outb(EXT_CONFIG_3, IOValue1 & 0x0FU);
+ if (!(inb(EXT_CONFIG_3) & 0xF0U))
+ {
+ outb(EXT_CONFIG_3, IOValue1 | 0xF0U);
+ if ((inb(EXT_CONFIG_3) & 0xF0U) == 0xF0U)
+ pATI->Coprocessor = ATI_CHIP_CT480;
+ }
+ outb(EXT_CONFIG_3, IOValue1);
+ break;
+
+ case ATI_ADAPTER_MACH8:
+ pATI->Coprocessor = ATI_CHIP_38800_1;
+ if (inw(CONFIG_STATUS_1) & MC_BUS)
+ pATI->BusType = ATI_BUS_MCA16;
+ break;
+
+ case ATI_ADAPTER_MACH32:
+ IOValue1 = inw(CONFIG_STATUS_1);
+ pATI->BusType = GetBits(IOValue1, BUS_TYPE);
+ pATI->BIOSBase = 0x000C0000U +
+ (GetBits(IOValue2, BIOS_BASE_SEGMENT) << 11);
+ if (!(IOValue1 & (_8514_ONLY | CHIP_DIS)))
+ {
+ pATI->VGAAdapter = ATI_ADAPTER_MACH32;
+ if ((xf86ReadBIOS(pATI->BIOSBase, 0x10U,
+ (pointer)(&pATI->CPIO_VGAWonder),
+ SizeOf(pATI->CPIO_VGAWonder)) <
+ SizeOf(pATI->CPIO_VGAWonder)) ||
+ !(pATI->CPIO_VGAWonder &= SPARSE_IO_PORT))
+ pATI->CPIO_VGAWonder = 0x01CEU;
+ pATI->VGAOffset = 0x80U;
+ }
+
+ ATIMach32ChipID(pATI);
+ break;
+
+ default:
+ break;
+ }
+
+ return pATI;
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIDetectMach64 --
+ *
+ * This function determines if a Mach64 is detectable at a particular base
+ * address.
+ */
+static Bool
+ATIDetectMach64
+(
+ ATIPtr pATI,
+ const CARD16 ChipType,
+ const ATIChipType Chip
+)
+{
+ CARD32 IOValue, bus_cntl, gen_test_cntl;
+
+ (void)ATIMapApertures(-1, pATI); /* Ignore errors */
+
+#ifdef AVOID_CPIO
+
+ if (!pATI->pBlock[0])
+ {
+ ATIUnmapApertures(-1, pATI);
+ return FALSE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Make sure any Mach64 is not in some weird state */
+ bus_cntl = inr(BUS_CNTL);
+ if (Chip < ATI_CHIP_264VTB)
+ outr(BUS_CNTL,
+ (bus_cntl & ~(BUS_HOST_ERR_INT_EN | BUS_FIFO_ERR_INT_EN)) |
+ (BUS_HOST_ERR_INT | BUS_FIFO_ERR_INT));
+ else if (Chip < ATI_CHIP_264VT4)
+ outr(BUS_CNTL, (bus_cntl & ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT);
+
+ gen_test_cntl = inr(GEN_TEST_CNTL);
+ IOValue = gen_test_cntl &
+ (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN);
+ outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
+ outr(GEN_TEST_CNTL, IOValue);
+ outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
+
+ /* See if a Mach64 answers */
+ IOValue = inr(SCRATCH_REG0);
+
+ /* Test odd bits */
+ outr(SCRATCH_REG0, 0x55555555U);
+ if (inr(SCRATCH_REG0) == 0x55555555U)
+ {
+ /* Test even bits */
+ outr(SCRATCH_REG0, 0xAAAAAAAAU);
+ if (inr(SCRATCH_REG0) == 0xAAAAAAAAU)
+ {
+ /*
+ * *Something* has a R/W 32-bit register at this address. Try to
+ * make sure it's a Mach64. The following assumes that ATI will
+ * not be producing any more adapters that do not register
+ * themselves in PCI configuration space.
+ */
+ ATIMach64ChipID(pATI, ChipType);
+ if ((pATI->Chip != ATI_CHIP_Mach64) ||
+ (pATI->CPIODecoding == BLOCK_IO))
+ pATI->Adapter = ATI_ADAPTER_MACH64;
+ }
+ }
+
+ /* Restore clobbered register value */
+ outr(SCRATCH_REG0, IOValue);
+
+ /* If no Mach64 was detected, return now */
+ if (pATI->Adapter != ATI_ADAPTER_MACH64)
+ {
+ outr(GEN_TEST_CNTL, gen_test_cntl);
+ outr(BUS_CNTL, bus_cntl);
+ ATIUnmapApertures(-1, pATI);
+ return FALSE;
+ }
+
+ /* Determine legacy BIOS address */
+ pATI->BIOSBase = 0x000C0000U +
+ (GetBits(inr(SCRATCH_REG1), BIOS_BASE_SEGMENT) << 11);
+
+ ATIUnmapApertures(-1, pATI);
+ pATI->PCIInfo = NULL;
+ return TRUE;
+}
+
+#ifdef AVOID_CPIO
+
+/*
+ * ATIMach64Probe --
+ *
+ * This function looks for a Mach64 at a particular MMIO address and returns an
+ * ATIRec if one is found.
+ */
+static ATIPtr
+ATIMach64Probe
+(
+ pciVideoPtr pVideo,
+ const IOADDRESS IOBase,
+ const CARD8 IODecoding,
+ const ATIChipType Chip
+)
+{
+ ATIPtr pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
+ CARD16 ChipType = 0;
+
+ pATI->CPIOBase = IOBase;
+ pATI->CPIODecoding = IODecoding;
+
+ if (pVideo)
+ {
+ pATI->PCIInfo = pVideo;
+ ChipType = pVideo->chipType;
+
+ /*
+ * Probe through auxiliary MMIO aperture if one exists. Because such
+ * apertures can be enabled/disabled only through PCI, this probes no
+ * further.
+ */
+ if ((pVideo->size[2] >= 12) &&
+ (pATI->Block0Base = pVideo->memBase[2]) &&
+ (pATI->Block0Base < (CARD32)(-1 << pVideo->size[2])))
+ {
+ pATI->Block0Base += 0x00000400U;
+ goto LastProbe;
+ }
+
+ /*
+ * Probe through the primary MMIO aperture that exists at the tail end
+ * of the linear aperture. Test for both 8MB and 4MB linear apertures.
+ */
+ if ((pVideo->size[0] >= 22) && (pATI->Block0Base = pVideo->memBase[0]))
+ {
+ pATI->Block0Base += 0x007FFC00U;
+ if ((pVideo->size[0] >= 23) &&
+ ATIDetectMach64(pATI, ChipType, Chip))
+ return pATI;
+
+ pATI->Block0Base -= 0x00400000U;
+ if (ATIDetectMach64(pATI, ChipType, Chip))
+ return pATI;
+ }
+ }
+
+ /*
+ * A last, perhaps desparate, probe attempt. Note that if this succeeds,
+ * there's a VGA in the system and it's likely the PIO version of the
+ * driver should be used instead (barring OS issues).
+ */
+ pATI->Block0Base = 0x000BFC00U;
+
+LastProbe:
+ if (ATIDetectMach64(pATI, ChipType, Chip))
+ return pATI;
+
+ xfree(pATI);
+ return NULL;
+}
+
+#else /* AVOID_CPIO */
+
+/*
+ * ATIMach64Probe --
+ *
+ * This function looks for a Mach64 at a particular PIO address and returns an
+ * ATIRec if one is found.
+ */
+static ATIPtr
+ATIMach64Probe
+(
+ pciVideoPtr pVideo,
+ const IOADDRESS IOBase,
+ const CARD8 IODecoding,
+ const ATIChipType Chip
+)
+{
+ ATIPtr pATI;
+ CARD32 IOValue;
+ CARD16 ChipType = 0;
+
+ if (!IOBase)
+ return NULL;
+
+ if (pVideo)
+ {
+ if ((IODecoding == BLOCK_IO) &&
+ ((pVideo->size[1] < 8) ||
+ (IOBase >= (CARD32)(-1 << pVideo->size[1]))))
+ return NULL;
+
+ ChipType = pVideo->chipType;
+ }
+
+ pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
+ pATI->CPIOBase = IOBase;
+ pATI->CPIODecoding = IODecoding;
+ pATI->PCIInfo = pVideo;
+
+ if (!ATIDetectMach64(pATI, ChipType, Chip))
+ {
+ xfree(pATI);
+ return NULL;
+ }
+
+ /*
+ * Determine VGA capability. VGA can always be enabled on integrated
+ * controllers. For the GX/CX, it's a board strap.
+ */
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ pATI->VGAAdapter = ATI_ADAPTER_MACH64;
+ else
+ {
+ IOValue = inr(CONFIG_STATUS64_0);
+ pATI->BusType = GetBits(IOValue, CFG_BUS_TYPE);
+ IOValue &= (CFG_VGA_EN | CFG_CHIP_EN);
+ if (pATI->Chip == ATI_CHIP_88800CX)
+ IOValue |= CFG_VGA_EN;
+ if (IOValue == (CFG_VGA_EN | CFG_CHIP_EN))
+ {
+ pATI->VGAAdapter = ATI_ADAPTER_MACH64;
+ pATI->CPIO_VGAWonder = 0x01CEU;
+ pATI->VGAOffset = 0x80U;
+ }
+ }
+
+ return pATI;
+}
+
+/*
+ * ATIAssignVGA --
+ *
+ * This function is called to associate a VGA interface with an accelerator.
+ * This is done by temporarily configuring the accelerator to route VGA RAMDAC
+ * I/O through the accelerator's RAMDAC. A value is then written through the
+ * VGA DAC ports and a check is made to see if the same value shows up on the
+ * accelerator side.
+ */
+static void
+ATIAssignVGA
+(
+ pciVideoPtr pVideo,
+ ATIPtr *ppVGA,
+ ATIPtr pATI,
+ ATIPtr p8514,
+ CARD8 *ProbeFlags
+)
+{
+ ATIPtr pVGA = *ppVGA;
+ CARD8 OldDACMask;
+
+ /* Assume unassignable VGA */
+ pATI->VGAAdapter = ATI_ADAPTER_NONE;
+
+ /* If no assignable VGA, return now */
+ if ((pATI != pVGA) && (!pVGA || (pVGA->Adapter > ATI_ADAPTER_VGA)))
+ return;
+
+ switch (pATI->Adapter)
+ {
+ case ATI_ADAPTER_8514A:
+ {
+ /*
+ * Assumption: Bit DISABPASSTHRU in ADVFUNC_CNTL is already
+ * off.
+ */
+ OldDACMask = inb(VGA_DAC_MASK);
+
+ if (inb(IBM_DAC_MASK) == OldDACMask)
+ {
+ outb(VGA_DAC_MASK, 0xA5U);
+ if (inb(IBM_DAC_MASK) == 0xA5U)
+ pATI->VGAAdapter = ATI_ADAPTER_VGA;
+ }
+
+ outb(VGA_DAC_MASK, OldDACMask);
+ }
+ break;
+
+ case ATI_ADAPTER_MACH8:
+ {
+ CARD16 ClockSel = inw(CLOCK_SEL);
+
+ if (ClockSel & DISABPASSTHRU)
+ outw(CLOCK_SEL, ClockSel & ~DISABPASSTHRU);
+
+ ProbeWaitIdleEmpty();
+
+ OldDACMask = inb(VGA_DAC_MASK);
+
+ if (inb(IBM_DAC_MASK) == OldDACMask)
+ {
+ outb(VGA_DAC_MASK, 0xA5U);
+ if (inb(IBM_DAC_MASK) == 0xA5U)
+ pATI->VGAAdapter = ATI_ADAPTER_VGA;
+ }
+
+ outb(VGA_DAC_MASK, OldDACMask);
+
+ if (ClockSel & DISABPASSTHRU)
+ outw(CLOCK_SEL, ClockSel);
+ }
+ break;
+
+ case ATI_ADAPTER_MACH32:
+ {
+ CARD16 ClockSel = inw(CLOCK_SEL),
+ MiscOptions = inw(MISC_OPTIONS);
+
+ if (ClockSel & DISABPASSTHRU)
+ outw(CLOCK_SEL, ClockSel & ~DISABPASSTHRU);
+ if (MiscOptions & (DISABLE_VGA | DISABLE_DAC))
+ outw(MISC_OPTIONS,
+ MiscOptions & ~(DISABLE_VGA | DISABLE_DAC));
+
+ ProbeWaitIdleEmpty();
+
+ OldDACMask = inb(VGA_DAC_MASK);
+
+ if (inb(IBM_DAC_MASK) == OldDACMask)
+ {
+ outb(VGA_DAC_MASK, 0xA5U);
+ if (inb(IBM_DAC_MASK) == 0xA5U)
+ pATI->VGAAdapter = ATI_ADAPTER_MACH32;
+ }
+
+ outb(VGA_DAC_MASK, OldDACMask);
+
+ if (ClockSel & DISABPASSTHRU)
+ outw(CLOCK_SEL, ClockSel);
+ if (MiscOptions & (DISABLE_VGA | DISABLE_DAC))
+ outw(MISC_OPTIONS, MiscOptions);
+ }
+ break;
+
+ case ATI_ADAPTER_MACH64:
+ {
+ CARD32 DACCntl = inr(DAC_CNTL);
+
+ if (!(DACCntl & DAC_VGA_ADR_EN))
+ outr(DAC_CNTL, DACCntl | DAC_VGA_ADR_EN);
+
+ OldDACMask = inb(VGA_DAC_MASK);
+
+ if (in8(M64_DAC_MASK) == OldDACMask)
+ {
+ outb(VGA_DAC_MASK, 0xA5U);
+ if (in8(M64_DAC_MASK) == 0xA5U)
+ pATI->VGAAdapter = ATI_ADAPTER_MACH64;
+ }
+
+ outb(VGA_DAC_MASK, OldDACMask);
+
+ if (!(DACCntl & DAC_VGA_ADR_EN))
+ outr(DAC_CNTL, DACCntl);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+ {
+ pATI->CPIO_VGAWonder = 0;
+ return;
+ }
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ ATIVGAWonderProbe(pVideo, pATI, p8514, ProbeFlags);
+ if (!pATI->CPIO_VGAWonder)
+ {
+ /*
+ * Some adapters are reputed to append ATI extended VGA registers
+ * to the VGA Graphics controller registers. In particular, 0x01CE
+ * cannot, in general, be used in a PCI environment due to routing
+ * of I/O through the bus tree.
+ */
+ pATI->CPIO_VGAWonder = GRAX;
+ ATIVGAWonderProbe(pVideo, pATI, p8514, ProbeFlags);
+ }
+ }
+
+ if (pATI == pVGA)
+ {
+ pATI->SharedVGA = TRUE;
+ return;
+ }
+
+ /* Assign the VGA to this adapter */
+ xfree(pVGA);
+ *ppVGA = pATI;
+
+ xf86MsgVerb(X_INFO, 3, ATI_NAME ": VGA assigned to this adapter.\n");
+}
+
+/*
+ * ATIClaimVGA --
+ *
+ * Attempt to assign a non-shareable VGA to an accelerator. If successful,
+ * update ProbeFlags array.
+ */
+static void
+ATIClaimVGA
+(
+ pciVideoPtr pVideo,
+ ATIPtr *ppVGA,
+ ATIPtr pATI,
+ ATIPtr p8514,
+ CARD8 *ProbeFlags,
+ int Detected
+)
+{
+ ATIAssignVGA(pVideo, ppVGA, pATI, p8514, ProbeFlags);
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+ return;
+
+ ATIClaimSparseIOBases(ProbeFlags, MonochromeIOBase, 48, Detected);
+ if (!pATI->CPIO_VGAWonder)
+ return;
+
+ ATIClaimSparseIOBases(ProbeFlags, pATI->CPIO_VGAWonder, 2, Detected);
+}
+
+/*
+ * ATIFindVGA --
+ *
+ * This function determines if a VGA associated with an ATI PCI adapter is
+ * shareable.
+ */
+static void
+ATIFindVGA
+(
+ pciVideoPtr pVideo,
+ ATIPtr *ppVGA,
+ ATIPtr *ppATI,
+ ATIPtr p8514,
+ CARD8 *ProbeFlags
+)
+{
+ ATIPtr pATI = *ppATI;
+
+ if (!*ppVGA)
+ {
+ /*
+ * An ATI PCI adapter has been detected at this point, and its VGA, if
+ * any, is shareable. Ensure the VGA isn't in sleep mode.
+ */
+ outb(GENENA, 0x16U);
+ outb(GENVS, 0x01U);
+ outb(GENENA, 0x0EU);
+
+ pATI = ATIVGAProbe(pATI);
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+ return;
+
+ ppVGA = ppATI;
+ }
+
+ ATIAssignVGA(pVideo, ppVGA, pATI, p8514, ProbeFlags);
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIProbe --
+ *
+ * This function is called once, at the start of the first server generation to
+ * do a minimal probe for supported hardware.
+ */
+Bool
+ATIProbe
+(
+ DriverPtr pDriver,
+ int flags
+)
+{
+ ATIPtr pATI, *ATIPtrs = NULL;
+ GDevPtr *GDevs, pGDev;
+ pciVideoPtr pVideo, *xf86PciVideoInfo = xf86GetPciVideoInfo();
+ pciConfigPtr pPCI;
+ ATIGDev *ATIGDevs = NULL, *pATIGDev;
+ ScrnInfoPtr pScreenInfo;
+ CARD32 PciReg;
+ Bool ProbeSuccess = FALSE;
+ Bool DoRage128 = FALSE, DoRadeon = FALSE;
+ int i, j, k;
+ int nGDev, nATIGDev = -1, nATIPtr = 0;
+ int Chipset;
+ ATIChipType Chip;
+
+#ifndef AVOID_CPIO
+
+ ATIPtr pVGA = NULL, p8514 = NULL;
+ ATIPtr pMach64[3] = {NULL, NULL, NULL};
+ pciConfigPtr *xf86PciInfo = xf86GetPciConfigInfo();
+ PortPtr PCIPorts = NULL;
+ int nPCIPort = 0;
+ CARD8 fChipsets[ATI_CHIPSET_MAX];
+ static const IOADDRESS Mach64SparseIOBases[] = {0x02ECU, 0x01CCU, 0x01C8U};
+ CARD8 ProbeFlags[LongPort(SPARSE_IO_BASE) + 1];
+
+ unsigned long BIOSBase;
+ static const CARD8 ATISignature[] = " 761295520";
+# define SignatureSize 10
+# define PrefixSize 0x50U
+# define BIOSSignature 0x30U
+ CARD8 BIOS[PrefixSize];
+# define BIOSWord(_n) (BIOS[_n] | (BIOS[(_n) + 1] << 8))
+
+#endif /* AVOID_CPIO */
+
+# define AddAdapter(_p) \
+ do \
+ { \
+ nATIPtr++; \
+ ATIPtrs = (ATIPtr *)xnfrealloc(ATIPtrs, SizeOf(ATIPtr) * nATIPtr); \
+ ATIPtrs[nATIPtr - 1] = (_p); \
+ (_p)->iEntity = -2; \
+ } while (0)
+
+#ifndef AVOID_CPIO
+
+ (void)memset(fChipsets, FALSE, SizeOf(fChipsets));
+
+#endif /* AVOID_CPIO */
+
+ if (!(flags & PROBE_DETECT))
+ {
+ /*
+ * Get a list of XF86Config device sections whose "Driver" is either
+ * not specified, or specified as this driver. From this list,
+ * eliminate those device sections that specify a "Chipset" or a
+ * "ChipID" not recognised by the driver. Those device sections that
+ * specify a "ChipRev" without a "ChipID" are also weeded out.
+ */
+ nATIGDev = 0;
+ if ((nGDev = xf86MatchDevice(ATI_NAME, &GDevs)) > 0)
+ {
+ ATIGDevs = (ATIGDevPtr)xnfcalloc(nGDev, SizeOf(ATIGDev));
+
+ for (i = 0, pATIGDev = ATIGDevs; i < nGDev; i++)
+ {
+ pGDev = GDevs[i];
+ Chipset = ATIIdentProbe(pGDev->chipset);
+ if (Chipset == -1)
+ continue;
+
+ if ((pGDev->chipID > (int)((CARD16)(-1))) ||
+ (pGDev->chipRev > (int)((CARD8)(-1))))
+ continue;
+
+ if (pGDev->chipID >= 0)
+ {
+ if (ATIChipID(pGDev->chipID, 0) == ATI_CHIP_Mach64)
+ continue;
+ }
+ else
+ {
+ if (pGDev->chipRev >= 0)
+ continue;
+ }
+
+ pATIGDev->pGDev = pGDev;
+ pATIGDev->Chipset = Chipset;
+ nATIGDev++;
+ pATIGDev++;
+
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": Candidate \"Device\" section \"%s\".\n",
+ pGDev->identifier);
+
+#ifndef AVOID_CPIO
+
+ fChipsets[Chipset] = TRUE;
+
+#endif /* AVOID_CPIO */
+
+ }
+
+ xfree(GDevs);
+
+ if (!nATIGDev)
+ {
+ xfree(ATIGDevs);
+ ATIGDevs = NULL;
+ }
+ }
+
+ if (xf86MatchDevice(R128_NAME, NULL) > 0)
+ DoRage128 = TRUE;
+ if (xf86MatchDevice(RADEON_NAME, NULL) > 0)
+ DoRadeon = TRUE;
+ }
+
+#ifndef AVOID_CPIO
+
+ /*
+ * Collect hardware information. This must be done with care to avoid
+ * lockups due to overlapping I/O port assignments.
+ *
+ * First, scan PCI configuration space for registered I/O ports (which will
+ * be block I/O bases). Each such port is used to generate a list of
+ * sparse I/O bases it precludes. This list is then used to decide whether
+ * or not certain sparse I/O probes are done. Unfortunately, this assumes
+ * that any registered I/O base actually reserves upto the full 256 ports
+ * allowed by the PCI specification. This assumption holds true for PCI
+ * Mach64, but probably doesn't for other device types. For some things,
+ * such as video devices, the number of ports a base represents is
+ * determined by the server's PCI probe, but, for other devices, this
+ * cannot be done by a user-level process without jeopardizing system
+ * integrity. This information should ideally be retrieved from the OS's
+ * own PCI probe (if any), but there's currently no portable way of doing
+ * so. The following allows sparse I/O probes to be forced in certain
+ * circumstances when an appropriate chipset specification is used in any
+ * XF86Config Device section.
+ *
+ * Note that this is not bullet-proof. Lockups can still occur, but they
+ * will usually be due to devices that are misconfigured to respond to the
+ * same I/O ports as 8514/A's or ATI sparse I/O devices without registering
+ * them in PCI configuration space.
+ */
+ if (nATIGDev)
+ {
+ if (xf86PciVideoInfo)
+ {
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if (pVideo->vendor == PCI_VENDOR_ATI)
+ continue;
+
+ pPCI = pVideo->thisCard;
+
+ ATIScanPCIBases(&PCIPorts, &nPCIPort,
+ &pPCI->pci_base0, pVideo->size,
+ (pciReadLong(pPCI->tag, PCI_CMD_STAT_REG) &
+ PCI_CMD_IO_ENABLE) ? 0 : Allowed);
+ }
+ }
+
+ /* Check non-video PCI devices for I/O bases */
+ if (xf86PciInfo)
+ {
+ for (i = 0; (pPCI = xf86PciInfo[i++]); )
+ {
+ if ((pPCI->pci_vendor == PCI_VENDOR_ATI) ||
+ (pPCI->pci_base_class == PCI_CLASS_BRIDGE) ||
+ (pPCI->pci_header_type &
+ ~GetByte(PCI_HEADER_MULTIFUNCTION, 2)))
+ continue;
+
+ ATIScanPCIBases(&PCIPorts, &nPCIPort,
+ &pPCI->pci_base0, pPCI->basesize,
+ (pciReadLong(pPCI->tag, PCI_CMD_STAT_REG) &
+ PCI_CMD_IO_ENABLE) ? 0 : Allowed);
+ }
+ }
+
+ /* Generate ProbeFlags array from list of registered PCI I/O bases */
+ (void)memset(ProbeFlags, Allowed | DoProbe, SizeOf(ProbeFlags));
+ for (i = 0; i < nPCIPort; i++)
+ {
+ CARD32 Base = PCIPorts[i].Base;
+ CARD16 Count = (1 << PCIPorts[i].Size) - 1;
+ CARD8 ProbeFlag = PCIPorts[i].Flag;
+
+ /*
+ * The following reduction of Count is based on the assumption that
+ * PCI-registered I/O port ranges do not overlap.
+ */
+ for (j = 0; j < nPCIPort; j++)
+ {
+ CARD32 Base2 = PCIPorts[j].Base;
+
+ if (Base < Base2)
+ while ((Base + Count) >= Base2)
+ Count >>= 1;
+ }
+
+ Base = LongPort(Base);
+ Count = LongPort((Count | IO_BYTE_SELECT) + 1);
+ while (Count--)
+ ProbeFlags[Base++] &= ProbeFlag;
+ }
+
+ xfree(PCIPorts);
+
+ /*
+ * A note on probe strategy. I/O and memory response by certain PCI
+ * devices has been disabled by the common layer at this point,
+ * including any devices this driver might be interested in. The
+ * following does sparse I/O probes, followed by block I/O probes.
+ * Block I/O probes are dictated by what is found to be of interest in
+ * PCI configuration space. All this will detect ATI adapters that do
+ * not implement this disablement, pre-PCI or not.
+ *
+ * PCI configuration space is then scanned again for ATI devices that
+ * failed to be detected the first time around. Each such device is
+ * probed for again, this time with I/O temporarily enabled through
+ * PCI.
+ */
+ if (ATICheckSparseIOBases(NULL, ProbeFlags, ATTRX, 16, TRUE) ==
+ DoProbe)
+ {
+ pATI = ATIVGAProbe(NULL);
+ if (pATI->Adapter == ATI_ADAPTER_NONE)
+ {
+ xfree(pATI);
+
+ xf86MsgVerb(X_INFO, 4,
+ ATI_NAME ": Unshared VGA not detected.\n");
+ }
+ else
+ {
+ /*
+ * Claim all MDA/HGA/CGA/EGA/VGA I/O ports. This might need to
+ * be more selective.
+ */
+ ATIClaimSparseIOBases(ProbeFlags, MonochromeIOBase, 48,
+ DetectedVGA);
+
+ pVGA = pATI;
+ strcpy(Identifier, "Unshared VGA");
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s detected.\n", Identifier);
+ }
+ }
+ else
+ {
+ xf86MsgVerb(X_INFO, 2, ATI_NAME ": Unshared VGA not probed.\n");
+ }
+
+ if (ATICheckSparseIOBases(NULL, ProbeFlags, 0x02E8U, 8,
+ fChipsets[ATI_CHIPSET_IBM8514] ||
+ fChipsets[ATI_CHIPSET_MACH8] ||
+ fChipsets[ATI_CHIPSET_MACH32]) == DoProbe)
+ {
+ if ((pATI = ATI8514Probe(NULL)))
+ {
+ strcpy(Identifier, "Unshared 8514/A");
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s detected.\n", Identifier);
+
+ AddAdapter(p8514 = pATI);
+
+ if ((pATI->VGAAdapter != ATI_ADAPTER_NONE) ||
+ (pATI->Coprocessor != ATI_CHIP_NONE))
+ ATIClaimVGA(NULL, &pVGA, pATI, p8514, ProbeFlags,
+ Detected8514A);
+
+ ATIClaimSparseIOBases(ProbeFlags, 0x02E8U, 8, Detected8514A);
+ }
+ else
+ {
+ xf86MsgVerb(X_INFO, 4,
+ ATI_NAME ": Unshared 8514/A not detected.\n");
+ }
+ }
+ else
+ {
+ xf86MsgVerb(X_INFO, 2,
+ ATI_NAME ": Unshared 8514/A not probed.\n");
+ }
+
+ for (i = 0; i < NumberOf(Mach64SparseIOBases); i++)
+ {
+ if (ATICheckSparseIOBases(NULL, ProbeFlags, Mach64SparseIOBases[i],
+ 4, fChipsets[ATI_CHIPSET_MACH64]) != DoProbe)
+ {
+ xf86MsgVerb(X_INFO, 2,
+ ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not"
+ " probed.\n",
+ Mach64SparseIOBases[i]);
+ continue;
+ }
+
+ pATI = ATIMach64Probe(NULL, Mach64SparseIOBases[i], SPARSE_IO, 0);
+ if (!pATI)
+ {
+ xf86MsgVerb(X_INFO, 4,
+ ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not"
+ " detected.\n", Mach64SparseIOBases[i]);
+ continue;
+ }
+
+ sprintf(Identifier, "Unshared Mach64 at sparse PIO base 0x%04lX",
+ Mach64SparseIOBases[i]);
+ xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n", Identifier);
+
+ AddAdapter(pMach64[i] = pATI);
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIClaimVGA(NULL, &pVGA, pATI, p8514, ProbeFlags,
+ DetectedMach64);
+
+ ATIClaimSparseIOBases(ProbeFlags, Mach64SparseIOBases[i], 4,
+ DetectedMach64);
+ }
+ }
+
+#endif /* AVOID_CPIO */
+
+ if (xf86PciVideoInfo)
+ {
+ if (nATIGDev)
+ {
+
+#ifndef AVOID_NON_PCI
+
+#ifdef AVOID_CPIO
+
+ /* PCI sparse I/O adapters can still be used through MMIO */
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType == PCI_CHIP_MACH32) ||
+ pVideo->size[1])
+ continue;
+
+ pPCI = pVideo->thisCard;
+ PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
+
+ /* Possibly fix block I/O indicator */
+ if (PciReg & 0x00000004U)
+ pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
+ PciReg & ~0x00000004U);
+
+ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
+
+ /*
+ * The CPIO base used by the adapter is of little concern here.
+ */
+ pATI = ATIMach64Probe(pVideo, 0, SPARSE_IO, Chip);
+ if (!pATI)
+ continue;
+
+ sprintf(Identifier,
+ "Unshared PCI sparse I/O Mach64 in slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s detected through Block 0 at 0x%08X.\n",
+ Identifier, pATI->Block0Base);
+ AddAdapter(pATI);
+ pATI->PCIInfo = pVideo;
+ }
+
+#endif /* AVOID_CPIO */
+
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType == PCI_CHIP_MACH32) ||
+ !pVideo->size[1])
+ continue;
+
+ /* For now, ignore Rage128's and Radeon's */
+ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
+ if (Chip > ATI_CHIP_Mach64)
+ continue;
+
+ pPCI = pVideo->thisCard;
+
+ /*
+ * Possibly fix block I/O indicator in PCI configuration space.
+ */
+ PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
+ if (!(PciReg & 0x00000004U))
+ pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
+ PciReg | 0x00000004U);
+
+ pATI =
+ ATIMach64Probe(pVideo, pVideo->ioBase[1], BLOCK_IO, Chip);
+ if (!pATI)
+ continue;
+
+ sprintf(Identifier, "Unshared PCI/AGP Mach64 in slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s detected.\n", Identifier);
+ AddAdapter(pATI);
+
+#ifndef AVOID_CPIO
+
+ /* This is probably not necessary */
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIClaimVGA(pVideo, &pVGA, pATI, p8514,
+ ProbeFlags, DetectedMach64);
+
+#endif /* AVOID_CPIO */
+
+ }
+
+#endif /* AVOID_NON_PCI */
+
+#ifndef AVOID_CPIO
+
+ /*
+ * This is the second pass through PCI configuration space. Much
+ * of this is verbiage to deal with potential situations that are
+ * very unlikely to occur in practice.
+ *
+ * First, look for non-ATI shareable VGA's. For now, these must
+ * the primary device.
+ */
+ if (ATICheckSparseIOBases(NULL, ProbeFlags, ATTRX, 16, TRUE) ==
+ DoProbe)
+ {
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor == PCI_VENDOR_ATI) ||
+ !xf86IsPrimaryPci(pVideo))
+ continue;
+
+ if (!xf86CheckPciSlot(pVideo->bus,
+ pVideo->device,
+ pVideo->func))
+ continue;
+
+ xf86SetPciVideo(pVideo, MEM_IO);
+
+ pATI = ATIVGAProbe(NULL);
+ if (pATI->Adapter == ATI_ADAPTER_NONE)
+ {
+ xfree(pATI);
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI/AGP VGA compatible in slot"
+ " %d:%d:%d could not be detected!\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ }
+ else
+ {
+ sprintf(Identifier,
+ "Shared non-ATI VGA in PCI/AGP slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n",
+ Identifier);
+ AddAdapter(pATI);
+ pATI->SharedVGA = TRUE;
+ pATI->BusType = ATI_BUS_PCI;
+ pATI->PCIInfo = pVideo;
+ }
+
+ xf86SetPciVideo(NULL, NONE);
+ }
+ }
+
+ /* Next, look for PCI Mach32's */
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType != PCI_CHIP_MACH32))
+ continue;
+
+ switch (ATICheckSparseIOBases(pVideo, ProbeFlags,
+ 0x02E8U, 8, TRUE))
+ {
+ case 0:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach32 in slot %d:%d:%d will not"
+ " be enabled\n because it conflicts with a"
+ " non-video PCI/AGP device.\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ break;
+
+ case Detected8514A:
+ if ((p8514->BusType >= ATI_BUS_PCI) && !p8514->PCIInfo)
+ p8514->PCIInfo = pVideo;
+ else
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach32 in slot %d:%d:%d will"
+ " not be enabled\n because it conflicts with"
+ " another %s %s.\n",
+ pVideo->bus, pVideo->device, pVideo->func,
+ ATIBusNames[p8514->BusType],
+ ATIAdapterNames[p8514->Adapter]);
+ break;
+
+ case DetectedMach64:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach32 in slot %d:%d:%d will not"
+ " be enabled\n because it conflicts with a Mach64"
+ " at I/O base 0x02EC.\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ break;
+
+ default: /* Must be DoProbe */
+ if (!xf86CheckPciSlot(pVideo->bus,
+ pVideo->device,
+ pVideo->func))
+ continue;
+
+ xf86SetPciVideo(pVideo, MEM_IO);
+
+ if (!(pATI = ATI8514Probe(pVideo)))
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach32 in slot %d:%d:%d could"
+ " not be detected!\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ else
+ {
+ sprintf(Identifier,
+ "Shared 8514/A in PCI slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s detected.\n", Identifier);
+ if (pATI->Adapter != ATI_ADAPTER_MACH32)
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach32 in slot %d:%d:%d"
+ " could only be detected as an %s!\n",
+ pVideo->bus, pVideo->device, pVideo->func,
+ ATIAdapterNames[pATI->Adapter]);
+
+ AddAdapter(pATI);
+ pATI->SharedAccelerator = TRUE;
+
+ if ((pATI->VGAAdapter != ATI_ADAPTER_NONE) ||
+ (pATI->Coprocessor != ATI_CHIP_NONE))
+ ATIFindVGA(pVideo, &pVGA, &pATI, p8514,
+ ProbeFlags);
+ }
+
+ xf86SetPciVideo(NULL, NONE);
+ break;
+ }
+ }
+
+ /* Next, look for sparse I/O Mach64's */
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType == PCI_CHIP_MACH32) ||
+ pVideo->size[1])
+ continue;
+
+ pPCI = pVideo->thisCard;
+ PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
+ j = PciReg & 0x03U;
+ if (j == 0x03U)
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d cannot be"
+ " enabled\n because it has neither a block, nor a"
+ " sparse, I/O base.\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ else switch(ATICheckSparseIOBases(pVideo, ProbeFlags,
+ Mach64SparseIOBases[j], 4, TRUE))
+ {
+ case 0:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d will not"
+ " be enabled\n because it conflicts with another"
+ " non-video PCI device.\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ break;
+
+ case Detected8514A:
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d will not"
+ " be enabled\n because it conflicts with an %s.\n",
+ pVideo->bus, pVideo->device, pVideo->func,
+ ATIAdapterNames[p8514->Adapter]);
+ break;
+
+ case DetectedMach64:
+ pATI = pMach64[j];
+ if ((pATI->BusType >= ATI_BUS_PCI) && !pATI->PCIInfo)
+ pATI->PCIInfo = pVideo;
+ else
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d will"
+ " not be enabled\n because it conflicts with"
+ " another %s Mach64 at sparse I/O base"
+ " 0x%04X.\n",
+ pVideo->bus, pVideo->device, pVideo->func,
+ ATIBusNames[pATI->BusType],
+ Mach64SparseIOBases[j]);
+ break;
+
+ default: /* Must be DoProbe */
+ if (!xf86CheckPciSlot(pVideo->bus,
+ pVideo->device,
+ pVideo->func))
+ continue;
+
+ /* Possibly fix block I/O indicator */
+ if (PciReg & 0x00000004U)
+ pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
+ PciReg & ~0x00000004U);
+
+ xf86SetPciVideo(pVideo, MEM_IO);
+
+ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
+ pATI = ATIMach64Probe(pVideo, Mach64SparseIOBases[j],
+ SPARSE_IO, Chip);
+ if (!pATI)
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d could"
+ " not be detected!\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ else
+ {
+ sprintf(Identifier,
+ "Shared PCI Mach64 in slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s with sparse PIO base 0x%04X"
+ " detected.\n", Identifier,
+ Mach64SparseIOBases[j]);
+ AddAdapter(pATI);
+ pATI->SharedAccelerator = TRUE;
+ pATI->PCIInfo = pVideo;
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIFindVGA(pVideo, &pVGA, &pATI, p8514,
+ ProbeFlags);
+ }
+
+ xf86SetPciVideo(NULL, NONE);
+ break;
+ }
+ }
+
+#else /* AVOID_CPIO */
+
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType == PCI_CHIP_MACH32) ||
+ pVideo->size[1])
+ continue;
+
+ /* Check if this one has already been detected */
+ for (j = 0; j < nATIPtr; j++)
+ {
+ pATI = ATIPtrs[j];
+ if (pATI->PCIInfo == pVideo)
+ goto SkipThisSlot;
+ }
+
+ if (!xf86CheckPciSlot(pVideo->bus,
+ pVideo->device,
+ pVideo->func))
+ continue;
+
+ xf86SetPciVideo(pVideo, MEM_IO);
+
+ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
+
+ /* The adapter's CPIO base is of little concern here */
+ pATI = ATIMach64Probe(pVideo, 0, SPARSE_IO, Chip);
+ if (pATI)
+ {
+ sprintf(Identifier, "Shared PCI Mach64 in slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s with Block 0 base 0x%08X detected.\n",
+ Identifier, pATI->Block0Base);
+ AddAdapter(pATI);
+ pATI->SharedAccelerator = TRUE;
+ pATI->PCIInfo = pVideo;
+ }
+ else
+ {
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI Mach64 in slot %d:%d:%d could not be"
+ " detected!\n",
+ pVideo->bus, pVideo->device, pVideo->func);
+ }
+
+ xf86SetPciVideo(NULL, NONE);
+
+ SkipThisSlot:;
+ }
+
+#endif /* AVOID_CPIO */
+
+ }
+
+ /* Lastly, look for block I/O devices */
+ for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
+ {
+ if ((pVideo->vendor != PCI_VENDOR_ATI) ||
+ (pVideo->chipType == PCI_CHIP_MACH32) ||
+ !pVideo->size[1])
+ continue;
+
+ /* Check for Rage128's, Radeon's and later adapters */
+ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
+ if (Chip > ATI_CHIP_Mach64)
+ {
+ switch (Chip)
+ {
+ case ATI_CHIP_RAGE128GL:
+ case ATI_CHIP_RAGE128VR:
+ case ATI_CHIP_RAGE128PROULTRA:
+ case ATI_CHIP_RAGE128PROGL:
+ case ATI_CHIP_RAGE128PROVR:
+ case ATI_CHIP_RAGE128MOBILITY3:
+ case ATI_CHIP_RAGE128MOBILITY4:
+ DoRage128 = TRUE;
+ continue;
+
+ case ATI_CHIP_RADEON:
+ case ATI_CHIP_RADEONVE:
+ case ATI_CHIP_RADEONMOBILITY6:
+ case ATI_CHIP_RADEONMOBILITY7:
+ case ATI_CHIP_R200:
+ case ATI_CHIP_RV200:
+ case ATI_CHIP_RV250:
+ case ATI_CHIP_RADEONMOBILITY9:
+ case ATI_CHIP_R300:
+ DoRadeon = TRUE;
+ continue;
+
+ case ATI_CHIP_HDTV:
+ default:
+ continue;
+ }
+ }
+
+ if (!nATIGDev)
+ continue;
+
+ /* Check if this one has already been detected */
+ for (j = 0; j < nATIPtr; j++)
+ {
+ pATI = ATIPtrs[j];
+ if (pATI->CPIOBase == pVideo->ioBase[1])
+ goto SetPCIInfo;
+ }
+
+ if (!xf86CheckPciSlot(pVideo->bus, pVideo->device, pVideo->func))
+ continue;
+
+ /* Probe for it */
+ xf86SetPciVideo(pVideo, MEM_IO);
+
+ pATI = ATIMach64Probe(pVideo, pVideo->ioBase[1], BLOCK_IO, Chip);
+ if (pATI)
+ {
+ sprintf(Identifier, "Shared PCI/AGP Mach64 in slot %d:%d:%d",
+ pVideo->bus, pVideo->device, pVideo->func);
+ xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n",
+ Identifier);
+ AddAdapter(pATI);
+ pATI->SharedAccelerator = TRUE;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ ATIFindVGA(pVideo, &pVGA, &pATI, p8514, ProbeFlags);
+
+#endif /* AVOID_CPIO */
+
+ }
+
+ xf86SetPciVideo(NULL, NONE);
+
+ if (!pATI)
+ {
+ xf86Msg(X_WARNING,
+ ATI_NAME ": PCI/AGP Mach64 in slot %d:%d:%d could not be"
+ " detected!\n", pVideo->bus, pVideo->device, pVideo->func);
+ continue;
+ }
+
+ SetPCIInfo:
+ pATI->PCIInfo = pVideo;
+ }
+ }
+
+#ifndef AVOID_CPIO
+
+ /*
+ * At this point, if there's a non-shareable VGA with its own framebuffer,
+ * find out if it's an ATI VGA Wonder.
+ */
+ do
+ {
+ if (!nATIGDev || !pVGA || (pVGA->VGAAdapter > ATI_ADAPTER_VGA))
+ break;
+
+ /* If it has not been assigned to a coprocessor, keep track of it */
+ if (pVGA->Coprocessor == ATI_CHIP_NONE)
+ AddAdapter(pVGA);
+
+ /*
+ * A VGA should have installed its int 10 vector. Use that to find the
+ * VGA BIOS. If this fails, scan all legacy BIOS segments, in 512-byte
+ * increments.
+ */
+ if (xf86ReadBIOS(0U, 0x42U, BIOS, 2) != 2)
+ goto NoVGAWonder;
+
+ pATI = NULL;
+ BIOSBase = 0;
+ if (!(BIOS[0] & 0x1FU)) /* Otherwise there's no 512-byte alignment */
+ BIOSBase = ((BIOS[1] << 8) | BIOS[0]) << 4;
+
+ /* Look for its BIOS */
+ for(; ; BIOSBase += 0x00000200U)
+ {
+ if (!BIOSBase)
+ goto SkipBiosSegment;
+
+ if (BIOSBase >= 0x000F8000U)
+ goto NoVGAWonder;
+
+ /* Skip over those that are already known */
+ for (i = 0; i < nATIPtr; i++)
+ if (ATIPtrs[i]->BIOSBase == BIOSBase)
+ goto SkipBiosSegment;
+
+ /* Get first 80 bytes of video BIOS */
+ if (xf86ReadBIOS(BIOSBase, 0, BIOS, SizeOf(BIOS)) !=
+ SizeOf(BIOS))
+ goto NoVGAWonder;
+
+ if ((BIOS[0x00U] != 0x55U) || (BIOS[0x01U] != 0xAAU))
+ goto SkipBiosSegment;
+
+ if ((BIOS[0x1EU] == 'I') &&
+ (BIOS[0x1FU] == 'B') &&
+ (BIOS[0x20U] == 'M'))
+ break;
+
+ /* XXX Should PCI BIOS signature be checked for here ? */
+ if ((BIOS[0x20U] == 'P') &&
+ (BIOS[0x21U] == 'C') &&
+ (BIOS[0x22U] == 'I'))
+ break;
+
+ SkipBiosSegment:
+ if (pATI)
+ continue;
+
+ pATI = pVGA;
+ BIOSBase = 0x000C0000U - 0x00000200U;
+ }
+
+ pVGA->BIOSBase = BIOSBase;
+
+ /* Look for the ATI signature string */
+ if (memcmp(BIOS + BIOSSignature, ATISignature, SignatureSize))
+ break;
+
+ if (BIOS[0x40U] != '3')
+ break;
+
+ switch (BIOS[0x41U])
+ {
+ case '1':
+ /* This is a Mach8 or VGA Wonder adapter of some kind */
+ if ((BIOS[0x43U] >= '1') && (BIOS[0x43U] <= '6'))
+ pVGA->Chip = BIOS[0x43U] - ('1' - ATI_CHIP_18800);
+
+ switch (BIOS[0x43U])
+ {
+ case '1': /* ATI_CHIP_18800 */
+ pVGA->VGAOffset = 0xB0U;
+ pVGA->VGAAdapter = ATI_ADAPTER_V3;
+ break;
+
+ case '2': /* ATI_CHIP_18800_1 */
+ pVGA->VGAOffset = 0xB0U;
+ if (BIOS[0x42U] & 0x10U)
+ pVGA->VGAAdapter = ATI_ADAPTER_V5;
+ else
+ pVGA->VGAAdapter = ATI_ADAPTER_V4;
+ break;
+
+ case '3': /* ATI_CHIP_28800_2 */
+ case '4': /* ATI_CHIP_28800_4 */
+ case '5': /* ATI_CHIP_28800_5 */
+ case '6': /* ATI_CHIP_28800_6 */
+ pVGA->VGAOffset = 0xA0U;
+ if (BIOS[0x44U] & 0x80U)
+ pVGA->VGAAdapter = ATI_ADAPTER_XL;
+ else
+ pVGA->VGAAdapter = ATI_ADAPTER_PLUS;
+ break;
+
+ case 'a': /* A crippled Mach32 */
+ case 'b':
+ case 'c':
+ pVGA->VGAOffset = 0x80U;
+ pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
+ ATIMach32ChipID(pVGA);
+ ProbeWaitIdleEmpty();
+ if (inw(SUBSYS_STAT) != (CARD16)(-1))
+ pVGA->ChipHasSUBSYS_CNTL = TRUE;
+ break;
+#if 0
+ case ' ': /* A crippled Mach64 */
+ pVGA->VGAOffset = 0x80U;
+ pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
+ ATIMach64ChipID(pVGA, 0);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (pVGA->VGAAdapter == ATI_ADAPTER_NONE)
+ break;
+
+ /* Set VGA Wonder I/O port */
+ pVGA->CPIO_VGAWonder = BIOSWord(0x10U) & SPARSE_IO_PORT;
+ if (!pVGA->CPIO_VGAWonder)
+ pVGA->CPIO_VGAWonder = 0x01CEU;
+
+ ATIVGAWonderProbe(NULL, pVGA, p8514, ProbeFlags);
+ break;
+#if 0
+ case '2':
+ pVGA->VGAOffset = 0xB0U; /* Presumably */
+ pVGA->VGAAdapter = ATI_ADAPTER_EGA_PLUS;
+ break;
+
+ case '3':
+ pVGA->VGAOffset = 0xB0U; /* Presumably */
+ pVGA->VGAAdapter = ATI_ADAPTER_BASIC;
+ break;
+
+ case '?': /* A crippled Mach64 */
+ pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
+ ATIMach64ChipID(pVGA, 0);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (pVGA->Adapter <= ATI_ADAPTER_VGA)
+ pVGA->Adapter = pVGA->VGAAdapter;
+
+NoVGAWonder:;
+ } while (0);
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Re-order list of detected devices so that the primary device is before
+ * any other PCI device.
+ */
+ for (i = 0; i < nATIPtr; i++)
+ {
+ if (!ATIPtrs[i]->PCIInfo)
+ continue;
+
+ for (j = i; j < nATIPtr; j++)
+ {
+ pATI = ATIPtrs[j];
+ if (!xf86IsPrimaryPci(pATI->PCIInfo))
+ continue;
+
+ for (; j > i; j--)
+ ATIPtrs[j] = ATIPtrs[j - 1];
+ ATIPtrs[j] = pATI;
+ break;
+ }
+
+ break;
+ }
+
+ if (flags & PROBE_DETECT)
+ {
+ /*
+ * No XF86Config information available, so use the default Chipset of
+ * "ati", and as many device sections as there are adapters.
+ */
+ for (i = 0; i < nATIPtr; i++)
+ {
+ pATI = ATIPtrs[i];
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->Adapter != ATI_ADAPTER_VGA) &&
+ ((pATI->Adapter != ATI_ADAPTER_8514A) ||
+ ((pATI->VGAAdapter != ATI_ADAPTER_VGA) &&
+ (pATI->VGAAdapter != ATI_ADAPTER_NONE))))
+
+#endif /* AVOID_CPIO */
+
+ {
+ ProbeSuccess = TRUE;
+ pGDev = xf86AddDeviceToConfigure(ATI_DRIVER_NAME,
+ pATI->PCIInfo, ATI_CHIPSET_ATI);
+ if (pGDev)
+ {
+ /* Fill in additional information */
+ pGDev->vendor = ATI_NAME;
+ pGDev->chipset = (char *)ATIChipsetNames[ATI_CHIPSET_ATI];
+ if (!pATI->PCIInfo)
+ pGDev->busID = NULL;
+ }
+ }
+
+ xfree(pATI);
+ }
+ }
+ else
+ {
+ /*
+ * Assign detected devices to XF86Config Device sections. This is done
+ * by comparing certain Device section specifications against the
+ * corresponding adapter information. Begin with those specifications
+ * that are independent of the adapter's bus location.
+ */
+ for (i = 0, pATIGDev = ATIGDevs; i < nATIGDev; i++, pATIGDev++)
+ {
+ pGDev = pATIGDev->pGDev;
+
+ for (j = 0; j < nATIPtr; j++)
+ {
+ pATI = ATIPtrs[j];
+
+ /*
+ * First check the Chipset specification. The placement of
+ * "break" and "continue" statements here is carefully chosen
+ * to produce the intended behaviour for each Chipset value.
+ */
+ switch (pATIGDev->Chipset)
+ {
+ case ATI_CHIPSET_ATI:
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter == ATI_ADAPTER_VGA)
+ continue;
+ if (pATI->Adapter != ATI_ADAPTER_8514A)
+ break;
+ /* Fall through */
+
+ case ATI_CHIPSET_ATIVGA:
+ if (pATI->VGAAdapter == ATI_ADAPTER_VGA)
+ continue;
+ /* Fall through */
+
+ case ATI_CHIPSET_IBMVGA:
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+ continue;
+ break;
+
+ case ATI_CHIPSET_VGAWONDER:
+ if (!pATI->CPIO_VGAWonder)
+ continue;
+ break;
+
+ case ATI_CHIPSET_IBM8514:
+ if (pATI->Adapter == ATI_ADAPTER_8514A)
+ break;
+ /* Fall through */
+
+ case ATI_CHIPSET_MACH8:
+ if (pATI->Adapter == ATI_ADAPTER_MACH8)
+ break;
+ /* Fall through */
+
+ case ATI_CHIPSET_MACH32:
+ if (pATI->Adapter == ATI_ADAPTER_MACH32)
+ break;
+ continue;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CHIPSET_MACH64:
+ if (pATI->Adapter == ATI_ADAPTER_MACH64)
+ break;
+ continue;
+
+ default:
+ continue;
+ }
+
+ /*
+ * The ChipID and ChipRev specifications are compared next.
+ * First, require these to be unspecified for anything other
+ * than Mach32 or Mach64 adapters. ChipRev is also required to
+ * be unspecified for Mach32's. ChipID is optional for
+ * Mach32's, and both specifications are optional for Mach64's.
+ * Lastly, allow both specifications to override their detected
+ * value in the case of Mach64 adapters whose ChipID is
+ * unrecognised.
+ */
+ pVideo = pATI->PCIInfo;
+ if (pGDev->chipID >= 0)
+ {
+ if ((pATI->ChipType != pGDev->chipID) &&
+ (!pVideo || (pGDev->chipID != pVideo->chipType)))
+ {
+ if ((pATI->Adapter != ATI_ADAPTER_MACH64) ||
+ (pATI->Chip != ATI_CHIP_Mach64))
+ continue;
+
+ Chip = ATIChipID(pGDev->chipID, 0);
+ if ((Chip <= ATI_CHIP_264GTB) ||
+ (Chip == ATI_CHIP_Mach64))
+ continue;
+ }
+ if ((pGDev->chipRev >= 0) &&
+ (pATI->ChipRev != pGDev->chipRev) &&
+ (!pVideo || (pGDev->chipRev != pVideo->chipRev) ||
+ (pGDev->chipID != pVideo->chipType)))
+ {
+ if (pATI->Chip < ATI_CHIP_264CT)
+ continue;
+
+ if (pATI->Chip != ATI_CHIP_Mach64)
+ {
+ /*
+ * There are two foundry codes for UMC. Some
+ * adapters will advertise one in CONFIG_CHIP_ID
+ * and the other in PCI configuration space. For
+ * matching purposes, make both codes compare
+ * equal.
+ */
+# define UMC_IGNORE \
+ (ATI_FOUNDRY_UMC ^ ATI_FOUNDRY_UMCA)
+# define UMC_NOCARE \
+ GetBits(SetBits(UMC_IGNORE, CFG_CHIP_FOUNDRY), \
+ CFG_CHIP_REV)
+
+ if ((pATI->ChipRev ^ pGDev->chipRev) & ~UMC_NOCARE)
+ continue;
+
+ if ((pATI->ChipFoundry != ATI_FOUNDRY_UMC) &&
+ (pATI->ChipFoundry != ATI_FOUNDRY_UMCA))
+ continue;
+
+ k = GetBits(pGDev->chipRev,
+ GetBits(CFG_CHIP_FOUNDRY, CFG_CHIP_REV));
+ if ((k != ATI_FOUNDRY_UMC) &&
+ (k != ATI_FOUNDRY_UMCA))
+ continue;
+ }
+ }
+ }
+
+ /*
+ * IOBase is next. This is the first specification that is
+ * potentially dependent on bus location. It is only allowed
+ * for Mach64 adapters, and is optional.
+ */
+ if (pGDev->IOBase && (pATI->CPIOBase != pGDev->IOBase))
+ continue;
+
+ /*
+ * Compare BusID's. This specification is only allowed for PCI
+ * Mach32's or Mach64's and is optional.
+ */
+ if (pGDev->busID && pGDev->busID[0])
+ {
+ pVideo = pATI->PCIInfo;
+
+#ifndef AVOID_CPIO
+
+ if (!pVideo)
+ continue;
+
+#endif /* AVOID_CPIO */
+
+ if (!xf86ComparePciBusString(pGDev->busID,
+ pVideo->bus, pVideo->device, pVideo->func))
+ continue;
+ }
+
+ /*
+ * Ensure no two adapters are assigned to the same XF86Config
+ * Device section.
+ */
+ if (pATIGDev->iATIPtr)
+ {
+ if (pATIGDev->iATIPtr < 0)
+ break;
+
+ xf86Msg(X_ERROR,
+ ATI_NAME ": XF86Config Device section \"%s\" may not"
+ " be assigned to more than one adapter.\n",
+ pGDev->identifier);
+ pATIGDev->iATIPtr = -1;
+ break;
+ }
+
+ /* Assign adapter */
+ pATIGDev->iATIPtr = j + 1;
+
+ /*
+ * For compatibility with previous releases, assign the first
+ * applicable adapter if there is only one Device section.
+ */
+ if (nATIGDev == 1)
+ break;
+ }
+ }
+
+ /*
+ * Ensure no two XF86Config Device sections are assigned to the same
+ * adapter. Then, generate screens for any that are left.
+ */
+ for (i = 0, pATIGDev = ATIGDevs; i < nATIGDev; i++, pATIGDev++)
+ {
+ pGDev = pATIGDev->pGDev;
+
+ j = pATIGDev->iATIPtr;
+ if (j <= 0)
+ continue;
+
+ for (k = i; ++k < nATIGDev; )
+ {
+ if (j == ATIGDevs[k].iATIPtr)
+ {
+ xf86Msg(X_ERROR,
+ ATI_NAME ": XF86Config Device sections \"%s\" and"
+ " \"%s\" may not be assigned to the same adapter.\n",
+ pGDev->identifier, ATIGDevs[k].pGDev->identifier);
+ pATIGDev->iATIPtr = ATIGDevs[k].iATIPtr = -1;
+ }
+ }
+
+ j = ATIGDevs[i].iATIPtr;
+ if (j <= 0)
+ continue;
+
+ pATI = ATIPtrs[j - 1];
+
+ xf86MsgVerb(X_INFO, 3,
+ ATI_NAME ": %s assigned to %sactive \"Device\" section"
+ " \"%s\".\n",
+ Identifier, pGDev->active ? "" : "in", pGDev->identifier);
+
+ /*
+ * Attach adapter to XF86Config Device section and register its
+ * resources.
+ */
+ if (ATIClaimBusSlot(pDriver, pATIGDev->Chipset,
+ pGDev, pGDev->active, pATI) < 0)
+ {
+ xf86Msg(X_ERROR,
+ ATI_NAME ": Could not claim bus slot for %s.\n",
+ Identifier);
+ continue;
+ }
+
+ if (!pGDev->active)
+ continue;
+
+ /* Allocate screen */
+ pScreenInfo = xf86AllocateScreen(pDriver, 0);
+
+#ifdef XFree86LOADER
+
+ if (!xf86LoadSubModule(pScreenInfo, "atimisc"))
+ {
+ xf86Msg(X_ERROR,
+ ATI_NAME ": Failed to load \"atimisc\" module.\n");
+ xf86DeleteScreen(pScreenInfo->scrnIndex, 0);
+ continue;
+ }
+
+ xf86LoaderReqSymLists(ATISymbols, NULL);
+
+#endif
+
+ /* Attach device to screen */
+ xf86AddEntityToScreen(pScreenInfo, pATI->iEntity);
+
+ ATIPtrs[j - 1] = NULL;
+
+ /* Fill in probe data */
+ pScreenInfo->driverVersion = ATI_VERSION_CURRENT;
+ pScreenInfo->driverName = ATI_DRIVER_NAME;
+ pScreenInfo->name = ATI_NAME;
+ pScreenInfo->Probe = ATIProbe;
+ pScreenInfo->PreInit = ATIPreInit;
+ pScreenInfo->ScreenInit = ATIScreenInit;
+ pScreenInfo->SwitchMode = ATISwitchMode;
+ pScreenInfo->AdjustFrame = ATIAdjustFrame;
+ pScreenInfo->EnterVT = ATIEnterVT;
+ pScreenInfo->LeaveVT = ATILeaveVT;
+ pScreenInfo->FreeScreen = ATIFreeScreen;
+ pScreenInfo->ValidMode = ATIValidMode;
+
+ pScreenInfo->driverPrivate = pATI;
+
+ pATI->Chipset = pATIGDev->Chipset;
+
+ ProbeSuccess = TRUE;
+ }
+
+ /* Deal with unassigned adapters */
+ for (i = 0; i < nATIPtr; i++)
+ {
+ if (!(pATI = ATIPtrs[i]))
+ continue;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->Adapter > ATI_ADAPTER_VGA)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (pATI->iEntity < 0)
+ (void)ATIClaimBusSlot(pDriver, 0, NULL, FALSE, pATI);
+ }
+
+ xfree(pATI);
+ }
+
+ xfree(ATIGDevs);
+ }
+
+ xfree(ATIPtrs);
+
+ /* Call Rage 128 driver probe */
+ if (DoRage128 && R128Probe(pDriver, flags))
+ ProbeSuccess = TRUE;
+
+ /* Call Radeon driver probe */
+ if (DoRadeon && RADEONProbe(pDriver, flags))
+ ProbeSuccess = TRUE;
+
+ return ProbeSuccess;
+}
diff --git a/src/atiprobe.h b/src/atiprobe.h
new file mode 100644
index 0000000..6f3d855
--- /dev/null
+++ b/src/atiprobe.h
@@ -0,0 +1,33 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.h,v 1.8 2003/01/01 19:16:33 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIPROBE_H___
+#define ___ATIPROBE_H___ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIProbe FunctionPrototype((DriverPtr, int));
+
+#endif /* ___ATIPROBE_H___ */
diff --git a/src/atiregs.h b/src/atiregs.h
new file mode 100644
index 0000000..6ef7160
--- /dev/null
+++ b/src/atiregs.h
@@ -0,0 +1,2718 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiregs.h,v 1.23 2003/01/10 17:43:40 tsi Exp $ */
+/*
+ * Copyright 1994 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Acknowledgements:
+ * Jake Richter, Panacea Inc., Londonderry, New Hampshire, U.S.A.
+ * Kevin E. Martin, martin@cs.unc.edu
+ * Tiago Gons, tiago@comosjn.hobby.nl
+ * Rickard E. Faith, faith@cs.unc.edu
+ * Scott Laird, lair@kimbark.uchicago.edu
+ *
+ * The intent here is to list all I/O ports for VGA (and its predecessors),
+ * ATI VGA Wonder, 8514/A, ATI Mach8, ATI Mach32 and ATI Mach64 video adapters,
+ * not just the ones in use by the ATI driver.
+ */
+
+#ifndef ___ATIREGS_H___
+#define ___ATIREGS_H___ 1
+
+#include "atiutil.h"
+
+/* I/O decoding definitions */
+#define SPARSE_IO_BASE 0x03fcu
+#define SPARSE_IO_SELECT 0xfc00u
+
+#define BLOCK_IO_BASE 0xff00u
+#define BLOCK_IO_SELECT 0x00fcu
+
+#define MM_IO_SELECT 0x03fcu
+#define BLOCK_SELECT 0x0400u
+#define DWORD_SELECT (BLOCK_SELECT | MM_IO_SELECT)
+
+#define IO_BYTE_SELECT 0x0003u
+
+#define SPARSE_IO_PORT (SPARSE_IO_BASE | IO_BYTE_SELECT)
+#define BLOCK_IO_PORT (BLOCK_IO_BASE | IO_BYTE_SELECT)
+
+#define IOPortTag(_SparseIOSelect, _BlockIOSelect) \
+ (SetBits(_SparseIOSelect, SPARSE_IO_SELECT) | \
+ SetBits(_BlockIOSelect, DWORD_SELECT))
+#define SparseIOTag(_IOSelect) IOPortTag(_IOSelect, 0)
+#define BlockIOTag(_IOSelect) IOPortTag(0, _IOSelect)
+
+/* MDA/[M]CGA/EGA/VGA I/O ports */
+#define GENVS 0x0102u /* Write (and Read on uC only) */
+
+#define R_GENLPS 0x03b9u /* Read */
+
+#define GENHP 0x03bfu
+
+#define ATTRX 0x03c0u
+#define ATTRD 0x03c1u
+#define GENS0 0x03c2u /* Read */
+#define GENMO 0x03c2u /* Write */
+#define GENENB 0x03c3u /* Read */
+#define SEQX 0x03c4u
+#define SEQD 0x03c5u
+#define VGA_DAC_MASK 0x03c6u
+#define VGA_DAC_READ 0x03c7u
+#define VGA_DAC_WRITE 0x03c8u
+#define VGA_DAC_DATA 0x03c9u
+#define R_GENFC 0x03cau /* Read */
+/* ? 0x03cbu */
+#define R_GENMO 0x03ccu /* Read */
+/* ? 0x03cdu */
+#define GRAX 0x03ceu
+#define GRAD 0x03cfu
+
+#define GENB 0x03d9u
+
+#define GENLPS 0x03dcu /* Write */
+#define KCX 0x03ddu
+#define KCD 0x03deu
+
+#define GENENA 0x46e8u /* Write */
+
+/* I/O port base numbers */
+#define MonochromeIOBase 0x03b0u
+#define ColourIOBase 0x03d0u
+
+/* Other MDA/[M]CGA/EGA/VGA I/O ports */
+/* ?(_IOBase) ((_IOBase) + 0x00u) */ /* CRTX synonym */
+/* ?(_IOBase) ((_IOBase) + 0x01u) */ /* CRTD synonym */
+/* ?(_IOBase) ((_IOBase) + 0x02u) */ /* CRTX synonym */
+/* ?(_IOBase) ((_IOBase) + 0x03u) */ /* CRTD synonym */
+#define CRTX(_IOBase) ((_IOBase) + 0x04u)
+#define CRTD(_IOBase) ((_IOBase) + 0x05u)
+/* ?(_IOBase) ((_IOBase) + 0x06u) */
+/* ?(_IOBase) ((_IOBase) + 0x07u) */
+#define GENMC(_IOBase) ((_IOBase) + 0x08u)
+/* ?(_IOBase) ((_IOBase) + 0x09u) */ /* R_GENLPS/GENB */
+#define GENS1(_IOBase) ((_IOBase) + 0x0au) /* Read */
+#define GENFC(_IOBase) ((_IOBase) + 0x0au) /* Write */
+#define GENLPC(_IOBase) ((_IOBase) + 0x0bu)
+/* ?(_IOBase) ((_IOBase) + 0x0cu) */ /* /GENLPS */
+/* ?(_IOBase) ((_IOBase) + 0x0du) */ /* /KCX */
+/* ?(_IOBase) ((_IOBase) + 0x0eu) */ /* /KCD */
+/* ?(_IOBase) ((_IOBase) + 0x0fu) */ /* GENHP/ */
+
+/* 8514/A VESA approved register definitions */
+#define DISP_STAT 0x02e8u /* Read */
+#define SENSE 0x0001u /* Presumably belong here */
+#define VBLANK 0x0002u
+#define HORTOG 0x0004u
+#define H_TOTAL 0x02e8u /* Write */
+#define IBM_DAC_MASK 0x02eau
+#define IBM_DAC_READ 0x02ebu
+#define IBM_DAC_WRITE 0x02ecu
+#define IBM_DAC_DATA 0x02edu
+#define H_DISP 0x06e8u /* Write */
+#define H_SYNC_STRT 0x0ae8u /* Write */
+#define H_SYNC_WID 0x0ee8u /* Write */
+#define HSYNCPOL_POS 0x0000u
+#define HSYNCPOL_NEG 0x0020u
+#define H_POLARITY_POS HSYNCPOL_POS /* Sigh */
+#define H_POLARITY_NEG HSYNCPOL_NEG /* Sigh */
+#define V_TOTAL 0x12e8u /* Write */
+#define V_DISP 0x16e8u /* Write */
+#define V_SYNC_STRT 0x1ae8u /* Write */
+#define V_SYNC_WID 0x1ee8u /* Write */
+#define VSYNCPOL_POS 0x0000u
+#define VSYNCPOL_NEG 0x0020u
+#define V_POLARITY_POS VSYNCPOL_POS /* Sigh */
+#define V_POLARITY_NEG VSYNCPOL_NEG /* Sigh */
+#define DISP_CNTL 0x22e8u /* Write */
+#define ODDBNKENAB 0x0001u
+#define MEMCFG_2 0x0000u
+#define MEMCFG_4 0x0002u
+#define MEMCFG_6 0x0004u
+#define MEMCFG_8 0x0006u
+#define DBLSCAN 0x0008u
+#define INTERLACE 0x0010u
+#define DISPEN_NC 0x0000u
+#define DISPEN_ENAB 0x0020u
+#define DISPEN_DISAB 0x0040u
+#define R_H_TOTAL 0x26e8u /* Read */
+/* ? 0x2ae8u */
+/* ? 0x2ee8u */
+/* ? 0x32e8u */
+/* ? 0x36e8u */
+/* ? 0x3ae8u */
+/* ? 0x3ee8u */
+#define SUBSYS_STAT 0x42e8u /* Read */
+#define VBLNKFLG 0x0001u
+#define PICKFLAG 0x0002u
+#define INVALIDIO 0x0004u
+#define GPIDLE 0x0008u
+#define MONITORID_MASK 0x0070u
+/* MONITORID_? 0x0000u */
+#define MONITORID_8507 0x0010u
+#define MONITORID_8514 0x0020u
+/* MONITORID_? 0x0030u */
+/* MONITORID_? 0x0040u */
+#define MONITORID_8503 0x0050u
+#define MONITORID_8512 0x0060u
+#define MONITORID_8513 0x0060u
+#define MONITORID_NONE 0x0070u
+#define _8PLANE 0x0080u
+#define SUBSYS_CNTL 0x42e8u /* Write */
+#define RVBLNKFLG 0x0001u
+#define RPICKFLAG 0x0002u
+#define RINVALIDIO 0x0004u
+#define RGPIDLE 0x0008u
+#define IVBLNKFLG 0x0100u
+#define IPICKFLAG 0x0200u
+#define IINVALIDIO 0x0400u
+#define IGPIDLE 0x0800u
+#define CHPTEST_NC 0x0000u
+#define CHPTEST_NORMAL 0x1000u
+#define CHPTEST_ENAB 0x2000u
+#define GPCTRL_NC 0x0000u
+#define GPCTRL_ENAB 0x4000u
+#define GPCTRL_RESET 0x8000u
+#define ROM_PAGE_SEL 0x46e8u /* Write */
+#define ADVFUNC_CNTL 0x4ae8u /* Write */
+#define DISABPASSTHRU 0x0001u
+#define CLOKSEL 0x0004u
+/* ? 0x4ee8u */
+#define EXT_CONFIG_0 0x52e8u /* C & T 82C480 */
+#define EXT_CONFIG_1 0x56e8u /* C & T 82C480 */
+#define EXT_CONFIG_2 0x5ae8u /* C & T 82C480 */
+#define EXT_CONFIG_3 0x5ee8u /* C & T 82C480 */
+/* ? 0x62e8u */
+/* ? 0x66e8u */
+/* ? 0x6ae8u */
+/* ? 0x6ee8u */
+/* ? 0x72e8u */
+/* ? 0x76e8u */
+/* ? 0x7ae8u */
+/* ? 0x7ee8u */
+#define CUR_Y 0x82e8u
+#define CUR_X 0x86e8u
+#define DESTY_AXSTP 0x8ae8u /* Write */
+#define DESTX_DIASTP 0x8ee8u /* Write */
+#define ERR_TERM 0x92e8u
+#define MAJ_AXIS_PCNT 0x96e8u /* Write */
+#define GP_STAT 0x9ae8u /* Read */
+#define GE_STAT 0x9ae8u /* Alias */
+#define DATARDY 0x0100u
+#define DATA_READY DATARDY /* Alias */
+#define GPBUSY 0x0200u
+#define CMD 0x9ae8u /* Write */
+#define WRTDATA 0x0001u
+#define PLANAR 0x0002u
+#define LASTPIX 0x0004u
+#define LINETYPE 0x0008u
+#define DRAW 0x0010u
+#define INC_X 0x0020u
+#define YMAJAXIS 0x0040u
+#define INC_Y 0x0080u
+#define PCDATA 0x0100u
+#define _16BIT 0x0200u
+#define CMD_NOP 0x0000u
+#define CMD_OP_MSK 0xf000u
+#define BYTSEQ 0x1000u
+#define CMD_LINE 0x2000u
+#define CMD_RECT 0x4000u
+#define CMD_RECTV1 0x6000u
+#define CMD_RECTV2 0x8000u
+#define CMD_LINEAF 0xa000u
+#define CMD_BITBLT 0xc000u
+#define SHORT_STROKE 0x9ee8u /* Write */
+#define SSVDRAW 0x0010u
+#define VECDIR_000 0x0000u
+#define VECDIR_045 0x0020u
+#define VECDIR_090 0x0040u
+#define VECDIR_135 0x0060u
+#define VECDIR_180 0x0080u
+#define VECDIR_225 0x00a0u
+#define VECDIR_270 0x00c0u
+#define VECDIR_315 0x00e0u
+#define BKGD_COLOR 0xa2e8u /* Write */
+#define FRGD_COLOR 0xa6e8u /* Write */
+#define WRT_MASK 0xaae8u /* Write */
+#define RD_MASK 0xaee8u /* Write */
+#define COLOR_CMP 0xb2e8u /* Write */
+#define BKGD_MIX 0xb6e8u /* Write */
+/* 0x001fu See MIX_* definitions below */
+#define BSS_BKGDCOL 0x0000u
+#define BSS_FRGDCOL 0x0020u
+#define BSS_PCDATA 0x0040u
+#define BSS_BITBLT 0x0060u
+#define FRGD_MIX 0xbae8u /* Write */
+/* 0x001fu See MIX_* definitions below */
+#define FSS_BKGDCOL 0x0000u
+#define FSS_FRGDCOL 0x0020u
+#define FSS_PCDATA 0x0040u
+#define FSS_BITBLT 0x0060u
+#define MULTIFUNC_CNTL 0xbee8u /* Write */
+#define MIN_AXIS_PCNT 0x0000u
+#define SCISSORS_T 0x1000u
+#define SCISSORS_L 0x2000u
+#define SCISSORS_B 0x3000u
+#define SCISSORS_R 0x4000u
+#define M32_MEM_CNTL 0x5000u
+#define HORCFG_4 0x0000u
+#define HORCFG_5 0x0001u
+#define HORCFG_8 0x0002u
+#define HORCFG_10 0x0003u
+#define VRTCFG_2 0x0000u
+#define VRTCFG_4 0x0004u
+#define VRTCFG_6 0x0008u
+#define VRTCFG_8 0x000cu
+#define BUFSWP 0x0010u
+#define PATTERN_L 0x8000u
+#define PATTERN_H 0x9000u
+#define PIX_CNTL 0xa000u
+#define PLANEMODE 0x0004u
+#define COLCMPOP_F 0x0000u
+#define COLCMPOP_T 0x0008u
+#define COLCMPOP_GE 0x0010u
+#define COLCMPOP_LT 0x0018u
+#define COLCMPOP_NE 0x0020u
+#define COLCMPOP_EQ 0x0028u
+#define COLCMPOP_LE 0x0030u
+#define COLCMPOP_GT 0x0038u
+#define MIXSEL_FRGDMIX 0x0000u
+#define MIXSEL_PATT 0x0040u
+#define MIXSEL_EXPPC 0x0080u
+#define MIXSEL_EXPBLT 0x00c0u
+/* ? 0xc2e8u */
+/* ? 0xc6e8u */
+/* ? 0xcae8u */
+/* ? 0xcee8u */
+/* ? 0xd2e8u */
+/* ? 0xd6e8u */
+/* ? 0xdae8u */
+/* ? 0xdee8u */
+#define PIX_TRANS 0xe2e8u
+/* ? 0xe6e8u */
+/* ? 0xeae8u */
+/* ? 0xeee8u */
+/* ? 0xf2e8u */
+/* ? 0xf6e8u */
+/* ? 0xfae8u */
+/* ? 0xfee8u */
+
+/* ATI Mach8 & Mach32 register definitions */
+#define OVERSCAN_COLOR_8 0x02eeu /* Write */ /* Mach32 */
+#define OVERSCAN_BLUE_24 0x02efu /* Write */ /* Mach32 */
+#define OVERSCAN_GREEN_24 0x06eeu /* Write */ /* Mach32 */
+#define OVERSCAN_RED_24 0x06efu /* Write */ /* Mach32 */
+#define CURSOR_OFFSET_LO 0x0aeeu /* Write */ /* Mach32 */
+#define CURSOR_OFFSET_HI 0x0eeeu /* Write */ /* Mach32 */
+#define CONFIG_STATUS_1 0x12eeu /* Read */
+#define CLK_MODE 0x0001u /* Mach8 */
+#define BUS_16 0x0002u /* Mach8 */
+#define MC_BUS 0x0004u /* Mach8 */
+#define EEPROM_ENA 0x0008u /* Mach8 */
+#define DRAM_ENA 0x0010u /* Mach8 */
+#define MEM_INSTALLED 0x0060u /* Mach8 */
+#define ROM_ENA 0x0080u /* Mach8 */
+#define ROM_PAGE_ENA 0x0100u /* Mach8 */
+#define ROM_LOCATION 0xfe00u /* Mach8 */
+#define _8514_ONLY 0x0001u /* Mach32 */
+#define BUS_TYPE 0x000eu /* Mach32 */
+#define ISA_16_BIT 0x0000u /* Mach32 */
+#define EISA 0x0002u /* Mach32 */
+#define MICRO_C_16_BIT 0x0004u /* Mach32 */
+#define MICRO_C_8_BIT 0x0006u /* Mach32 */
+#define LOCAL_386SX 0x0008u /* Mach32 */
+#define LOCAL_386DX 0x000au /* Mach32 */
+#define LOCAL_486 0x000cu /* Mach32 */
+#define PCI 0x000eu /* Mach32 */
+#define MEM_TYPE 0x0070u /* Mach32 */
+#define CHIP_DIS 0x0080u /* Mach32 */
+#define TST_VCTR_ENA 0x0100u /* Mach32 */
+#define DACTYPE 0x0e00u /* Mach32 */
+#define MC_ADR_DECODE 0x1000u /* Mach32 */
+#define CARD_ID 0xe000u /* Mach32 */
+#define HORZ_CURSOR_POSN 0x12eeu /* Write */ /* Mach32 */
+#define CONFIG_STATUS_2 0x16eeu /* Read */
+#define SHARE_CLOCK 0x0001u /* Mach8 */
+#define HIRES_BOOT 0x0002u /* Mach8 */
+#define EPROM_16_ENA 0x0004u /* Mach8 */
+#define WRITE_PER_BIT 0x0008u /* Mach8 */
+#define FLASH_ENA 0x0010u /* Mach8 */
+#define SLOW_SEQ_EN 0x0001u /* Mach32 */
+#define MEM_ADDR_DIS 0x0002u /* Mach32 */
+#define ISA_16_ENA 0x0004u /* Mach32 */
+#define KOR_TXT_MODE_ENA 0x0008u /* Mach32 */
+#define LOCAL_BUS_SUPPORT 0x0030u /* Mach32 */
+#define LOCAL_BUS_CONFIG_2 0x0040u /* Mach32 */
+#define LOCAL_BUS_RD_DLY_ENA 0x0080u /* Mach32 */
+#define LOCAL_DAC_EN 0x0100u /* Mach32 */
+#define LOCAL_RDY_EN 0x0200u /* Mach32 */
+#define EEPROM_ADR_SEL 0x0400u /* Mach32 */
+#define GE_STRAP_SEL 0x0800u /* Mach32 */
+#define VESA_RDY 0x1000u /* Mach32 */
+#define Z4GB 0x2000u /* Mach32 */
+#define LOC2_MDRAM 0x4000u /* Mach32 */
+#define VERT_CURSOR_POSN 0x16eeu /* Write */ /* Mach32 */
+#define FIFO_TEST_DATA 0x1aeeu /* Read */ /* Mach32 */
+#define CURSOR_COLOR_0 0x1aeeu /* Write */ /* Mach32 */
+#define CURSOR_COLOR_1 0x1aefu /* Write */ /* Mach32 */
+#define HORZ_CURSOR_OFFSET 0x1eeeu /* Write */ /* Mach32 */
+#define VERT_CURSOR_OFFSET 0x1eefu /* Write */ /* Mach32 */
+#define PCI_CNTL 0x22eeu /* Mach32-PCI */
+#define CRT_PITCH 0x26eeu /* Write */
+#define CRT_OFFSET_LO 0x2aeeu /* Write */
+#define CRT_OFFSET_HI 0x2eeeu /* Write */
+#define LOCAL_CNTL 0x32eeu /* Mach32 */
+#define FIFO_OPT 0x36eeu /* Write */ /* Mach8 */
+#define MISC_OPTIONS 0x36eeu /* Mach32 */
+#define W_STATE_ENA 0x0000u /* Mach32 */
+#define HOST_8_ENA 0x0001u /* Mach32 */
+#define MEM_SIZE_ALIAS 0x000cu /* Mach32 */
+#define MEM_SIZE_512K 0x0000u /* Mach32 */
+#define MEM_SIZE_1M 0x0004u /* Mach32 */
+#define MEM_SIZE_2M 0x0008u /* Mach32 */
+#define MEM_SIZE_4M 0x000cu /* Mach32 */
+#define DISABLE_VGA 0x0010u /* Mach32 */
+#define _16_BIT_IO 0x0020u /* Mach32 */
+#define DISABLE_DAC 0x0040u /* Mach32 */
+#define DLY_LATCH_ENA 0x0080u /* Mach32 */
+#define TEST_MODE 0x0100u /* Mach32 */
+#define BLK_WR_ENA 0x0400u /* Mach32 */
+#define _64_DRAW_ENA 0x0800u /* Mach32 */
+#define FIFO_TEST_TAG 0x3aeeu /* Read */ /* Mach32 */
+#define EXT_CURSOR_COLOR_0 0x3aeeu /* Write */ /* Mach32 */
+#define EXT_CURSOR_COLOR_1 0x3eeeu /* Write */ /* Mach32 */
+#define MEM_BNDRY 0x42eeu /* Mach32 */
+#define MEM_PAGE_BNDRY 0x000fu /* Mach32 */
+#define MEM_BNDRY_ENA 0x0010u /* Mach32 */
+#define SHADOW_CTL 0x46eeu /* Write */
+#define CLOCK_SEL 0x4aeeu
+/* DISABPASSTHRU 0x0001u See ADVFUNC_CNTL */
+#define VFIFO_DEPTH_1 0x0100u /* Mach32 */
+#define VFIFO_DEPTH_2 0x0200u /* Mach32 */
+#define VFIFO_DEPTH_3 0x0300u /* Mach32 */
+#define VFIFO_DEPTH_4 0x0400u /* Mach32 */
+#define VFIFO_DEPTH_5 0x0500u /* Mach32 */
+#define VFIFO_DEPTH_6 0x0600u /* Mach32 */
+#define VFIFO_DEPTH_7 0x0700u /* Mach32 */
+#define VFIFO_DEPTH_8 0x0800u /* Mach32 */
+#define VFIFO_DEPTH_9 0x0900u /* Mach32 */
+#define VFIFO_DEPTH_A 0x0a00u /* Mach32 */
+#define VFIFO_DEPTH_B 0x0b00u /* Mach32 */
+#define VFIFO_DEPTH_C 0x0c00u /* Mach32 */
+#define VFIFO_DEPTH_D 0x0d00u /* Mach32 */
+#define VFIFO_DEPTH_E 0x0e00u /* Mach32 */
+#define VFIFO_DEPTH_F 0x0f00u /* Mach32 */
+#define COMPOSITE_SYNC 0x1000u
+/* ? 0x4eeeu */
+#define ROM_ADDR_1 0x52eeu
+#define BIOS_BASE_SEGMENT 0x007fu /* Mach32 */
+/* ? 0xff80u */ /* Mach32 */
+#define ROM_ADDR_2 0x56eeu /* Sick ... */
+#define SHADOW_SET 0x5aeeu /* Write */
+#define MEM_CFG 0x5eeeu /* Mach32 */
+#define MEM_APERT_SEL 0x0003u /* Mach32 */
+#define MEM_APERT_PAGE 0x000cu /* Mach32 */
+#define MEM_APERT_LOC 0xfff0u /* Mach32 */
+#define EXT_GE_STATUS 0x62eeu /* Read */ /* Mach32 */
+#define HORZ_OVERSCAN 0x62eeu /* Write */ /* Mach32 */
+#define VERT_OVERSCAN 0x66eeu /* Write */ /* Mach32 */
+#define MAX_WAITSTATES 0x6aeeu
+#define GE_OFFSET_LO 0x6eeeu /* Write */
+#define BOUNDS_LEFT 0x72eeu /* Read */
+#define GE_OFFSET_HI 0x72eeu /* Write */
+#define BOUNDS_TOP 0x76eeu /* Read */
+#define GE_PITCH 0x76eeu /* Write */
+#define BOUNDS_RIGHT 0x7aeeu /* Read */
+#define EXT_GE_CONFIG 0x7aeeu /* Write */ /* Mach32 */
+#define MONITOR_ALIAS 0x0007u /* Mach32 */
+/* MONITOR_? 0x0000u */ /* Mach32 */
+#define MONITOR_8507 0x0001u /* Mach32 */
+#define MONITOR_8514 0x0002u /* Mach32 */
+/* MONITOR_? 0x0003u */ /* Mach32 */
+/* MONITOR_? 0x0004u */ /* Mach32 */
+#define MONITOR_8503 0x0005u /* Mach32 */
+#define MONITOR_8512 0x0006u /* Mach32 */
+#define MONITOR_8513 0x0006u /* Mach32 */
+#define MONITOR_NONE 0x0007u /* Mach32 */
+#define ALIAS_ENA 0x0008u /* Mach32 */
+#define PIXEL_WIDTH_4 0x0000u /* Mach32 */
+#define PIXEL_WIDTH_8 0x0010u /* Mach32 */
+#define PIXEL_WIDTH_16 0x0020u /* Mach32 */
+#define PIXEL_WIDTH_24 0x0030u /* Mach32 */
+#define RGB16_555 0x0000u /* Mach32 */
+#define RGB16_565 0x0040u /* Mach32 */
+#define RGB16_655 0x0080u /* Mach32 */
+#define RGB16_664 0x00c0u /* Mach32 */
+#define MULTIPLEX_PIXELS 0x0100u /* Mach32 */
+#define RGB24 0x0000u /* Mach32 */
+#define RGBx24 0x0200u /* Mach32 */
+#define BGR24 0x0400u /* Mach32 */
+#define xBGR24 0x0600u /* Mach32 */
+#define DAC_8_BIT_EN 0x4000u /* Mach32 */
+#define ORDER_16BPP_565 RGB16_565 /* Mach32 */
+#define BOUNDS_BOTTOM 0x7eeeu /* Read */
+#define MISC_CNTL 0x7eeeu /* Write */ /* Mach32 */
+#define PATT_DATA_INDEX 0x82eeu
+/* ? 0x86eeu */
+/* ? 0x8aeeu */
+#define R_EXT_GE_CONFIG 0x8eeeu /* Read */ /* Mach32 */
+#define PATT_DATA 0x8eeeu /* Write */
+#define R_MISC_CNTL 0x92eeu /* Read */ /* Mach32 */
+#define BRES_COUNT 0x96eeu
+#define EXT_FIFO_STATUS 0x9aeeu /* Read */
+#define LINEDRAW_INDEX 0x9aeeu /* Write */
+/* ? 0x9eeeu */
+#define LINEDRAW_OPT 0xa2eeu
+#define BOUNDS_RESET 0x0100u
+#define CLIP_MODE_0 0x0000u /* Clip exception disabled */
+#define CLIP_MODE_1 0x0200u /* Line segments */
+#define CLIP_MODE_2 0x0400u /* Polygon boundary lines */
+#define CLIP_MODE_3 0x0600u /* Patterned lines */
+#define DEST_X_START 0xa6eeu /* Write */
+#define DEST_X_END 0xaaeeu /* Write */
+#define DEST_Y_END 0xaeeeu /* Write */
+#define R_H_TOTAL_DISP 0xb2eeu /* Read */ /* Mach32 */
+#define SRC_X_STRT 0xb2eeu /* Write */
+#define R_H_SYNC_STRT 0xb6eeu /* Read */ /* Mach32 */
+#define ALU_BG_FN 0xb6eeu /* Write */
+#define R_H_SYNC_WID 0xbaeeu /* Read */ /* Mach32 */
+#define ALU_FG_FN 0xbaeeu /* Write */
+#define SRC_X_END 0xbeeeu /* Write */
+#define R_V_TOTAL 0xc2eeu /* Read */
+#define SRC_Y_DIR 0xc2eeu /* Write */
+#define R_V_DISP 0xc6eeu /* Read */ /* Mach32 */
+#define EXT_SHORT_STROKE 0xc6eeu /* Write */
+#define R_V_SYNC_STRT 0xcaeeu /* Read */ /* Mach32 */
+#define SCAN_X 0xcaeeu /* Write */
+#define VERT_LINE_CNTR 0xceeeu /* Read */ /* Mach32 */
+#define DP_CONFIG 0xceeeu /* Write */
+#define READ_WRITE 0x0001u
+#define DATA_WIDTH 0x0200u
+#define DATA_ORDER 0x1000u
+#define FG_COLOR_SRC_FG 0x2000u
+#define FG_COLOR_SRC_BLIT 0x6000u
+#define R_V_SYNC_WID 0xd2eeu /* Read */
+#define PATT_LENGTH 0xd2eeu /* Write */
+#define PATT_INDEX 0xd6eeu /* Write */
+#define READ_SRC_X 0xdaeeu /* Read */ /* Mach32 */
+#define EXT_SCISSOR_L 0xdaeeu /* Write */
+#define READ_SRC_Y 0xdeeeu /* Read */ /* Mach32 */
+#define EXT_SCISSOR_T 0xdeeeu /* Write */
+#define EXT_SCISSOR_R 0xe2eeu /* Write */
+#define EXT_SCISSOR_B 0xe6eeu /* Write */
+/* ? 0xeaeeu */
+#define DEST_COMP_FN 0xeeeeu /* Write */
+#define DEST_COLOR_CMP_MASK 0xf2eeu /* Write */ /* Mach32 */
+/* ? 0xf6eeu */
+#define CHIP_ID 0xfaeeu /* Read */ /* Mach32 */
+#define CHIP_CODE_0 0x001fu /* Mach32 */
+#define CHIP_CODE_1 0x03e0u /* Mach32 */
+#define CHIP_CLASS 0x0c00u /* Mach32 */
+#define CHIP_REV 0xf000u /* Mach32 */
+#define LINEDRAW 0xfeeeu /* Write */
+
+/* ATI Mach64 register definitions */
+#define CRTC_H_TOTAL_DISP IOPortTag(0x00u, 0x00u)
+#define CRTC_H_TOTAL 0x000001fful
+/* ? 0x0000fe00ul */
+#define CRTC_H_DISP 0x01ff0000ul
+/* ? 0xfe000000ul */
+#define CRTC_H_SYNC_STRT_WID IOPortTag(0x01u, 0x01u)
+#define CRTC_H_SYNC_STRT 0x000000fful
+#define CRTC_H_SYNC_DLY 0x00000700ul
+/* ? 0x00000800ul */
+#define CRTC_H_SYNC_STRT_HI 0x00001000ul
+/* ? 0x0000e000ul */
+#define CRTC_H_SYNC_WID 0x001f0000ul
+#define CRTC_H_SYNC_POL 0x00200000ul
+/* ? 0xffc00000ul */
+#define CRTC_V_TOTAL_DISP IOPortTag(0x02u, 0x02u)
+#define CRTC_V_TOTAL 0x000007fful
+/* ? 0x0000f800ul */
+#define CRTC_V_DISP 0x07ff0000ul
+/* ? 0xf8000000ul */
+#define CRTC_V_SYNC_STRT_WID IOPortTag(0x03u, 0x03u)
+#define CRTC_V_SYNC_STRT 0x000007fful
+/* ? 0x0000f800ul */
+#define CRTC_V_SYNC_WID 0x001f0000ul
+#define CRTC_V_SYNC_POL 0x00200000ul
+/* ? 0xffc00000ul */
+#define CRTC_VLINE_CRNT_VLINE IOPortTag(0x04u, 0x04u)
+#define CRTC_VLINE 0x000007fful
+/* ? 0x0000f800ul */
+#define CRTC_CRNT_VLINE 0x07ff0000ul
+/* ? 0xf8000000ul */
+#define CRTC_OFF_PITCH IOPortTag(0x05u, 0x05u)
+#define CRTC_OFFSET 0x000ffffful
+#define CRTC_OFFSET_VGA 0x0003fffful
+#define CRTC_OFFSET_LOCK 0x00100000ul /* XC/XL */
+/* ? 0x00200000ul */
+#define CRTC_PITCH 0xffc00000ul
+#define CRTC_INT_CNTL IOPortTag(0x06u, 0x06u)
+#define CRTC_VBLANK 0x00000001ul
+#define CRTC_VBLANK_INT_EN 0x00000002ul
+#define CRTC_VBLANK_INT 0x00000004ul
+#define CRTC_VLINE_INT_EN 0x00000008ul
+#define CRTC_VLINE_INT 0x00000010ul
+#define CRTC_VLINE_SYNC 0x00000020ul
+#define CRTC_FRAME 0x00000040ul
+#define CRTC_SNAPSHOT_INT_EN 0x00000080ul /* GTPro */
+#define CRTC_SNAPSHOT_INT 0x00000100ul /* GTPro */
+#define CRTC_I2C_INT_EN 0x00000200ul /* GTPro */
+#define CRTC_I2C_INT 0x00000400ul /* GTPro */
+#define CRTC2_VBLANK 0x00000800ul /* LTPro */
+#define CRTC2_VBLANK_INT_EN 0x00001000ul /* LTPro */
+#define CRTC2_VBLANK_INT 0x00002000ul /* LTPro */
+#define CRTC2_VLINE_INT_EN 0x00004000ul /* LTPro */
+#define CRTC2_VLINE_INT 0x00008000ul /* LTPro */
+#define CRTC_CAPBUF0_INT_EN 0x00010000ul /* VT/GT */
+#define CRTC_CAPBUF0_INT 0x00020000ul /* VT/GT */
+#define CRTC_CAPBUF1_INT_EN 0x00040000ul /* VT/GT */
+#define CRTC_CAPBUF1_INT 0x00080000ul /* VT/GT */
+#define CRTC_OVERLAY_EOF_INT_EN 0x00100000ul /* VT/GT */
+#define CRTC_OVERLAY_EOF_INT 0x00200000ul /* VT/GT */
+#define CRTC_ONESHOT_CAP_INT_EN 0x00400000ul /* VT/GT */
+#define CRTC_ONESHOT_CAP_INT 0x00800000ul /* VT/GT */
+#define CRTC_BUSMASTER_EOL_INT_EN 0x01000000ul /* VTB/GTB/LT */
+#define CRTC_BUSMASTER_EOL_INT 0x02000000ul /* VTB/GTB/LT */
+#define CRTC_GP_INT_EN 0x04000000ul /* VTB/GTB/LT */
+#define CRTC_GP_INT 0x08000000ul /* VTB/GTB/LT */
+#define CRTC2_VLINE_SYNC 0x10000000ul /* LTPro */
+#define CRTC_SNAPSHOT2_INT_EN 0x20000000ul /* LTPro */
+#define CRTC_SNAPSHOT2_INT 0x40000000ul /* LTPro */
+#define CRTC_VBLANK_BIT2_INT 0x80000000ul /* GTPro */
+#define CRTC_INT_ENS /* *** UPDATE ME *** */ \
+ ( \
+ CRTC_VBLANK_INT_EN | \
+ CRTC_VLINE_INT_EN | \
+ CRTC_SNAPSHOT_INT_EN | \
+ CRTC_I2C_INT_EN | \
+ CRTC2_VBLANK_INT_EN | \
+ CRTC2_VLINE_INT_EN | \
+ CRTC_CAPBUF0_INT_EN | \
+ CRTC_CAPBUF1_INT_EN | \
+ CRTC_OVERLAY_EOF_INT_EN | \
+ CRTC_ONESHOT_CAP_INT_EN | \
+ CRTC_BUSMASTER_EOL_INT_EN | \
+ CRTC_GP_INT_EN | \
+ CRTC_SNAPSHOT2_INT_EN | \
+ 0 \
+ )
+#define CRTC_INT_ACKS /* *** UPDATE ME *** */ \
+ ( \
+ CRTC_VBLANK_INT | \
+ CRTC_VLINE_INT | \
+ CRTC_SNAPSHOT_INT | \
+ CRTC_I2C_INT | \
+ CRTC2_VBLANK_INT | \
+ CRTC2_VLINE_INT | \
+ CRTC_CAPBUF0_INT | \
+ CRTC_CAPBUF1_INT | \
+ CRTC_OVERLAY_EOF_INT | \
+ CRTC_ONESHOT_CAP_INT | \
+ CRTC_BUSMASTER_EOL_INT | \
+ CRTC_GP_INT | \
+ CRTC_SNAPSHOT2_INT | \
+ CRTC_VBLANK_BIT2_INT | \
+ 0 \
+ )
+#define CRTC_GEN_CNTL IOPortTag(0x07u, 0x07u)
+#define CRTC_DBL_SCAN_EN 0x00000001ul
+#define CRTC_INTERLACE_EN 0x00000002ul
+#define CRTC_HSYNC_DIS 0x00000004ul
+#define CRTC_VSYNC_DIS 0x00000008ul
+#define CRTC_CSYNC_EN 0x00000010ul
+#define CRTC_PIX_BY_2_EN 0x00000020ul
+#define CRTC2_DBL_SCAN_EN 0x00000020ul /* LTPro */
+#define CRTC_DISPLAY_DIS 0x00000040ul
+#define CRTC_VGA_XOVERSCAN 0x00000080ul
+#define CRTC_PIX_WIDTH 0x00000700ul
+#define CRTC_BYTE_PIX_ORDER 0x00000800ul
+#define CRTC_VSYNC_INT_EN 0x00001000ul /* XC/XL */
+#define CRTC_VSYNC_INT 0x00002000ul /* XC/XL */
+#define CRTC_FIFO_OVERFILL 0x0000c000ul /* VT/GT */
+#define CRTC2_VSYNC_INT_EN 0x00004000ul /* XC/XL */
+#define CRTC2_VSYNC_INT 0x00008000ul /* XC/XL */
+#define CRTC_FIFO_LWM 0x000f0000ul
+#define CRTC_HVSYNC_IO_DRIVE 0x00010000ul /* XC/XL */
+#define CRTC2_PIX_WIDTH 0x000e0000ul /* LTPro */
+#define CRTC_VGA_128KAP_PAGING 0x00100000ul /* VT/GT */
+#define CRTC_DISPREQ_ONLY 0x00200000ul /* VT/GT */
+#define CRTC_VFC_SYNC_TRISTATE 0x00200000ul /* VTB/GTB/LT */
+#define CRTC2_EN 0x00200000ul /* LTPro */
+#define CRTC_LOCK_REGS 0x00400000ul /* VT/GT */
+#define CRTC_SYNC_TRISTATE 0x00800000ul /* VT/GT */
+#define CRTC_EXT_DISP_EN 0x01000000ul
+#define CRTC_EN 0x02000000ul
+#define CRTC_DISP_REQ_EN 0x04000000ul
+#define CRTC_VGA_LINEAR 0x08000000ul
+#define CRTC_VSYNC_FALL_EDGE 0x10000000ul
+#define CRTC_VGA_TEXT_132 0x20000000ul
+#define CRTC_CNT_EN 0x40000000ul
+#define CRTC_CUR_B_TEST 0x80000000ul
+#define CRTC_INT_ENS_X /* *** UPDATE ME *** */ \
+ ( \
+ CRTC_VSYNC_INT_EN | \
+ CRTC2_VSYNC_INT_EN | \
+ 0 \
+ )
+#define CRTC_INT_ACKS_X /* *** UPDATE ME *** */ \
+ ( \
+ CRTC_VSYNC_INT | \
+ CRTC2_VSYNC_INT | \
+ 0 \
+ )
+#define DSP_CONFIG BlockIOTag(0x08u) /* VTB/GTB/LT */
+#define DSP_XCLKS_PER_QW 0x00003ffful
+/* ? 0x00004000ul */
+#define DSP_FLUSH_WB 0x00008000ul
+#define DSP_LOOP_LATENCY 0x000f0000ul
+#define DSP_PRECISION 0x00700000ul
+/* ? 0xff800000ul */
+#define DSP_ON_OFF BlockIOTag(0x09u) /* VTB/GTB/LT */
+#define DSP_OFF 0x000007fful
+/* ? 0x0000f800ul */
+#define DSP_ON 0x07ff0000ul
+/* ? 0xf8000000ul */
+#define TIMER_CONFIG BlockIOTag(0x0au) /* VTB/GTB/LT */
+#define MEM_BUF_CNTL BlockIOTag(0x0bu) /* VTB/GTB/LT */
+#define SHARED_CNTL BlockIOTag(0x0cu) /* VTB/GTB/LT */
+#define SHARED_MEM_CONFIG BlockIOTag(0x0du) /* VTB/GTB/LT */
+#define MEM_ADDR_CONFIG BlockIOTag(0x0du) /* GTPro */
+#define SHARED_CNTL_CTD BlockIOTag(0x0eu) /* CTD */
+/* ? 0x00fffffful */
+#define CTD_FIFO5 0x01000000ul
+/* ? 0xfe000000ul */
+#define CRT_TRAP BlockIOTag(0x0eu) /* VTB/GTB/LT */
+#define DSTN_CONTROL BlockIOTag(0x0fu) /* LT */
+#define I2C_CNTL_0 BlockIOTag(0x0fu) /* GTPro */
+#define I2C_CNTL_STAT 0x0000000ful
+#define I2C_CNTL_DONE 0x00000001ul
+#define I2C_CNTL_NACK 0x00000002ul
+#define I2C_CNTL_HALT 0x00000004ul
+#define I2C_CNTL_FULL 0x00000008ul
+/* ? 0x00000010ul */
+#define I2C_CNTL_HPTR_RST 0x00000020ul
+/* ? 0x000000c0ul */
+#define I2C_CNTL_START 0x00000100ul
+#define I2C_CNTL_STOP 0x00000200ul
+#define I2C_CNTL_GO 0x00000400ul
+#define I2C_CNTL_RECEIVE 0x00000800ul
+#define I2C_CNTL_ABORT 0x00001000ul
+#define I2C_CNTL_INT_EN 0x00002000ul
+#define I2C_CNTL_SCL 0x00004000ul
+#define I2C_CNTL_SDA 0x00008000ul
+#define I2C_CNTL_M_FACTOR 0x00ff0000ul
+#define I2C_CNTL_N_FACTOR 0xff000000ul
+#define OVR_CLR IOPortTag(0x08u, 0x10u)
+#define OVR_CLR_8 0x000000fful
+#define OVR_CLR_B 0x0000ff00ul
+#define OVR_CLR_G 0x00ff0000ul
+#define OVR_CLR_R 0xff000000ul
+#define OVR_WID_LEFT_RIGHT IOPortTag(0x09u, 0x11u)
+#define OVR_WID_LEFT 0x0000003ful /* 0x0f on <LT */
+/* ? 0x0000ffc0ul */
+#define OVR_WID_RIGHT 0x003f0000ul /* 0x0f0000 on <LT */
+/* ? 0xffc00000ul */
+#define OVR_WID_TOP_BOTTOM IOPortTag(0x0au, 0x12u)
+#define OVR_WID_TOP 0x000001fful /* 0x00ff on <LT */
+/* ? 0x0000fe00ul */
+#define OVR_WID_BOTTOM 0x01ff0000ul /* 0x00ff0000 on <LT */
+/* ? 0xfe000000ul */
+#define VGA_DSP_CONFIG BlockIOTag(0x13u) /* VTB/GTB/LT */
+#define VGA_DSP_XCLKS_PER_QW DSP_XCLKS_PER_QW
+/* ? 0x000fc000ul */
+#define VGA_DSP_PREC_PCLKBY2 0x00700000ul
+/* ? 0x00800000ul */
+#define VGA_DSP_PREC_PCLK 0x07000000ul
+/* ? 0xf8000000ul */
+#define VGA_DSP_ON_OFF BlockIOTag(0x14u) /* VTB/GTB/LT */
+#define VGA_DSP_OFF DSP_OFF
+/* ? 0x0000f800ul */
+#define VGA_DSP_ON DSP_ON
+/* ? 0xf8000000ul */
+#define DSP2_CONFIG BlockIOTag(0x15u) /* LTPro */
+#define DSP2_ON_OFF BlockIOTag(0x16u) /* LTPro */
+#define EXT_CRTC_GEN_CNTL BlockIOTag(0x17u) /* VT-A4 (W) */
+#define CRTC2_OFF_PITCH BlockIOTag(0x17u) /* LTPro */
+#define CUR_CLR0 IOPortTag(0x0bu, 0x18u)
+#define CUR_CLR1 IOPortTag(0x0cu, 0x19u)
+/* These are for both CUR_CLR0 and CUR_CLR1 */
+#define CUR_CLR_I 0x000000fful
+#define CUR_CLR_B 0x0000ff00ul
+#define CUR_CLR_G 0x00ff0000ul
+#define CUR_CLR_R 0xff000000ul
+#define CUR_CLR (CUR_CLR_R | CUR_CLR_G | CUR_CLR_B)
+#define CUR_OFFSET IOPortTag(0x0du, 0x1au)
+#define CUR_HORZ_VERT_POSN IOPortTag(0x0eu, 0x1bu)
+#define CUR_HORZ_POSN 0x000007fful
+/* ? 0x0000f800ul */
+#define CUR_VERT_POSN 0x07ff0000ul
+/* ? 0xf8000000ul */
+#define CUR_HORZ_VERT_OFF IOPortTag(0x0fu, 0x1cu)
+#define CUR_HORZ_OFF 0x0000007ful
+/* ? 0x0000ff80ul */
+#define CUR_VERT_OFF 0x007f0000ul
+/* ? 0xff800000ul */
+#define CONFIG_PANEL BlockIOTag(0x1du) /* LT */
+#define PANEL_FORMAT 0x00000007ul
+/* ? 0x00000008ul */
+#define PANEL_TYPE 0x000000f0ul
+#define NO_OF_GREY 0x00000700ul
+#define MOD_GEN 0x00001800ul
+#define EXT_LVDS_CLK 0x00001800ul /* LTPro */
+#define BLINK_RATE 0x00006000ul
+#define BLINK_RATE_PRO 0x00002000ul /* LTPro */
+#define DONT_SHADOW_HEND 0x00004000ul /* LTPro */
+#define DONT_USE_F32KHZ 0x00008000ul
+#define LCD_IO_DRIVE 0x00008000ul /* XC/XL */
+#define FP_POL 0x00010000ul
+#define LP_POL 0x00020000ul
+#define DTMG_POL 0x00040000ul
+#define SCK_POL 0x00080000ul
+#define DITHER_SEL 0x00300000ul
+#define INVERSE_VIDEO_EN 0x00400000ul
+#define BL_CLK_SEL 0x01800000ul
+#define BL_LEVEL 0x0e000000ul
+#define BL_CLK_SEL_PRO 0x00800000ul /* LTPro */
+#define BL_LEVEL_PRO 0x03000000ul /* LTPro */
+#define BIAS_LEVEL_PRO 0x0c000000ul /* LTPro */
+#define HSYNC_DELAY 0xf0000000ul
+#define TV_OUT_INDEX BlockIOTag(0x1du) /* LTPro */
+#define TV_REG_INDEX 0x000000fful
+#define TV_ON 0x00000100ul
+/* ? 0xfffffe00ul */
+#define GP_IO IOPortTag(0x1eu, 0x1eu) /* VT/GT */
+#define GP_IO_0 0x00000001ul
+#define GP_IO_1 0x00000002ul
+#define GP_IO_2 0x00000004ul
+#define GP_IO_3 0x00000008ul
+#define GP_IO_4 0x00000010ul
+#define GP_IO_5 0x00000020ul
+#define GP_IO_6 0x00000040ul
+#define GP_IO_7 0x00000080ul
+#define GP_IO_8 0x00000100ul
+#define GP_IO_9 0x00000200ul
+#define GP_IO_A 0x00000400ul
+#define GP_IO_B 0x00000800ul
+#define GP_IO_C 0x00001000ul
+#define GP_IO_D 0x00002000ul
+#define GP_IO_E 0x00004000ul
+#define GP_IO_F 0x00008000ul
+#define GP_IO_DIR_0 0x00010000ul
+#define GP_IO_DIR_1 0x00020000ul
+#define GP_IO_DIR_2 0x00040000ul
+#define GP_IO_DIR_3 0x00080000ul
+#define GP_IO_DIR_4 0x00100000ul
+#define GP_IO_DIR_5 0x00200000ul
+#define GP_IO_DIR_6 0x00400000ul
+#define GP_IO_DIR_7 0x00800000ul
+#define GP_IO_DIR_8 0x01000000ul
+#define GP_IO_DIR_9 0x02000000ul
+#define GP_IO_DIR_A 0x04000000ul
+#define GP_IO_DIR_B 0x08000000ul
+#define GP_IO_DIR_C 0x10000000ul
+#define GP_IO_DIR_D 0x20000000ul
+#define GP_IO_DIR_E 0x40000000ul
+#define GP_IO_DIR_F 0x80000000ul
+#define GP_IO_CNTL BlockIOTag(0x1fu) /* VT/GT */
+#define GP_IO_MODE 0x0000000ful
+/* ? 0x7ffffff0ul */
+#define GP_IO_EN 0x80000000ul
+#define HW_DEBUG BlockIOTag(0x1fu) /* VTB/GTB/LT */
+#define FAST_SRCCOPY_DIS 0x00000001ul
+#define BYPASS_SUBPIC_DBF 0x00000001ul /* XL/XC */
+#define SRC_AUTONA_FIX_DIS 0x00000002ul
+#define SYNC_PD_EN 0x00000002ul /* Mobility */
+#define DISP_QW_FIX_DIS 0x00000004ul
+#define GUIDST_WB_EXP_DIS 0x00000008ul
+#define CYC_ALL_FIX_DIS 0x00000008ul /* GTPro */
+#define AGPPLL_FIX_EN 0x00000008ul /* Mobility */
+#define SRC_AUTONA_ALWAYS_EN 0x00000010ul
+#define GUI_BEATS_HOST_P 0x00000010ul /* GTPro */
+#define DRV_CNTL_DQMB_WEB 0x00000020ul
+#define FAST_FILL_SCISSOR_DIS 0x00000020ul /* GT2c/VT4 */
+#define INTER_BLIT_FIX_DIS 0x00000020ul /* GTPro */
+#define DRV_CNTL_MA 0x00000040ul
+#define AUTO_BLKWRT_COLOR_DIS 0x00000040ul /* GT2c/VT4 */
+#define INTER_PRIM_DIS 0x00000040ul /* GTPro */
+#define DRV_CNTL_MD 0x00000080ul
+#define CHG_DEV_ID 0x00000100ul
+#define SRC_TRACK_DST_FIX_DIS 0x00000200ul
+#define HCLK_FB_SKEW 0x00000380ul /* GT2c/VT4 */
+#define SRC_TRACK_DST_FIX_DIS_P 0x00000080ul /* GTPro */
+#define AUTO_BLKWRT_COLOR_DIS_P 0x00000100ul /* GTPro */
+#define INTER_LINE_OVERLAP_DIS 0x00000200ul /* GTPro */
+#define MEM_OE_PULLBACK 0x00000400ul
+#define DBL_BUFFER_EN 0x00000400ul /* GTPro */
+#define MEM_WE_FIX_DIS 0x00000800ul
+#define MEM_OE_PULLBACK_B 0x00000800ul /* GT2c/VT4 */
+#define CMDFIFO_SIZE_EN 0x00000800ul /* GTPro */
+#define RD_EN_FIX_DIS 0x00001000ul
+#define MEM_WE_FIX_DIS_B 0x00001000ul
+#define AUTO_FF_DIS 0x00001000ul /* GTPro */
+#define CMDFIFO_SIZE_DIS 0x00002000ul /* GT2c/VT4 */
+#define AUTO_BLKWRT_DIS 0x00002000ul /* GTPro */
+#define GUI_BEATS_HOST 0x00004000ul /* GT2c/VT4 */
+#define ORED_INVLD_RB_CACHE 0x00004000ul /* GTPro */
+#define BLOCK_DBL_BUF 0x00008000ul /* GTPro */
+#define R2W_TURNAROUND_DELAY 0x00020000ul /* GT2c/VT4 */
+#define ENA_32BIT_DATA_BUS 0x00040000ul /* GT2c/VT4 */
+#define HCLK_FB_SKEW_P 0x00070000ul /* GTPro */
+#define ENA_FLASH_ROM 0x00080000ul /* GT2c/VT4 */
+#define DISABLE_SWITCH_FIX 0x00080000ul /* GTPro */
+#define MCLK_START_EN 0x00080000ul /* LTPro */
+#define SEL_VBLANK_BDL_BUF 0x00100000ul /* GTPro */
+#define CMDFIFO_64EN 0x00200000ul /* GTPro */
+#define BM_FIX_DIS 0x00400000ul /* GTPro */
+#define Z_SWITCH_EN 0x00800000ul /* LTPro */
+#define FLUSH_HOST_WB 0x01000000ul /* GTPro */
+#define HW_DEBUG_WRITE_MSK_FIX_DIS 0x02000000ul /* LTPro */
+#define Z_NO_WRITE_EN 0x04000000ul /* LTPro */
+#define DISABLE_PCLK_RESET_P 0x08000000ul /* LTPro */
+#define PM_D3_SUPPORT_ENABLE_P 0x10000000ul /* LTPro */
+#define STARTCYCLE_FIX_ENABLE 0x20000000ul /* LTPro */
+#define DONT_RST_CHAREN 0x20000000ul /* XL/XC */
+#define C3_FIX_ENABLE 0x40000000ul /* LTPro */
+#define BM_HOSTRA_EN 0x40000000ul /* XL/XC */
+#define PKGBGAb 0x80000000ul /* XL/XC */
+#define AUTOEXP_HORZ_FIX 0x80000000ul /* Mobility */
+#define SCRATCH_REG0 IOPortTag(0x10u, 0x20u)
+#define SCRATCH_REG1 IOPortTag(0x11u, 0x21u)
+/* BIOS_BASE_SEGMENT 0x0000007ful */ /* As above */
+/* ? 0x00000f80ul */
+#define BIOS_INIT_DAC_SUBTYPE 0x0000f000ul
+/* ? 0xffff0000ul */
+#define SCRATCH_REG2 BlockIOTag(0x22u) /* LT */
+#define SCRATCH_REG3 BlockIOTag(0x23u) /* GTPro */
+/* Not described here 0x07fffffful */
+#define DISPLAY_SWITCH_DISABLE 0x08000000ul
+/* Not described here 0xf0000000ul */
+#define CLOCK_CNTL IOPortTag(0x12u, 0x24u)
+#define CLOCK_BIT 0x00000004ul /* For ICS2595 */
+#define CLOCK_PULSE 0x00000008ul /* For ICS2595 */
+#define CLOCK_SELECT 0x0000000ful
+#define CLOCK_DIVIDER 0x00000030ul
+#define CLOCK_STROBE 0x00000040ul
+#define CLOCK_DATA 0x00000080ul
+/* ? 0x00000100ul */
+#define PLL_WR_EN 0x00000200ul /* For internal PLL */
+#define PLL_ADDR 0x0000fc00ul /* For internal PLL */
+#define PLL_DATA 0x00ff0000ul /* For internal PLL */
+/* ? 0xff000000ul */
+#define CONFIG_STAT64_1 BlockIOTag(0x25u) /* GTPro */
+#define CFG_SUBSYS_DEV_ID 0x000000fful
+#define CFG_SUBSYS_VEN_ID 0x00ffff00ul
+/* ? 0x1f000000ul */
+#define CFG_DIMM_TYPE 0xe0000000ul
+#define CFG_PCI_SUBSYS_DEV_ID 0x0000fffful /* XC/XL */
+#define CFG_PCI_SUBSYS_VEN_ID 0xffff0000ul /* XC/XL */
+#define CONFIG_STAT64_2 BlockIOTag(0x26u) /* GTPro */
+#define CFG_DIMM_TYPE_3 0x00000001ul
+/* ? 0x0000001eul */
+#define CFG_ROMWRTEN 0x00000020ul
+#define CFG_AGPVCOGAIN 0x000000c0ul
+#define CFG_PCI_TYPE 0x00000100ul
+#define CFG_AGPSKEW 0x00000e00ul
+#define CFG_X1CLKSKEW 0x00007000ul
+#define CFG_PANEL_ID_P 0x000f8000ul /* LTPro */
+/* ? 0x00100000ul */
+#define CFG_PREFETCH_EN 0x00200000ul
+#define CFG_ID_DISABLE 0x00400000ul
+#define CFG_PRE_TESTEN 0x00800000ul
+/* ? 0x01000000ul */
+#define CFG_PCI5VEN 0x02000000ul /* LTPro */
+#define CFG_VGA_DISABLE 0x04000000ul
+#define CFG_ENINTB 0x08000000ul
+/* ? 0x10000000ul */
+#define CFG_ROM_REMAP_2 0x20000000ul
+#define CFG_IDSEL 0x40000000ul
+/* ? 0x80000000ul */
+#define TV_OUT_DATA BlockIOTag(0x27u) /* LTPro */
+#define BUS_CNTL IOPortTag(0x13u, 0x28u)
+#define BUS_WS 0x0000000ful
+#define BUS_DBL_RESYNC 0x00000001ul /* VTB/GTB/LT */
+#define BUS_MSTR_RESET 0x00000002ul /* VTB/GTB/LT */
+#define BUS_FLUSH_BUF 0x00000004ul /* VTB/GTB/LT */
+#define BUS_STOP_REQ_DIS 0x00000008ul /* VTB/GTB/LT */
+#define BUS_ROM_WS 0x000000f0ul
+#define BUS_APER_REG_DIS 0x00000010ul /* VTB/GTB/LT */
+#define BUS_EXTRA_PIPE_DIS 0x00000020ul /* VTB/GTB/LT */
+#define BUS_MASTER_DIS 0x00000040ul /* VTB/GTB/LT */
+#define BUS_ROM_WRT_EN 0x00000080ul /* GTPro */
+#define BUS_ROM_PAGE 0x00000f00ul
+#define BUS_MINOR_REV_ID 0x00000700ul /* LTPro */
+/* First silicom - Prototype (A11) 0x00000000ul */
+/* Metal mask spin (A12 & A13) 0x00000100ul */
+/* All layer spin (A21) 0x00000200ul */
+/* Fast metal spin (A22) - Prod. 0x00000300ul */
+/* All layer spin (A31) 0x00000700ul */
+/* ? 0x00000800ul */ /* LTPro */
+#define BUS_CHIP_HIDDEN_REV 0x00000300ul /* XC/XL */
+/* ? 0x00001c00ul */ /* XC/XL */
+#define BUS_ROM_DIS 0x00001000ul
+#define BUS_IO_16_EN 0x00002000ul /* GX */
+#define BUS_PCI_READ_RETRY_EN 0x00002000ul /* VTB/GTB/LT */
+#define BUS_DAC_SNOOP_EN 0x00004000ul
+#define BUS_PCI_RETRY_EN 0x00008000ul /* VT/GT */
+#define BUS_PCI_WRT_RETRY_EN 0x00008000ul /* VTB/GTB/LT */
+#define BUS_FIFO_WS 0x000f0000ul
+#define BUS_RETRY_WS 0x000f0000ul /* VTB/GTB/LT */
+#define BUS_FIFO_ERR_INT_EN 0x00100000ul
+#define BUS_MSTR_RD_MULT 0x00100000ul /* VTB/GTB/LT */
+#define BUS_FIFO_ERR_INT 0x00200000ul
+#define BUS_MSTR_RD_LINE 0x00200000ul /* VTB/GTB/LT */
+#define BUS_HOST_ERR_INT_EN 0x00400000ul
+#define BUS_SUSPEND 0x00400000ul /* GTPro */
+#define BUS_HOST_ERR_INT 0x00800000ul
+#define BUS_LAT16X 0x00800000ul /* GTPro */
+#define BUS_PCI_DAC_WS 0x07000000ul
+#define BUS_RD_DISCARD_EN 0x01000000ul /* VTB/GTB/LT */
+#define BUS_RD_ABORT_EN 0x02000000ul /* VTB/GTB/LT */
+#define BUS_MSTR_WS 0x04000000ul /* VTB/GTB/LT */
+#define BUS_PCI_DAC_DLY 0x08000000ul
+#define BUS_EXT_REG_EN 0x08000000ul /* VT/GT */
+#define BUS_PCI_MEMW_WS 0x10000000ul
+#define BUS_MSTR_DISCONNECT_EN 0x10000000ul /* VTB/GTB/LT */
+#define BUS_PCI_BURST_DEC 0x20000000ul /* GX/CX */
+#define BUS_BURST 0x20000000ul /* 264xT */
+#define BUS_WRT_BURST 0x20000000ul /* VTB/GTB/LT */
+#define BUS_RDY_READ_DLY 0xc0000000ul
+#define BUS_READ_BURST 0x40000000ul /* VTB/GTB/LT */
+#define BUS_RDY_READ_DLY_B 0x80000000ul /* VTB/GTB/LT */
+#define LCD_INDEX BlockIOTag(0x29u) /* LTPro */
+#define LCD_REG_INDEX 0x0000003ful
+/* ? 0x000000c0ul */
+#define LCD_DISPLAY_DIS 0x00000100ul
+#define LCD_SRC_SEL 0x00000200ul
+#define LCD_SRC_SEL_CRTC1 0x00000000ul
+#define LCD_SRC_SEL_CRTC2 0x00000200ul
+#define LCD_CRTC2_DISPLAY_DIS 0x00000400ul
+#define LCD_GUI_ACTIVE 0x00000800ul /* XC/XL */
+/* ? 0x00fff000ul */
+#define LCD_MONDET_SENSE 0x01000000ul /* XC/XL */
+#define LCD_MONDET_INT_POL 0x02000000ul /* XC/XL */
+#define LCD_MONDET_INT_EN 0x04000000ul /* XC/XL */
+#define LCD_MONDET_INT 0x08000000ul /* XC/XL */
+#define LCD_MONDET_EN 0x10000000ul /* XC/XL */
+#define LCD_EN_PL 0x20000000ul /* XC/XL */
+/* ? 0xc0000000ul */
+#define HFB_PITCH_ADDR BlockIOTag(0x2au) /* LT */
+#define LCD_DATA BlockIOTag(0x2au) /* LTPro */
+#define EXT_MEM_CNTL BlockIOTag(0x2bu) /* VTB/GTB/LT */
+#define MEM_CNTL IOPortTag(0x14u, 0x2cu)
+#define CTL_MEM_SIZE 0x00000007ul
+/* ? 0x00000008ul */
+#define CTL_MEM_REFRESH 0x00000078ul /* VT/GT */
+#define CTL_MEM_SIZEB 0x0000000ful /* VTB/GTB/LT */
+#define CTL_MEM_RD_LATCH_EN 0x00000010ul
+#define CTL_MEM_RD_LATCH_DLY 0x00000020ul
+#define CTL_MEM_LATENCY 0x00000030ul /* VTB/GTB/LT */
+#define CTL_MEM_SD_LATCH_EN 0x00000040ul
+#define CTL_MEM_SD_LATCH_DLY 0x00000080ul
+#define CTL_MEM_LATCH 0x000000c0ul /* VTB/GTB/LT */
+#define CTL_MEM_WDOE_CNTL 0x000000c0ul /* XC/XL */
+#define CTL_MEM_FULL_PLS 0x00000100ul
+#define CTL_MEM_CYC_LNTH_AUX 0x00000180ul /* VT/GT */
+#define CTL_MEM_TRP 0x00000300ul /* VTB/GTB/LT */
+#define CTL_MEM_CYC_LNTH 0x00000600ul
+#define CTL_MEM_REFRESH_RATE 0x00001800ul /* 264xT */
+#define CTL_MEM_TRCD 0x00000c00ul /* VTB/GTB/LT */
+#define CTL_MEM_WR_RDY_SEL 0x00000800ul /* GX/CX */
+#define CTL_MEM_EXT_RMW_CYC_EN 0x00001000ul /* GX/CX */
+#define CTL_MEM_TCRD 0x00001000ul /* VTB/GTB/LT */
+#define CTL_MEM_DLL_RESET 0x00002000ul /* VT/GT */
+#define CTL_MEM_TR2W 0x00002000ul /* GTPro */
+#define CTL_MEM_ACTV_PRE 0x0000c000ul /* VT/GT */
+#define CTL_MEM_CAS_PHASE 0x00004000ul /* GTPro */
+#define CTL_MEM_OE_PULLBACK 0x00008000ul /* GTPro */
+#define CTL_MEM_TWR 0x0000c000ul /* XC/XL */
+#define CTL_MEM_BNDRY 0x00030000ul
+#define CTL_MEM_BNDRY_0K 0x00000000ul
+#define CTL_MEM_BNDRY_256K 0x00010000ul
+#define CTL_MEM_BNDRY_512K 0x00020000ul
+#define CTL_MEM_BNDRY_1024K 0x00030000ul
+#define CTL_MEM_DLL_GAIN_CNTL 0x00030000ul /* VT/GT */
+#define CTL_MEM_BNDRY_EN 0x00040000ul
+#define CTL_MEM_SDRAM_RESET 0x00040000ul /* VT/GT */
+#define CTL_MEM_TRAS 0x00070000ul /* VTB/GTB/LT */
+#define CTL_MEM_TILE_SELECT 0x00180000ul /* VT/GT */
+#define CTL_MEM_REFRESH_DIS 0x00080000ul /* VTB/GTB/LT */
+#define CTL_MEM_LOW_LATENCY_MODE 0x00200000ul /* VT/GT */
+#define CTL_MEM_CDE_PULLBACK 0x00400000ul /* VT/GT */
+#define CTL_MEM_REFRESH_RATE_B 0x00f00000ul /* VTB/GTB/LT */
+#define CTL_MEM_PIX_WIDTH 0x07000000ul
+#define CTL_MEM_LOWER_APER_ENDIAN 0x03000000ul /* VTB/GTB/LT */
+#define CTL_MEM_OE_SELECT 0x18000000ul /* VT/GT */
+#define CTL_MEM_UPPER_APER_ENDIAN 0x0c000000ul /* VTB/GTB/LT */
+/* ? 0xe0000000ul */
+#define CTL_MEM_PAGE_SIZE 0x30000000ul /* VTB/GTB/LT */
+#define MEM_VGA_WP_SEL IOPortTag(0x15u, 0x2du)
+#define MEM_VGA_WPS0 0x0000fffful
+#define MEM_VGA_WPS1 0xffff0000ul
+#define MEM_VGA_RP_SEL IOPortTag(0x16u, 0x2eu)
+#define MEM_VGA_RPS0 0x0000fffful
+#define MEM_VGA_RPS1 0xffff0000ul
+#define LT_GIO BlockIOTag(0x2fu) /* LT */
+#define I2C_CNTL_1 BlockIOTag(0x2fu) /* GTPro */
+#define I2C_DATA_PORT 0x000000fful
+#define I2C_DATA_COUNT 0x0000ff00ul
+#define I2C_ADDR_COUNT 0x00070000ul
+/* ? 0x00380000ul */
+#define I2C_SEL 0x00400000ul
+/* ? 0x00800000ul */
+#define I2C_TIME_LIMIT 0xff000000ul
+#define DAC_REGS IOPortTag(0x17u, 0x30u) /* 4 separate bytes */
+#define M64_DAC_WRITE (DAC_REGS + 0)
+#define M64_DAC_DATA (DAC_REGS + 1)
+#define M64_DAC_MASK (DAC_REGS + 2)
+#define M64_DAC_READ (DAC_REGS + 3)
+#define DAC_CNTL IOPortTag(0x18u, 0x31u)
+#define DAC_EXT_SEL 0x00000003ul
+#define DAC_EXT_SEL_RS2 0x000000001ul
+#define DAC_EXT_SEL_RS3 0x000000002ul
+#define DAC_RANGE_CTL 0x00000003ul /* VTB/GTB/LT */
+#define DAC_BLANKING 0x00000004ul /* 264xT */
+#define DAC_CMP_DIS 0x00000008ul /* 264xT */
+#define DAC1_CLK_SEL 0x00000010ul /* LTPro */
+#define DAC_PALETTE_ACCESS_CNTL 0x00000020ul /* LTPro */
+#define DAC_PALETTE2_SNOOP_EN 0x00000040ul /* LTPro */
+#define DAC_CMP_OUTPUT 0x00000080ul /* 264xT */
+#define DAC_8BIT_EN 0x00000100ul
+#define DAC_PIX_DLY 0x00000600ul
+#define DAC_DIRECT 0x00000400ul /* VTB/GTB/LT */
+#define DAC_BLANK_ADJ 0x00001800ul
+#define DAC_PAL_CLK_SEL 0x00000800ul /* VTB/GTB/LT */
+#define DAC_CRT_SENSE 0x00000800ul /* XC/XL */
+#define DAC_CRT_DETECTION_ON 0x00001000ul /* XC/XL */
+#define DAC_VGA_ADR_EN 0x00002000ul
+#define DAC_FEA_CON_EN 0x00004000ul /* 264xT */
+#define DAC_PDMN 0x00008000ul /* 264xT */
+#define DAC_TYPE 0x00070000ul
+/* ? 0x00f80000ul */
+#define DAC_MON_ID_STATE0 0x01000000ul /* GX-E+/CX */
+#define DAC_GIO_STATE_1 0x01000000ul /* 264xT */
+#define DAC_MON_ID_STATE1 0x02000000ul /* GX-E+/CX */
+#define DAC_GIO_STATE_0 0x02000000ul /* 264xT */
+#define DAC_MON_ID_STATE2 0x04000000ul /* GX-E+/CX */
+#define DAC_GIO_STATE_4 0x04000000ul /* 264xT */
+#define DAC_MON_ID_DIR0 0x08000000ul /* GX-E+/CX */
+#define DAC_GIO_DIR_1 0x08000000ul /* 264xT */
+#define DAC_MON_ID_DIR1 0x10000000ul /* GX-E+/CX */
+#define DAC_GIO_DIR_0 0x10000000ul /* 264xT */
+#define DAC_MON_ID_DIR2 0x20000000ul /* GX-E+/CX */
+#define DAC_GIO_DIR_4 0x20000000ul /* 264xT */
+#define DAC_MAN_CMP_STATE 0x40000000ul /* GX-E+ */
+#define DAC_RW_WS 0x80000000ul /* VT/GT */
+#define HORZ_STRETCHING BlockIOTag(0x32u) /* LT */
+#define HORZ_STRETCH_BLEND 0x00000ffful
+#define HORZ_STRETCH_RATIO 0x0000fffful
+#define HORZ_STRETCH_LOOP 0x00070000ul
+#define HORZ_STRETCH_LOOP09 0x00000000ul
+#define HORZ_STRETCH_LOOP11 0x00010000ul
+#define HORZ_STRETCH_LOOP12 0x00020000ul
+#define HORZ_STRETCH_LOOP14 0x00030000ul
+#define HORZ_STRETCH_LOOP15 0x00040000ul
+/* ? 0x00050000ul */
+/* ? 0x00060000ul */
+/* ? 0x00070000ul */
+/* ? 0x00080000ul */
+#define HORZ_PANEL_SIZE 0x0ff00000ul /* XC/XL */
+/* ? 0x10000000ul */
+#define AUTO_HORZ_RATIO 0x20000000ul /* XC/XL */
+#define HORZ_STRETCH_MODE 0x40000000ul
+#define HORZ_STRETCH_EN 0x80000000ul
+#define EXT_DAC_REGS BlockIOTag(0x32u) /* GTPro */
+#define EXT_DAC_REG_SEL 0x0000000ful
+/* ? 0x000000f0ul */
+#define EXT_DAC_DATA 0x0000ff00ul
+#define EXT_DAC_EN 0x00010000ul
+#define EXT_DAC_WID 0x00020000ul
+/* ? 0xfffc0000ul */
+#define VERT_STRETCHING BlockIOTag(0x33u) /* LT */
+#define VERT_STRETCH_RATIO0 0x000003fful
+#define VERT_STRETCH_RATIO1 0x000ffc00ul
+#define VERT_STRETCH_RATIO2 0x3ff00000ul
+#define VERT_STRETCH_USE0 0x40000000ul
+#define VERT_STRETCH_EN 0x80000000ul
+#define GEN_TEST_CNTL IOPortTag(0x19u, 0x34u)
+#define GEN_EE_DATA_OUT 0x00000001ul /* GX/CX */
+#define GEN_GIO2_DATA_OUT 0x00000001ul /* 264xT */
+#define GEN_EE_CLOCK 0x00000002ul /* GX/CX */
+/* ? 0x00000002ul */ /* 264xT */
+#define GEN_EE_CHIP_SEL 0x00000004ul /* GX/CX */
+#define GEN_GIO3_DATA_OUT 0x00000004ul /* 264xT */
+#define GEN_EE_DATA_IN 0x00000008ul /* GX/CX */
+#define GEN_GIO2_DATA_IN 0x00000008ul /* 264xT */
+#define GEN_EE_EN 0x00000010ul /* GX/CX */
+#define GEN_GIO2_ENABLE 0x00000010ul /* 264xT */
+#define GEN_ICON2_ENABLE 0x00000010ul /* XC/XL */
+#define GEN_OVR_OUTPUT_EN 0x00000020ul /* GX/CX */
+#define GEN_GIO2_WRITE 0x00000020ul /* 264xT */
+#define GEN_CUR2_ENABLE 0x00000020ul /* XC/XL */
+#define GEN_OVR_POLARITY 0x00000040ul /* GX/CX */
+#define GEN_ICON_ENABLE 0x00000040ul /* XC/XL */
+#define GEN_CUR_EN 0x00000080ul
+#define GEN_GUI_EN 0x00000100ul /* GX/CX */
+#define GEN_GUI_RESETB 0x00000100ul /* 264xT */
+#define GEN_BLOCK_WR_EN 0x00000200ul /* GX */
+/* ? 0x00000200ul */ /* CX/264xT */
+#define GEN_SOFT_RESET 0x00000200ul /* VTB/GTB/LT */
+#define GEN_MEM_TRISTATE 0x00000400ul /* GTPro */
+/* ? 0x00000800ul */
+#define GEN_TEST_VECT_MODE 0x00003000ul /* VT/GT */
+/* ? 0x0000c000ul */
+#define GEN_TEST_FIFO_EN 0x00010000ul /* GX/CX */
+#define GEN_TEST_GUI_REGS_EN 0x00020000ul /* GX/CX */
+#define GEN_TEST_VECT_EN 0x00040000ul /* GX/CX */
+#define GEN_TEST_CRC_STR 0x00080000ul /* GX-C/-D */
+/* ? 0x00080000ul */ /* GX-E+/CX */
+#define GEN_TEST_MODE_T 0x000f0000ul /* 264xT */
+#define GEN_TEST_MODE 0x00700000ul /* GX/CX */
+#define GEN_TEST_CNT_EN 0x00100000ul /* 264xT */
+#define GEN_TEST_CRC_EN 0x00200000ul /* 264xT */
+/* ? 0x00400000ul */ /* 264xT */
+/* ? 0x00800000ul */
+#define GEN_TEST_MEM_WR 0x01000000ul /* GX-C/-D */
+#define GEN_TEST_MEM_STROBE 0x02000000ul /* GX-C/-D */
+#define GEN_TEST_DST_SS_EN 0x04000000ul /* GX/CX */
+#define GEN_TEST_DST_SS_STROBE 0x08000000ul /* GX/CX */
+#define GEN_TEST_SRC_SS_EN 0x10000000ul /* GX/CX */
+#define GEN_TEST_SRC_SS_STROBE 0x20000000ul /* GX/CX */
+#define GEN_TEST_CNT_VALUE 0x3f000000ul /* 264xT */
+#define GEN_TEST_CC_EN 0x40000000ul /* GX/CX */
+#define GEN_TEST_CC_STROBE 0x80000000ul /* GX/CX */
+/* ? 0xc0000000ul */ /* 264xT */
+#define GEN_DEBUG_MODE 0xff000000ul /* VTB/GTB/LT */
+#define LCD_GEN_CTRL BlockIOTag(0x35u) /* LT */
+#define CRT_ON 0x00000001ul
+#define LCD_ON 0x00000002ul
+#define HORZ_DIVBY2_EN 0x00000004ul
+#define TRISTATE_MEM_EN 0x00000008ul
+#define DONT_DS_ICON 0x00000008ul /* LTPro */
+#define LOCK_8DOT 0x00000010ul
+#define ICON_ENABLE 0x00000020ul
+#define DONT_SHADOW_VPAR 0x00000040ul
+#define TOGGLE_EN 0x00000080ul
+#define V2CLK_PM_EN 0x00000080ul /* LTPro */
+#define RST_FM 0x00000100ul
+#define DISABLE_PCLK_RESET 0x00000200ul /* XC/XL */
+#define DIS_HOR_CRT_DIVBY2 0x00000400ul
+#define SCLK_SEL 0x00000800ul
+#define SCLK_DELAY 0x0000f000ul
+#define MCLK_PM_EN 0x00010000ul
+#define TVCLK_PM_EN 0x00010000ul /* LTPro */
+#define VCLK_DAC_PM_EN 0x00020000ul
+#define VCLK_LCD_OFF 0x00040000ul
+#define SLOWDOWN_XMCLK 0x00080000ul
+#define SELECT_WAIT_4MS 0x00080000ul /* LTPro */
+#define XTALIN_PM_EN 0x00080000ul /* XC/XL */
+#define LCD_CLK_RATIO 0x00100000ul
+#define V2CLK_DAC_PM_EN 0x00100000ul /* LTPro */
+#define LVDS_EN 0x00200000ul
+#define LVDS_PLL_EN 0x00400000ul
+#define LVDS_PLL_RESET 0x00800000ul
+#define LVDS_RESERVED_BITS 0x07000000ul
+#define CRTC_RW_SELECT 0x08000000ul /* LTPro */
+#define USE_SHADOWED_VEND 0x10000000ul
+#define USE_SHADOWED_ROWCUR 0x20000000ul
+#define SHADOW_EN 0x40000000ul
+#define SHADOW_RW_EN 0x80000000ul
+#define CUSTOM_MACRO_CNTL BlockIOTag(0x35u) /* GTPro */
+#define POWER_MANAGEMENT BlockIOTag(0x36u) /* LT */
+#define PWR_MGT_ON 0x00000001ul
+#define PWR_MGT_MODE 0x00000006ul
+#define AUTO_PWRUP_EN 0x00000008ul
+#define ACTIVITY_PIN_ON 0x00000010ul
+#define STANDBY_POL 0x00000020ul
+#define SUSPEND_POL 0x00000040ul
+#define SELF_REFRESH 0x00000080ul
+#define ACTIVITY_PIN_EN 0x00000100ul
+#define KEYBD_SNOOP 0x00000200ul
+#define USE_F32KHZ 0x00000400ul /* LTPro */
+#define DONT_USE_XTALIN 0x00000400ul /* XC/XL */
+#define TRISTATE_MEM_EN_P 0x00000800ul /* LTPro */
+#define LCDENG_TEST_MODE 0x0000f000ul
+#define STANDBY_COUNT 0x000f0000ul
+#define SUSPEND_COUNT 0x00f00000ul
+#define BAISON 0x01000000ul
+#define BLON 0x02000000ul
+#define DIGON 0x04000000ul
+#define PM_D3_SUPPORT_ENABLE 0x08000000ul /* XC/XL */
+#define STANDBY_NOW 0x10000000ul
+#define SUSPEND_NOW 0x20000000ul
+#define PWR_MGT_STATUS 0xc0000000ul
+#define CONFIG_CNTL IOPortTag(0x1au, 0x37u)
+#define CFG_MEM_AP_SIZE 0x00000003ul
+#define CFG_MEM_VGA_AP_EN 0x00000004ul
+/* ? 0x00000008ul */
+#define CFG_MEM_AP_LOC 0x00003ff0ul
+/* ? 0x0000c000ul */
+#define CFG_CARD_ID 0x00070000ul
+#define CFG_VGA_DIS 0x00080000ul
+/* ? 0x00f00000ul */
+#define CFG_CDE_WINDOW 0x3f000000ul /* VT/GT */
+/* ? 0xc0000000ul */
+#define CONFIG_CHIP_ID IOPortTag(0x1bu, 0x38u) /* Read */
+#define CFG_CHIP_TYPE0 0x000000fful
+#define CFG_CHIP_TYPE1 0x0000ff00ul
+#define CFG_CHIP_TYPE 0x0000fffful
+#define CFG_CHIP_CLASS 0x00ff0000ul
+#define CFG_CHIP_REV 0xff000000ul
+#define CFG_CHIP_VERSION 0x07000000ul /* 264xT */
+#define CFG_CHIP_FOUNDRY 0x38000000ul /* 264xT */
+#define CFG_CHIP_REVISION 0xc0000000ul /* 264xT */
+#define CONFIG_STATUS64_0 IOPortTag(0x1cu, 0x39u) /* Read (R/W (264xT)) */
+#define CFG_BUS_TYPE 0x00000007ul /* GX/CX */
+#define CFG_MEM_TYPE_T 0x00000007ul /* 264xT */
+#define CFG_MEM_TYPE 0x00000038ul /* GX/CX */
+#define CFG_DUAL_CAS_EN_T 0x00000008ul /* 264xT */
+#define CFG_ROM_128K_EN 0x00000008ul /* VTB/GTB/LT */
+#define CFG_ROM_REMAP 0x00000008ul /* GTPro */
+#define CFG_VGA_EN_T 0x00000010ul /* VT/GT */
+#define CFG_CLOCK_EN 0x00000020ul /* 264xT */
+#define CFG_DUAL_CAS_EN 0x00000040ul /* GX/CX */
+#define CFG_VMC_SENSE 0x00000040ul /* VT/GT */
+#define CFG_SHARED_MEM_EN 0x00000040ul /* VTB/GTB/LT */
+#define CFG_LOCAL_BUS_OPTION 0x00000180ul /* GX/CX */
+#define CFG_VFC_SENSE 0x00000080ul /* VT/GT */
+#define CFG_INIT_DAC_TYPE 0x00000e00ul /* GX/CX */
+#define CFG_INIT_CARD_ID 0x00007000ul /* GX-C/-D */
+#define CFG_BLK_WR_SIZE 0x00001000ul /* GX-E+ */
+#define CFG_INT_QSF_EN 0x00002000ul /* GX-E+ */
+/* ? 0x00004000ul */ /* GX-E+ */
+/* ? 0x00007000ul */ /* CX */
+#define CFG_TRI_BUF_DIS 0x00008000ul /* GX/CX */
+#define CFG_BOARD_ID 0x0000ff00ul /* VT/GT */
+#define CFG_EXT_RAM_ADDR 0x003f0000ul /* GX/CX */
+#define CFG_PANEL_ID 0x001f0000ul /* LT */
+#define CFG_MACROVISION_EN 0x00200000ul /* GTPro */
+#define CFG_ROM_DIS 0x00400000ul /* GX/CX */
+#define CFG_PCI33EN 0x00400000ul /* GTPro */
+#define CFG_VGA_EN 0x00800000ul /* GX/CX */
+#define CFG_FULLAGP 0x00800000ul /* GTPro */
+#define CFG_ARITHMOS_ENABLE 0x00800000ul /* XC/XL */
+#define CFG_LOCAL_BUS_CFG 0x01000000ul /* GX/CX */
+#define CFG_CHIP_EN 0x02000000ul /* GX/CX */
+#define CFG_LOCAL_READ_DLY_DIS 0x04000000ul /* GX/CX */
+#define CFG_ROM_OPTION 0x08000000ul /* GX/CX */
+#define CFG_BUS_OPTION 0x10000000ul /* GX/CX */
+#define CFG_LOCAL_DAC_WR_EN 0x20000000ul /* GX/CX */
+#define CFG_VLB_RDY_DIS 0x40000000ul /* GX/CX */
+#define CFG_AP_4GBYTE_DIS 0x80000000ul /* GX/CX */
+#define CONFIG_STATUS64_1 IOPortTag(0x1du, 0x3au) /* Read */
+#define CFG_PCI_DAC_CFG 0x00000001ul /* GX/CX */
+/* ? 0x0000001eul */ /* GX/CX */
+#define CFG_1C8_IO_SEL 0x00000020ul /* GX/CX */
+/* ? 0xffffffc0ul */ /* GX/CX */
+#define CRC_SIG 0xfffffffful /* 264xT */
+#define MPP_CONFIG BlockIOTag(0x3bu) /* VTB/GTB/LT */
+#define MPP_PRESCALE 0x00000007ul
+/* ? 0x00000008ul */
+#define MPP_NSTATES 0x00000030ul
+/* ? 0x00000000ul */
+#define MPP_NSTATES_2 0x00000010ul
+#define MPP_NSTATES_4 0x00000020ul
+#define MPP_NSTATES_8 0x00000030ul
+#define MPP_FORMAT 0x000000c0ul
+#define MPP_FORMAT_DO8 0x00000000ul
+#define MPP_FORMAT_DO16 0x00000040ul
+#define MPP_FORMAT_DA8 0x00000080ul
+#define MPP_FORMAT_DA16 0x000000c0ul
+#define MPP_WAIT_STATE 0x00000700ul
+#define MPP_CHKRDY_EN 0x00000800ul
+#define MPP_INSERT_WAIT 0x00001000ul
+#define MPP_TRISTATE_ADDR 0x00002000ul
+/* ? 0x00004000ul */
+#define MPP_READ_EARLY 0x00008000ul
+#define MPP_RW_MODE 0x00030000ul
+#define MPP_INT_MASK 0x000c0000ul
+#define MPP_AUTO_INC_EN 0x00300000ul
+#define MPP_CHKREQ_EN 0x00400000ul
+#define MPP_CHKREQ_MODE 0x00800000ul
+#define MPP_BUFFER_SIZE 0x03000000ul
+#define MPP_BUFFER_MODE 0x0c000000ul
+#define MPP_BUFFER_MODE_NORMAL 0x00000000ul
+#define MPP_BUFFER_MODE_PREFETCH 0x04000000ul
+#define MPP_BUFFER_MODE_BUS_MASTER 0x08000000ul
+/* ? 0x0c000000ul */
+/* ? 0x30000000ul */
+#define MPP_BUSY 0x40000000ul
+#define MPP_EN 0x80000000ul
+#define MPP_STROBE_SEQ BlockIOTag(0x3cu) /* VTB/GTB/LT */
+#define MPP_STB0_SEQ 0x000000fful
+#define MPP_STB1_SEQ 0x0000ff00ul
+/* ? 0xffff0000ul */
+#define MPP_ADDR BlockIOTag(0x3du) /* VTB/GTB/LT */
+#define MPP_DATA BlockIOTag(0x3eu) /* VTB/GTB/LT */
+#define TVO_CNTL BlockIOTag(0x3fu) /* VTB/GTB/LT */
+#define TVO_H_TOT_PIX 0x00000007ul
+#define TVO_PC_OVR_DIS 0x00000008ul
+#define TVO_H_TOT_EDGE 0x00000010ul
+/* ? 0x00000060ul */
+#define TVO_VBLANK_ONLY 0x00000080ul
+/* ? 0x0000ff00ul */
+#define TVO_MPEG_CLR_SRC 0x00030000ul
+/* ? 0x1ffc0000ul */
+#define TVO_MPEG_CLK_EN 0x20000000ul
+#define TVO_OVERRIDE_EN 0x40000000ul
+#define TVO_EN 0x80000000ul
+/* GP_IO IOPortTag(0x1eu, 0x1eu) */ /* See above */
+/* CRTC_H_TOTAL_DISP IOPortTag(0x1fu, 0x00u) */ /* Duplicate */
+#define DST_OFF_PITCH BlockIOTag(0x40u)
+#define DST_OFFSET 0x000ffffful
+/* ? 0x00300000ul */
+#define DST_PITCH 0xffc00000ul
+#define DST_X BlockIOTag(0x41u)
+#define DST_Y BlockIOTag(0x42u)
+#define DST_Y_X BlockIOTag(0x43u)
+#define DST_WIDTH BlockIOTag(0x44u)
+#define DST_HEIGHT BlockIOTag(0x45u)
+#define DST_HEIGHT_WIDTH BlockIOTag(0x46u)
+#define DST_X_WIDTH BlockIOTag(0x47u)
+#define DST_BRES_LNTH BlockIOTag(0x48u)
+#define DST_BRES_ERR BlockIOTag(0x49u)
+#define DST_BRES_INC BlockIOTag(0x4au)
+#define DST_BRES_DEC BlockIOTag(0x4bu)
+#define DST_CNTL BlockIOTag(0x4cu)
+#define DST_X_DIR 0x00000001ul
+#define DST_Y_DIR 0x00000002ul
+#define DST_Y_MAJOR 0x00000004ul
+#define DST_X_TILE 0x00000008ul
+#define DST_Y_TILE 0x00000010ul
+#define DST_LAST_PEL 0x00000020ul
+#define DST_POLYGON_EN 0x00000040ul
+#define DST_24_ROT_EN 0x00000080ul
+#define DST_24_ROT 0x00000700ul
+#define DST_BRES_SIGN 0x00000800ul /* GX/CX */
+#define DST_BRES_ZERO 0x00000800ul /* CT */
+#define DST_POLYGON_RTEDGE_DIS 0x00001000ul /* CT */
+#define TRAIL_X_DIR 0x00002000ul /* GT */
+#define TRAP_FILL_DIR 0x00004000ul /* GT */
+#define TRAIL_BRES_SIGN 0x00008000ul /* GT */
+/* ? 0x00010000ul */
+#define BRES_SIGN_AUTO 0x00020000ul /* GT */
+/* ? 0x00040000ul */
+#define ALPHA_OVERLAP_ENB 0x00080000ul /* GTPro */
+#define SUB_PIX_ON 0x00100000ul /* GTPro */
+/* ? 0xffe00000ul */
+/* DST_Y_X BlockIOTag(0x4du) */ /* Duplicate */
+#define TRAIL_BRES_ERR BlockIOTag(0x4eu) /* GT */
+#define TRAIL_BRES_INC BlockIOTag(0x4fu) /* GT */
+#define TRAIL_BRES_DEC BlockIOTag(0x50u) /* GT */
+#define LEAD_BRES_LNTH BlockIOTag(0x51u) /* GT */
+#define Z_OFF_PITCH BlockIOTag(0x52u) /* GT */
+#define Z_CNTL BlockIOTag(0x53u) /* GT */
+#define ALPHA_TST_CNTL BlockIOTag(0x54u) /* GTPro */
+/* ? BlockIOTag(0x55u) */
+#define SECONDARY_STW_EXP BlockIOTag(0x56u) /* GTPro */
+#define SECONDARY_S_X_INC BlockIOTag(0x57u) /* GTPro */
+#define SECONDARY_S_Y_INC BlockIOTag(0x58u) /* GTPro */
+#define SECONDARY_S_START BlockIOTag(0x59u) /* GTPro */
+#define SECONDARY_W_X_INC BlockIOTag(0x5au) /* GTPro */
+#define SECONDARY_W_Y_INC BlockIOTag(0x5bu) /* GTPro */
+#define SECONDARY_W_START BlockIOTag(0x5cu) /* GTPro */
+#define SECONDARY_T_X_INC BlockIOTag(0x5du) /* GTPro */
+#define SECONDARY_T_Y_INC BlockIOTag(0x5eu) /* GTPro */
+#define SECONDARY_T_START BlockIOTag(0x5fu) /* GTPro */
+#define SRC_OFF_PITCH BlockIOTag(0x60u)
+#define SRC_OFFSET 0x000ffffful
+/* ? 0x00300000ul */
+#define SRC_PITCH 0xffc00000ul
+#define SRC_X BlockIOTag(0x61u)
+#define SRC_Y BlockIOTag(0x62u)
+#define SRC_Y_X BlockIOTag(0x63u)
+#define SRC_WIDTH1 BlockIOTag(0x64u)
+#define SRC_HEIGHT1 BlockIOTag(0x65u)
+#define SRC_HEIGHT1_WIDTH1 BlockIOTag(0x66u)
+#define SRC_X_START BlockIOTag(0x67u)
+#define SRC_Y_START BlockIOTag(0x68u)
+#define SRC_Y_X_START BlockIOTag(0x69u)
+#define SRC_WIDTH2 BlockIOTag(0x6au)
+#define SRC_HEIGHT2 BlockIOTag(0x6bu)
+#define SRC_HEIGHT2_WIDTH2 BlockIOTag(0x6cu)
+#define SRC_CNTL BlockIOTag(0x6du)
+#define SRC_PATT_EN 0x00000001ul
+#define SRC_PATT_ROT_EN 0x00000002ul
+#define SRC_LINEAR_EN 0x00000004ul
+#define SRC_BYTE_ALIGN 0x00000008ul
+#define SRC_LINE_X_DIR 0x00000010ul
+#define SRC_8X8X8_BRUSH 0x00000020ul /* VTB/GTB */
+#define FAST_FILL_EN 0x00000040ul /* VTB/GTB */
+#define SRC_TRACK_DST 0x00000080ul /* VTB/GTB */
+#define BUS_MASTER_EN 0x00000100ul /* VTB/GTB */
+#define BUS_MASTER_SYNC 0x00000200ul /* VTB/GTB */
+#define BUS_MASTER_OP 0x00000c00ul /* VTB/GTB */
+#define SRC_8X8X8_BRUSH_LOADED 0x00001000ul /* VTB/GTB */
+#define COLOR_REG_WRITE_EN 0x00002000ul /* VTB/GTB */
+#define BLOCK_WRITE_EN 0x00004000ul /* VTB/GTB */
+/* ? 0xffff8000ul */
+/* ? BlockIOTag(0x6eu) */
+/* ? BlockIOTag(0x6fu) */
+#define SCALE_Y_OFF BlockIOTag(0x70u) /* GT */
+#define SCALE_OFF BlockIOTag(0x70u) /* GTPro */
+#define SECONDARY_SCALE_OFF BlockIOTag(0x70u) /* GTPro */
+#define TEX_0_OFF BlockIOTag(0x70u) /* GT */
+#define TEX_1_OFF BlockIOTag(0x71u) /* GT */
+#define TEX_2_OFF BlockIOTag(0x72u) /* GT */
+#define TEX_3_OFF BlockIOTag(0x73u) /* GT */
+#define TEX_4_OFF BlockIOTag(0x74u) /* GT */
+#define TEX_5_OFF BlockIOTag(0x75u) /* GT */
+#define TEX_6_OFF BlockIOTag(0x76u) /* GT */
+#define SCALE_WIDTH BlockIOTag(0x77u) /* GT */
+#define TEX_7_OFF BlockIOTag(0x77u) /* GT */
+#define SCALE_HEIGHT BlockIOTag(0x78u) /* GT */
+#define TEX_8_OFF BlockIOTag(0x78u) /* GT */
+#define TEX_9_OFF BlockIOTag(0x79u) /* GT */
+#define TEX_10_OFF BlockIOTag(0x7au) /* GT */
+#define S_Y_INC BlockIOTag(0x7bu) /* GT */
+#define SCALE_Y_PITCH BlockIOTag(0x7bu) /* GT */
+#define SCALE_X_INC BlockIOTag(0x7cu) /* GT */
+#define RED_X_INC BlockIOTag(0x7cu) /* GT */
+#define GREEN_X_INC BlockIOTag(0x7du) /* GT */
+#define SCALE_Y_INC BlockIOTag(0x7du) /* GT */
+#define SCALE_VACC BlockIOTag(0x7eu) /* GT */
+#define SCALE_3D_CNTL BlockIOTag(0x7fu) /* GT */
+#define HOST_DATA_0 BlockIOTag(0x80u)
+#define HOST_DATA_1 BlockIOTag(0x81u)
+#define HOST_DATA_2 BlockIOTag(0x82u)
+#define HOST_DATA_3 BlockIOTag(0x83u)
+#define HOST_DATA_4 BlockIOTag(0x84u)
+#define HOST_DATA_5 BlockIOTag(0x85u)
+#define HOST_DATA_6 BlockIOTag(0x86u)
+#define HOST_DATA_7 BlockIOTag(0x87u)
+#define HOST_DATA_8 BlockIOTag(0x88u)
+#define HOST_DATA_9 BlockIOTag(0x89u)
+#define HOST_DATA_A BlockIOTag(0x8au)
+#define HOST_DATA_B BlockIOTag(0x8bu)
+#define HOST_DATA_C BlockIOTag(0x8cu)
+#define HOST_DATA_D BlockIOTag(0x8du)
+#define HOST_DATA_E BlockIOTag(0x8eu)
+#define HOST_DATA_F BlockIOTag(0x8fu)
+#define HOST_CNTL BlockIOTag(0x90u)
+#define HOST_BYTE_ALIGN 0x00000001ul
+#define HOST_BIG_ENDIAN_EN 0x00000002ul /* GX-E/CT */
+/* ? 0xfffffffcul */
+#define BM_HOSTDATA BlockIOTag(0x91u) /* VTB/GTB */
+#define BM_ADDR BlockIOTag(0x92u) /* VTB/GTB */
+#define BM_DATA BlockIOTag(0x92u) /* VTB/GTB */
+#define BM_GUI_TABLE_CMD BlockIOTag(0x93u) /* GTPro */
+/* ? BlockIOTag(0x94u) */
+/* ? BlockIOTag(0x95u) */
+/* ? BlockIOTag(0x96u) */
+/* ? BlockIOTag(0x97u) */
+/* ? BlockIOTag(0x98u) */
+/* ? BlockIOTag(0x99u) */
+/* ? BlockIOTag(0x9au) */
+/* ? BlockIOTag(0x9bu) */
+/* ? BlockIOTag(0x9cu) */
+/* ? BlockIOTag(0x9du) */
+/* ? BlockIOTag(0x9eu) */
+/* ? BlockIOTag(0x9fu) */
+#define PAT_REG0 BlockIOTag(0xa0u)
+#define PAT_REG1 BlockIOTag(0xa1u)
+#define PAT_CNTL BlockIOTag(0xa2u)
+#define PAT_MONO_EN 0x00000001ul
+#define PAT_CLR_4x2_EN 0x00000002ul
+#define PAT_CLR_8x1_EN 0x00000004ul
+/* ? 0xfffffff8ul */
+/* ? BlockIOTag(0xa3u) */
+/* ? BlockIOTag(0xa4u) */
+/* ? BlockIOTag(0xa5u) */
+/* ? BlockIOTag(0xa6u) */
+/* ? BlockIOTag(0xa7u) */
+#define SC_LEFT BlockIOTag(0xa8u)
+#define SC_RIGHT BlockIOTag(0xa9u)
+#define SC_LEFT_RIGHT BlockIOTag(0xaau)
+#define SC_TOP BlockIOTag(0xabu)
+#define SC_BOTTOM BlockIOTag(0xacu)
+#define SC_TOP_BOTTOM BlockIOTag(0xadu)
+#define USR1_DST_OFF_PITCH BlockIOTag(0xaeu) /* LTPro */
+#define USR2_DST_OFF_PITCH BlockIOTag(0xafu) /* LTPro */
+#define DP_BKGD_CLR BlockIOTag(0xb0u)
+#define DP_FRGD_CLR BlockIOTag(0xb1u)
+#define DP_WRITE_MASK BlockIOTag(0xb2u)
+#define DP_CHAIN_MASK BlockIOTag(0xb3u)
+#define DP_CHAIN_1BPP 0x00000000ul /* Irrelevant */
+#define DP_CHAIN_4BPP 0x00008888ul
+#define DP_CHAIN_8BPP 0x00008080ul
+#define DP_CHAIN_8BPP_332 0x00009292ul
+#define DP_CHAIN_15BPP_1555 0x00004210ul
+#define DP_CHAIN_16BPP_565 0x00008410ul
+#define DP_CHAIN_24BPP_888 0x00008080ul
+#define DP_CHAIN_32BPP_8888 0x00008080ul
+/* ? 0xffff0000ul */
+#define DP_PIX_WIDTH BlockIOTag(0xb4u)
+#define DP_DST_PIX_WIDTH 0x0000000ful
+#define COMPOSITE_PIX_WIDTH 0x000000f0ul /* GTPro */
+#define DP_SRC_PIX_WIDTH 0x00000f00ul
+/* ? 0x00001000ul */
+#define DP_HOST_TRIPLE_EN 0x00002000ul /* GT2c/VT4 */
+#define DP_SRC_AUTONA_FIX_DIS 0x00004000ul /* GTB */
+#define DP_FAST_SRCCOPY_DIS 0x00008000ul /* GTB */
+#define DP_HOST_PIX_WIDTH 0x000f0000ul
+#define DP_CI4_RGB_INDEX 0x00f00000ul /* GTB */
+#define DP_BYTE_PIX_ORDER 0x01000000ul
+#define DP_CONVERSION_TEMP 0x02000000ul /* GTB */
+#define DP_CI4_RGB_LOW_NIBBLE 0x04000000ul /* GTB */
+#define DP_C14_RGB_HIGH_NIBBLE 0x08000000ul /* GTB */
+#define DP_SCALE_PIX_WIDTH 0xf0000000ul /* GTB */
+#define DP_MIX BlockIOTag(0xb5u)
+#define DP_BKGD_MIX 0x0000001ful
+/* ? 0x0000ffe0ul */
+#define DP_FRGD_MIX 0x001f0000ul
+/* ? 0xffe00000ul */
+#define DP_SRC BlockIOTag(0xb6u)
+#define DP_BKGD_SRC 0x00000007ul
+/* ? 0x000000feul */
+#define DP_FRGD_SRC 0x00000700ul
+/* ? 0x0000fe00ul */
+#define DP_MONO_SRC 0x00030000ul
+#define DP_MONO_SRC_ALLONES 0x00000000ul
+#define DP_MONO_SRC_PATTERN 0x00010000ul
+#define DP_MONO_SRC_HOST 0x00020000ul
+#define DP_MONO_SRC_BLIT 0x00030000ul
+/* ? 0xfffc0000ul */
+#define DP_FRGD_CLR_MIX BlockIOTag(0xb7u) /* VTB/GTB */
+#define DP_FRGD_BKGD_CLR BlockIOTag(0xb8u) /* VTB/GTB */
+/* ? BlockIOTag(0xb9u) */
+#define DST_X_Y BlockIOTag(0xbau) /* VTB/GTB */
+#define DST_WIDTH_HEIGHT BlockIOTag(0xbbu) /* VTB/GTB */
+#define USR_DST_PITCH BlockIOTag(0xbcu) /* GTPro */
+/* ? BlockIOTag(0xbdu) */
+#define DP_SET_GUI_ENGINE2 BlockIOTag(0xbeu) /* GTPro */
+#define DP_SET_GUI_ENGINE BlockIOTag(0xbfu) /* VTB/GTB */
+#define CLR_CMP_CLR BlockIOTag(0xc0u)
+#define CLR_CMP_MSK BlockIOTag(0xc1u)
+#define CLR_CMP_CNTL BlockIOTag(0xc2u)
+#define CLR_CMP_FN 0x00000007ul
+#define CLR_CMP_FN_FALSE 0x00000000ul
+#define CLR_CMP_FN_TRUE 0x00000001ul
+/* ? 0x00000002ul */
+/* ? 0x00000003ul */
+#define CLR_CMP_FN_NOT_EQUAL 0x00000004ul
+#define CLR_CMP_FN_EQUAL 0x00000005ul
+/* ? 0x00000006ul */
+/* ? 0x00000007ul */
+/* ? 0x00fffff8ul */
+#define CLR_CMP_SRC 0x03000000ul
+#define CLR_CMP_SRC_DST 0x00000000ul
+#define CLR_CMP_SRC_2D 0x01000000ul
+#define CLR_CMP_SRC_TEXEL 0x02000000ul
+/* ? 0x03000000ul */
+/* ? 0xfc000000ul */
+/* ? BlockIOTag(0xc3u) */
+#define FIFO_STAT BlockIOTag(0xc4u)
+#define FIFO_STAT_BITS 0x0000fffful
+/* ? 0x7fff0000ul */
+#define FIFO_ERR 0x80000000ul
+/* ? BlockIOTag(0xc5u) */
+/* ? BlockIOTag(0xc6u) */
+/* ? BlockIOTag(0xc7u) */
+#define CONTEXT_MASK BlockIOTag(0xc8u)
+/* ? BlockIOTag(0xc9u) */
+/* ? BlockIOTag(0xcau) */
+#define CONTEXT_LOAD_CNTL BlockIOTag(0xcbu)
+#define CONTEXT_LOAD_PTR 0x00007ffful
+/* ? 0x00008000ul */
+#define CONTEXT_LOAD_CMD 0x00030000ul
+#define CONTEXT_LOAD_NONE 0x00000000ul
+#define CONTEXT_LOAD_ONLY 0x00010000ul
+#define CONTEXT_LOAD_FILL 0x00020000ul
+#define CONTEXT_LOAD_LINE 0x00030000ul
+/* ? 0x7ffc0000ul */
+#define CONTEXT_LOAD_DIS 0x80000000ul
+#define GUI_TRAJ_CNTL BlockIOTag(0xccu)
+/* ? BlockIOTag(0xcdu) */
+#define GUI_STAT BlockIOTag(0xceu)
+#define GUI_ACTIVE 0x00000001ul
+/* ? 0x000000feul */
+#define DSTX_LT_SCISSOR_LEFT 0x00000100ul
+#define DSTX_GT_SCISSOR_RIGHT 0x00000200ul
+#define DSTY_LT_SCISSOR_TOP 0x00000400ul
+#define DSTY_GT_SCISSOR_BOTTOM 0x00000800ul
+/* ? 0x0000f000ul */
+#define GUI_FIFO 0x03ff0000ul /* VTB/GTB */
+/* ? 0xfc000000ul */
+/* ? BlockIOTag(0xcfu) */
+#define S_X_INC2 BlockIOTag(0xd0u) /* GTB */
+#define TEX_PALETTE_INDEX BlockIOTag(0xd0u) /* GTPro */
+#define S_Y_INC2 BlockIOTag(0xd1u) /* GTB */
+#define STW_EXP BlockIOTag(0xd1u) /* GTPro */
+#define S_XY_INC2 BlockIOTag(0xd2u) /* GTB */
+#define LOG_MAX_INC BlockIOTag(0xd2u) /* GTPro */
+#define S_XINC_START BlockIOTag(0xd3u) /* GTB */
+/* S_Y_INC BlockIOTag(0xd4u) */ /* Duplicate */
+/* SCALE_Y_PITCH BlockIOTag(0xd4u) */ /* Duplicate */
+#define S_START BlockIOTag(0xd5u) /* GTB */
+#define T_X_INC2 BlockIOTag(0xd6u) /* GTB */
+#define W_X_INC BlockIOTag(0xd6u) /* GTPro */
+#define T_Y_INC2 BlockIOTag(0xd7u) /* GTB */
+#define W_Y_INC BlockIOTag(0xd7u) /* GTPro */
+#define T_XY_INC2 BlockIOTag(0xd8u) /* GTB */
+#define W_START BlockIOTag(0xd8u) /* GTPro */
+#define T_XINC_START BlockIOTag(0xd9u) /* GTB */
+#define T_Y_INC BlockIOTag(0xdau) /* GTB */
+#define SECONDARY_SCALE_PITCH BlockIOTag(0xdau) /* GTPro */
+#define T_START BlockIOTag(0xdbu) /* GTB */
+#define TEX_SIZE_PITCH BlockIOTag(0xdcu) /* GTB */
+#define TEX_CNTL BlockIOTag(0xddu) /* GTPro */
+#define SECONDARY_TEX_OFFSET BlockIOTag(0xdeu) /* GTPro */
+#define TEX_PAL_WR BlockIOTag(0xdfu) /* GTB */
+#define TEX_PALETTE BlockIOTag(0xdfu) /* GTPro */
+#define SCALE_PITCH_BOTH BlockIOTag(0xe0u) /* GTPro */
+#define SECONDARY_SCALE_OFF_ACC BlockIOTag(0xe1u) /* GTPro */
+#define SCALE_OFF_ACC BlockIOTag(0xe2u) /* GTPro */
+#define SCALE_DST_Y_X BlockIOTag(0xe3u) /* GTPro */
+/* ? BlockIOTag(0xe4u) */
+/* ? BlockIOTag(0xe5u) */
+#define COMPOSITE_SHADOW_ID BlockIOTag(0xe6u) /* GTPro */
+#define SECONDARY_SCALE_X_INC BlockIOTag(0xe7u) /* GTPro */
+#define SPECULAR_RED_X_INC BlockIOTag(0xe7u) /* GTPro */
+#define SPECULAR_RED_Y_INC BlockIOTag(0xe8u) /* GTPro */
+#define SPECULAR_RED_START BlockIOTag(0xe9u) /* GTPro */
+#define SECONDARY_SCALE_HACC BlockIOTag(0xe9u) /* GTPro */
+#define SPECULAR_GREEN_X_INC BlockIOTag(0xeau) /* GTPro */
+#define SPECULAR_GREEN_Y_INC BlockIOTag(0xebu) /* GTPro */
+#define SPECULAR_GREEN_START BlockIOTag(0xecu) /* GTPro */
+#define SPECULAR_BLUE_X_INC BlockIOTag(0xedu) /* GTPro */
+#define SPECULAR_BLUE_Y_INC BlockIOTag(0xeeu) /* GTPro */
+#define SPECULAR_BLUE_START BlockIOTag(0xefu) /* GTPro */
+/* SCALE_X_INC BlockIOTag(0xf0u) */ /* Duplicate */
+/* RED_X_INC BlockIOTag(0xf0u) */ /* Duplicate */
+#define RED_Y_INC BlockIOTag(0xf1u) /* GTB */
+#define SCALE_HACC BlockIOTag(0xf2u) /* GTB */
+#define RED_START BlockIOTag(0xf2u) /* GTB */
+/* GREEN_X_INC BlockIOTag(0xf3u) */ /* Duplicate */
+/* SCALE_Y_INC BlockIOTag(0xf3u) */ /* Duplicate */
+#define GREEN_Y_INC BlockIOTag(0xf4u) /* GTB */
+#define SECONDARY_SCALE_Y_INC BlockIOTag(0xf4u) /* GTPro */
+#define SECONDARY_SCALE_VACC BlockIOTag(0xf5u) /* GTPro */
+#define GREEN_START BlockIOTag(0xf5u) /* GTB */
+#define BLUE_X_INC BlockIOTag(0xf6u) /* GTB */
+#define SCALE_XUV_INC BlockIOTag(0xf6u) /* GTB */
+#define BLUE_Y_INC BlockIOTag(0xf7u) /* GTB */
+#define BLUE_START BlockIOTag(0xf8u) /* GTB */
+#define SCALE_UV_HACC BlockIOTag(0xf8u) /* GTB */
+#define Z_X_INC BlockIOTag(0xf9u) /* GTB */
+#define Z_Y_INC BlockIOTag(0xfau) /* GTB */
+#define Z_START BlockIOTag(0xfbu) /* GTB */
+#define ALPHA_FOG_X_INC BlockIOTag(0xfcu) /* GTB */
+#define ALPHA_FOG_Y_INC BlockIOTag(0xfdu) /* GTB */
+#define ALPHA_FOG_START BlockIOTag(0xfeu) /* GTB */
+/* ? BlockIOTag(0xffu) */
+#define OVERLAY_Y_X_START BlockIOTag(0x100u)
+#define OVERLAY_Y_START 0x000003fful
+/* ? 0x0000fc00ul */
+#define OVERLAY_X_START 0x03ff0000ul
+/* ? 0x7c000000ul */
+#define OVERLAY_LOCK_START 0x80000000ul
+#define OVERLAY_Y_X_END BlockIOTag(0x101u)
+#define OVERLAY_Y_END 0x000003fful
+/* ? 0x0000fc00ul */
+#define OVERLAY_X_END 0x03ff0000ul
+/* ? 0x7c000000ul */
+#define OVERLAY_LOCK_END 0x80000000ul
+#define OVERLAY_VIDEO_KEY_CLR BlockIOTag(0x102u)
+#define OVERLAY_VIDEO_KEY_MSK BlockIOTag(0x103u)
+#define OVERLAY_GRAPHICS_KEY_CLR BlockIOTag(0x104u)
+#define OVERLAY_GRAPHICS_KEY_MSK BlockIOTag(0x105u)
+#define OVERLAY_KEY_CNTL BlockIOTag(0x106u)
+#define OVERLAY_VIDEO_FN 0x00000007ul
+/* ? 0x00000008ul */
+#define OVERLAY_GRAPHICS_FN 0x00000070ul
+/* ? 0x00000080ul */
+#define OVERLAY_CMP_MIX 0x00000100ul
+/* ? 0xfffffe00ul */
+/* ? BlockIOTag(0x107u) */
+#define OVERLAY_SCALE_INC BlockIOTag(0x108u)
+#define OVERLAY_SCALE_CNTL BlockIOTag(0x109u)
+#define SCALE_PIX_EXPAND 0x00000001ul
+#define SCALE_Y2R_TEMP 0x00000002ul
+#define SCALE_HORZ_MODE 0x00000004ul
+#define SCALE_VERT_MODE 0x00000008ul
+#define SCALE_SIGNED_UV 0x00000010ul
+#define SCALE_GAMMA_SEL 0x00000060ul
+/* ? 0x03ffff80ul */
+#define SCALE_BANDWIDTH 0x04000000ul
+#define SCALE_DIS_LIMIT 0x08000000ul
+/* ? 0x10000000ul */
+#define SCALE_CLK_FORCE_ON 0x20000000ul
+#define OVERLAY_EN 0x40000000ul
+#define SCALE_EN 0x80000000ul
+#define SCALER_HEIGHT_WIDTH BlockIOTag(0x10au)
+#define SCALER_TEST BlockIOTag(0x10bu)
+/* ? 0x00000001ul */
+#define SCALE_Y2R_DIS 0x00000002ul
+/* ? 0xfffffffcul */
+#define SCALER_THRESHOLD BlockIOTag(0x10cu)
+#define SCALER_BUF0_OFFSET BlockIOTag(0x10du) /* VTB/GTB */
+#define SCALER_BUF1_OFFSET BlockIOTag(0x10eu) /* VTB/GTB */
+#define SCALER_BUF_PITCH BlockIOTag(0x10fu) /* VTB/GTB */
+#define CAPTURE_Y_X BlockIOTag(0x110u)
+#define CAPTURE_START_END BlockIOTag(0x110u) /* VTB/GTB */
+#define CAPTURE_HEIGHT_WIDTH BlockIOTag(0x111u)
+#define CAPTURE_X_WIDTH BlockIOTag(0x111u) /* VTB/GTB */
+#define VIDEO_FORMAT BlockIOTag(0x112u)
+#define VIDEO_IN 0x0000000ful
+/* ? 0x00000000ul */
+/* ? 0x00000001ul */
+/* ? 0x00000002ul */
+/* ? 0x00000003ul */
+/* ? 0x00000004ul */
+/* ? 0x00000005ul */
+/* ? 0x00000006ul */
+/* ? 0x00000007ul */
+/* ? 0x00000008ul */
+/* ? 0x00000009ul */
+/* ? 0x0000000aul */
+#define VIDEO_IN_VYUY422 0x0000000bul
+#define VIDEO_IN_YVYU422 0x0000000cul
+/* ? 0x0000000dul */
+/* ? 0x0000000eul */
+/* ? 0x0000000ful */
+#define VIDEO_SIGNED_UV 0x00000010ul
+/* ? 0x0000ffe0ul */
+#define SCALER_IN 0x000f0000ul
+/* ? 0x00000000ul */
+/* ? 0x00010000ul */
+/* ? 0x00020000ul */
+#define SCALER_IN_15BPP 0x00030000ul
+#define SCALER_IN_16BPP 0x00040000ul
+/* ? 0x00050000ul */
+#define SCALER_IN_32BPP 0x00060000ul
+/* ? 0x00070000ul */
+/* ? 0x00080000ul */
+#define SCALER_IN_YUV9 0x00090000ul
+#define SCALER_IN_YUV12 0x000a0000ul
+#define SCALER_IN_VYUY422 0x000b0000ul
+#define SCALER_IN_YVYU422 0x000c0000ul
+/* ? 0x000d0000ul */
+/* ? 0x000e0000ul */
+/* ? 0x000f0000ul */
+/* ? 0x0ff00000ul */
+#define HOST_BYTE_SHIFT_EN 0x10000000ul
+#define HOST_YUV_APER 0x20000000ul
+#define HOST_MEM_MODE 0xc0000000ul
+#define HOST_MEM_MODE_NORMAL 0x00000000ul
+#define HOST_MEM_MODE_Y 0x40000000ul
+#define HOST_MEM_MODE_U 0x80000000ul
+#define HOST_MEM_MODE_V 0xc0000000ul
+#define VIDEO_CONFIG BlockIOTag(0x113u)
+#define VBI_START_END BlockIOTag(0x113u) /* VTB/GTB */
+#define CAPTURE_CONFIG BlockIOTag(0x114u)
+#define CAP_INPUT_MODE 0x00000001ul
+#define CAP_START_FIELD 0x00000002ul
+#define CAP_BUF_MODE 0x00000004ul
+#define CAP_START_BUF 0x00000008ul
+#define CAP_BUF_TYPE 0x00000030ul
+#define CAP_BUF_FIELD 0x00000000ul
+#define CAP_BUF_ALTERNATING 0x00000010ul
+#define CAP_BUF_FRAME 0x00000020ul
+/* ? 0x00000030ul */
+#define CAP_FIELD_FLIP 0x00000040ul
+#define CAP_CCIR656_EN 0x00000080ul
+/* ? 0x00000f00ul */
+#define CAP_MIRROR_EN 0x00001000ul
+#define ONESHOT_MIRROR_EN 0x00002000ul
+#define ONESHOT_MODE 0x00004000ul
+/* ? 0x00008000ul */
+#define CAP_HORZ_DOWN 0x00030000ul
+#define CAP_VERT_DOWN 0x000c0000ul
+#define ONESHOT_HORZ_DOWN 0x00300000ul
+#define ONESHOT_VERT_DOWN 0x00c00000ul
+/* ? 0x0f000000ul */
+#define OVL_BUF_MODE 0x10000000ul
+#define OVL_BUF_NEXT 0x20000000ul
+/* ? 0xc0000000ul */
+#define TRIG_CNTL BlockIOTag(0x115u)
+#define CAP_TRIGGER 0x00000003ul
+#define CAP_TRIGGER_NEXT 0x00000001ul
+/* ? 0x0000001cul */
+#define OVL_CUR_BUF 0x00000020ul
+#define OVL_BUF_STATUS 0x00000040ul
+#define CAP_BUF_STATUS 0x00000080ul
+/* ? 0x7fffff00ul */
+#define CAPTURE_EN 0x80000000ul
+#define VIDEO_SYNC_TEST BlockIOTag(0x116u)
+#define OVERLAY_EXCLUSIVE_HORZ BlockIOTag(0x116u) /* VTB/GTB */
+#define EXCLUSIVE_HORZ_START 0x000000fful
+#define EXCLUSIVE_HORZ_END 0x0000ff00ul
+#define EXCLUSIVE_HORZ_PORCH 0x00ff0000ul
+/* ? 0x7f000000ul */
+#define EXCLUSIVE_EN 0x80000000ul
+#define EXT_CRTC_GEN_CNTL_R BlockIOTag(0x117u) /* VT-A4 (R) */
+#define OVERLAY_EXCLUSIVE_VERT BlockIOTag(0x117u) /* VTB/GTB */
+#define EXCLUSIVE_VERT_START 0x000003fful
+/* ? 0x0000fc00ul */
+#define EXCLUSIVE_VERT_END 0x03ff0000ul
+/* ? 0xfc000000ul */
+#define VMC_CONFIG BlockIOTag(0x118u)
+#define VBI_WIDTH BlockIOTag(0x118u) /* VTB/GTB */
+#define VMC_STATUS BlockIOTag(0x119u)
+#define CAPTURE_DEBUG BlockIOTag(0x119u) /* VTB/GTB */
+#define VMC_CMD BlockIOTag(0x11au)
+#define VIDEO_SYNC_TEST_B BlockIOTag(0x11au) /* VTB/GTB */
+#define VMC_ARG0 BlockIOTag(0x11bu)
+#define VMC_ARG1 BlockIOTag(0x11cu)
+#define SNAPSHOT_VH_COUNTS BlockIOTag(0x11cu) /* GTPro */
+#define VMC_SNOOP_ARG0 BlockIOTag(0x11du)
+#define SNAPSHOT_F_COUNT BlockIOTag(0x11du) /* GTPro */
+#define VMC_SNOOP_ARG1 BlockIOTag(0x11eu)
+#define N_VIF_COUNT BlockIOTag(0x11eu) /* GTPro */
+#define SNAPSHOT_VIF_COUNT BlockIOTag(0x11fu) /* GTPro */
+#define BUF0_OFFSET BlockIOTag(0x120u)
+#define CAPTURE_BUF0_OFFSET BlockIOTag(0x120u) /* VTB/GTB */
+#define CAPTURE_BUF1_OFFSET BlockIOTag(0x121u) /* VTB/GTB */
+#define ONESHOT_BUF_OFFSET BlockIOTag(0x122u) /* VTB/GTB */
+#define BUF0_PITCH BlockIOTag(0x123u)
+/* ? BlockIOTag(0x124u) */
+/* ? BlockIOTag(0x125u) */
+#define BUF1_OFFSET BlockIOTag(0x126u)
+/* ? BlockIOTag(0x127u) */
+/* ? BlockIOTag(0x128u) */
+#define BUF1_PITCH BlockIOTag(0x129u)
+/* ? BlockIOTag(0x12au) */
+#define BUF0_CAP_ODD_OFFSET BlockIOTag(0x12bu)
+#define BUF1_CAP_ODD_OFFSET BlockIOTag(0x12cu)
+#define SNAPSHOT2_VH_COUNTS BlockIOTag(0x12cu) /* LTPro */
+#define SNAPSHOT2_F_COUNT BlockIOTag(0x12du) /* LTPro */
+#define N_VIF2_COUNT BlockIOTag(0x12eu) /* LTPro */
+#define SNAPSHOT2_VIF_COUNT BlockIOTag(0x12fu) /* LTPro */
+#define VMC_STRM_DATA_0 BlockIOTag(0x130u)
+/* MPP_CONFIG BlockIOTag(0x130u) */ /* See 0x3bu */
+#define VMC_STRM_DATA_1 BlockIOTag(0x131u)
+/* MPP_STROBE_SEQ BlockIOTag(0x131u) */ /* See 0x3cu */
+#define VMC_STRM_DATA_2 BlockIOTag(0x132u)
+/* MPP_ADDR BlockIOTag(0x132u) */ /* See 0x3du */
+#define VMC_STRM_DATA_3 BlockIOTag(0x133u)
+/* MPP_DATA BlockIOTag(0x133u) */ /* See 0x3eu */
+#define VMC_STRM_DATA_4 BlockIOTag(0x134u)
+#define VMC_STRM_DATA_5 BlockIOTag(0x135u)
+#define VMC_STRM_DATA_6 BlockIOTag(0x136u)
+#define VMC_STRM_DATA_7 BlockIOTag(0x137u)
+#define VMC_STRM_DATA_8 BlockIOTag(0x138u)
+#define VMC_STRM_DATA_9 BlockIOTag(0x139u)
+#define VMC_STRM_DATA_A BlockIOTag(0x13au)
+#define VMC_STRM_DATA_B BlockIOTag(0x13bu)
+#define VMC_STRM_DATA_C BlockIOTag(0x13cu)
+#define VMC_STRM_DATA_D BlockIOTag(0x13du)
+#define VMC_STRM_DATA_E BlockIOTag(0x13eu)
+#define VMC_STRM_DATA_F BlockIOTag(0x13fu)
+/* TVO_CNTL BlockIOTag(0x140u) */ /* See 0x3fu */
+/* ? BlockIOTag(0x141u) */
+/* ? BlockIOTag(0x142u) */
+/* ? BlockIOTag(0x143u) */
+/* ? BlockIOTag(0x144u) */
+/* ? BlockIOTag(0x145u) */
+/* ? BlockIOTag(0x146u) */
+/* ? BlockIOTag(0x147u) */
+/* ? BlockIOTag(0x148u) */
+/* ? BlockIOTag(0x149u) */
+/* ? BlockIOTag(0x14au) */
+/* ? BlockIOTag(0x14bu) */
+/* ? BlockIOTag(0x14cu) */
+/* ? BlockIOTag(0x14du) */
+/* ? BlockIOTag(0x14eu) */
+/* ? BlockIOTag(0x14fu) */
+/* ? BlockIOTag(0x150u) */
+#define CRT_HORZ_VERT_LOAD BlockIOTag(0x151u) /* VTB/GTB */
+#define AGP_BASE BlockIOTag(0x152u) /* GTPro */
+#define AGP_CNTL BlockIOTag(0x153u) /* GTPro */
+#define SCALER_COLOUR_CNTL BlockIOTag(0x154u) /* GTPro */
+#define SCALE_BRIGHTNESS 0x0000007ful
+/* ? 0x00000080ul */
+#define SCALE_SATURATION_U 0x00001f00ul
+/* ? 0x0000e000ul */
+#define SCALE_SATURATION_V 0x001f0000ul
+#define SCALE_VERT_ADJ_UV 0x0fe00000ul
+#define SCALE_HORZ_ADJ_UV 0xf0000000ul
+#define SCALER_H_COEFF0 BlockIOTag(0x155u) /* GTPro */
+#define SCALER_H_COEFF1 BlockIOTag(0x156u) /* GTPro */
+#define SCALER_H_COEFF2 BlockIOTag(0x157u) /* GTPro */
+#define SCALER_H_COEFF3 BlockIOTag(0x158u) /* GTPro */
+#define SCALER_H_COEFF4 BlockIOTag(0x159u) /* GTPro */
+/* ? BlockIOTag(0x15au) */
+/* ? BlockIOTag(0x15bu) */
+#define GUI_CMDFIFO_DEBUG BlockIOTag(0x15cu) /* GT2c/VT4 */
+#define GUI_CMDFIFO_DATA BlockIOTag(0x15du) /* GT2c/VT4 */
+#define GUI_CNTL BlockIOTag(0x15eu) /* GT2c/VT4 */
+#define CMDFIFO_SIZE_MODE 0x00000003ul
+/* ? 0x0000fffcul */
+#define IDCT_PRSR_MODE 0x00010000ul /* XL/XC */
+#define IDCT_BLOCK_GUI_INITIATOR 0x00020000ul /* XL/XC */
+/* ? 0xfffc0000ul */
+/* ? BlockIOTag(0x15fu) */
+#define BM_FRAME_BUF_OFFSET BlockIOTag(0x160u) /* VTB/GTB */
+#define BM_SYSTEM_MEM_ADDR BlockIOTag(0x161u) /* VTB/GTB */
+#define BM_COMMAND BlockIOTag(0x162u) /* VTB/GTB */
+#define BM_STATUS BlockIOTag(0x163u) /* VTB/GTB */
+/* ? BlockIOTag(0x164u) */
+/* ? BlockIOTag(0x165u) */
+/* ? BlockIOTag(0x166u) */
+/* ? BlockIOTag(0x167u) */
+/* ? BlockIOTag(0x168u) */
+/* ? BlockIOTag(0x169u) */
+/* ? BlockIOTag(0x16au) */
+/* ? BlockIOTag(0x16bu) */
+/* ? BlockIOTag(0x16cu) */
+/* ? BlockIOTag(0x16du) */
+#define BM_GUI_TABLE BlockIOTag(0x16eu) /* VTB/GTB */
+#define BM_SYSTEM_TABLE BlockIOTag(0x16fu) /* VTB/GTB */
+/* ? BlockIOTag(0x170u) */
+/* ? BlockIOTag(0x171u) */
+/* ? BlockIOTag(0x172u) */
+/* ? BlockIOTag(0x173u) */
+/* ? BlockIOTag(0x174u) */
+#define SCALER_BUF0_OFFSET_U BlockIOTag(0x175u) /* GTPro */
+#define SCALER_BUF0_OFFSET_V BlockIOTag(0x176u) /* GTPro */
+#define SCALER_BUF1_OFFSET_U BlockIOTag(0x177u) /* GTPro */
+#define SCALER_BUF1_OFFSET_V BlockIOTag(0x178u) /* GTPro */
+/* ? BlockIOTag(0x179u) */
+/* ? BlockIOTag(0x17au) */
+/* ? BlockIOTag(0x17bu) */
+/* ? BlockIOTag(0x17cu) */
+/* ? BlockIOTag(0x17du) */
+/* ? BlockIOTag(0x17eu) */
+/* ? BlockIOTag(0x17fu) */
+/* ? BlockIOTag(0x180u) */
+/* ? BlockIOTag(0x181u) */
+/* ? BlockIOTag(0x182u) */
+/* ? BlockIOTag(0x183u) */
+/* ? BlockIOTag(0x184u) */
+/* ? BlockIOTag(0x185u) */
+/* ? BlockIOTag(0x186u) */
+/* ? BlockIOTag(0x187u) */
+/* ? BlockIOTag(0x188u) */
+/* ? BlockIOTag(0x189u) */
+/* ? BlockIOTag(0x18au) */
+/* ? BlockIOTag(0x18bu) */
+/* ? BlockIOTag(0x18cu) */
+/* ? BlockIOTag(0x18du) */
+/* ? BlockIOTag(0x18eu) */
+/* ? BlockIOTag(0x18fu) */
+#define VERTEX_1_S BlockIOTag(0x190u) /* GTPro */
+#define VERTEX_1_T BlockIOTag(0x191u) /* GTPro */
+#define VERTEX_1_W BlockIOTag(0x192u) /* GTPro */
+#define VERTEX_1_SPEC_ARGB BlockIOTag(0x193u) /* GTPro */
+#define VERTEX_1_Z BlockIOTag(0x194u) /* GTPro */
+#define VERTEX_1_ARGB BlockIOTag(0x195u) /* GTPro */
+#define VERTEX_1_X_Y BlockIOTag(0x196u) /* GTPro */
+#define ONE_OVER_AREA BlockIOTag(0x197u) /* GTPro */
+#define VERTEX_2_S BlockIOTag(0x198u) /* GTPro */
+#define VERTEX_2_T BlockIOTag(0x199u) /* GTPro */
+#define VERTEX_2_W BlockIOTag(0x19au) /* GTPro */
+#define VERTEX_2_SPEC_ARGB BlockIOTag(0x19bu) /* GTPro */
+#define VERTEX_2_Z BlockIOTag(0x19cu) /* GTPro */
+#define VERTEX_2_ARGB BlockIOTag(0x19du) /* GTPro */
+#define VERTEX_2_X_Y BlockIOTag(0x19eu) /* GTPro */
+/* ONE_OVER_AREA BlockIOTag(0x19fu) */ /* Duplicate */
+#define VERTEX_3_S BlockIOTag(0x1a0u) /* GTPro */
+#define VERTEX_3_T BlockIOTag(0x1a1u) /* GTPro */
+#define VERTEX_3_W BlockIOTag(0x1a2u) /* GTPro */
+#define VERTEX_3_SPEC_ARGB BlockIOTag(0x1a3u) /* GTPro */
+#define VERTEX_3_Z BlockIOTag(0x1a4u) /* GTPro */
+#define VERTEX_3_ARGB BlockIOTag(0x1a5u) /* GTPro */
+#define VERTEX_3_X_Y BlockIOTag(0x1a6u) /* GTPro */
+/* ONE_OVER_AREA BlockIOTag(0x1a7u) */ /* Duplicate */
+#define VERTEX_3_SECONDARY_S BlockIOTag(0x1a8u) /* GTPro */
+#define VERTEX_3_SECONDARY_T BlockIOTag(0x1a9u) /* GTPro */
+#define VERTEX_3_SECONDARY_W BlockIOTag(0x1aau) /* GTPro */
+/* VERTEX_1_S BlockIOTag(0x1abu) */ /* Duplicate */
+/* VERTEX_1_T BlockIOTag(0x1acu) */ /* Duplicate */
+/* VERTEX_1_W BlockIOTag(0x1adu) */ /* Duplicate */
+/* VERTEX_2_S BlockIOTag(0x1aeu) */ /* Duplicate */
+/* VERTEX_2_T BlockIOTag(0x1afu) */ /* Duplicate */
+/* VERTEX_2_W BlockIOTag(0x1b0u) */ /* Duplicate */
+/* VERTEX_3_S BlockIOTag(0x1b1u) */ /* Duplicate */
+/* VERTEX_3_T BlockIOTag(0x1b2u) */ /* Duplicate */
+/* VERTEX_3_W BlockIOTag(0x1b3u) */ /* Duplicate */
+/* VERTEX_1_SPEC_ARGB BlockIOTag(0x1b4u) */ /* Duplicate */
+/* VERTEX_2_SPEC_ARGB BlockIOTag(0x1b5u) */ /* Duplicate */
+/* VERTEX_3_SPEC_ARGB BlockIOTag(0x1b6u) */ /* Duplicate */
+/* VERTEX_1_Z BlockIOTag(0x1b7u) */ /* Duplicate */
+/* VERTEX_2_Z BlockIOTag(0x1b8u) */ /* Duplicate */
+/* VERTEX_3_Z BlockIOTag(0x1b9u) */ /* Duplicate */
+/* VERTEX_1_ARGB BlockIOTag(0x1bau) */ /* Duplicate */
+/* VERTEX_2_ARGB BlockIOTag(0x1bbu) */ /* Duplicate */
+/* VERTEX_3_ARGB BlockIOTag(0x1bcu) */ /* Duplicate */
+/* VERTEX_1_X_Y BlockIOTag(0x1bdu) */ /* Duplicate */
+/* VERTEX_2_X_Y BlockIOTag(0x1beu) */ /* Duplicate */
+/* VERTEX_3_X_Y BlockIOTag(0x1bfu) */ /* Duplicate */
+#define ONE_OVER_AREA_UC BlockIOTag(0x1c0u) /* GTPro */
+#define SETUP_CNTL BlockIOTag(0x1c1u) /* GTPro */
+/* ? BlockIOTag(0x1c2u) */
+/* ? BlockIOTag(0x1c3u) */
+/* ? BlockIOTag(0x1c4u) */
+/* ? BlockIOTag(0x1c5u) */
+/* ? BlockIOTag(0x1c6u) */
+/* ? BlockIOTag(0x1c7u) */
+/* ? BlockIOTag(0x1c8u) */
+/* ? BlockIOTag(0x1c9u) */
+#define VERTEX_1_SECONDARY_S BlockIOTag(0x1cau) /* GTPro */
+#define VERTEX_1_SECONDARY_T BlockIOTag(0x1cbu) /* GTPro */
+#define VERTEX_1_SECONDARY_W BlockIOTag(0x1ccu) /* GTPro */
+#define VERTEX_2_SECONDARY_S BlockIOTag(0x1cdu) /* GTPro */
+#define VERTEX_2_SECONDARY_T BlockIOTag(0x1ceu) /* GTPro */
+#define VERTEX_2_SECONDARY_W BlockIOTag(0x1cfu) /* GTPro */
+/* ? BlockIOTag(0x1d0u) */
+/* ? BlockIOTag(0x1d1u) */
+/* ? BlockIOTag(0x1d2u) */
+/* ? BlockIOTag(0x1d3u) */
+/* ? BlockIOTag(0x1d4u) */
+/* ? BlockIOTag(0x1d5u) */
+/* ? BlockIOTag(0x1d6u) */
+/* ? BlockIOTag(0x1d7u) */
+/* ? BlockIOTag(0x1d8u) */
+/* ? BlockIOTag(0x1d9u) */
+/* ? BlockIOTag(0x1dau) */
+/* ? BlockIOTag(0x1dbu) */
+/* ? BlockIOTag(0x1dcu) */
+/* ? BlockIOTag(0x1ddu) */
+/* ? BlockIOTag(0x1deu) */
+/* ? BlockIOTag(0x1dfu) */
+/* ? BlockIOTag(0x1e0u) */
+/* ? BlockIOTag(0x1e1u) */
+/* ? BlockIOTag(0x1e2u) */
+/* ? BlockIOTag(0x1e3u) */
+/* ? BlockIOTag(0x1e4u) */
+/* ? BlockIOTag(0x1e5u) */
+/* ? BlockIOTag(0x1e6u) */
+/* ? BlockIOTag(0x1e7u) */
+/* ? BlockIOTag(0x1e8u) */
+/* ? BlockIOTag(0x1e9u) */
+/* ? BlockIOTag(0x1eau) */
+/* ? BlockIOTag(0x1ebu) */
+/* ? BlockIOTag(0x1ecu) */
+/* ? BlockIOTag(0x1edu) */
+/* ? BlockIOTag(0x1eeu) */
+/* ? BlockIOTag(0x1efu) */
+/* ? BlockIOTag(0x1f0u) */
+/* ? BlockIOTag(0x1f1u) */
+/* ? BlockIOTag(0x1f2u) */
+/* ? BlockIOTag(0x1f3u) */
+/* ? BlockIOTag(0x1f4u) */
+/* ? BlockIOTag(0x1f5u) */
+/* ? BlockIOTag(0x1f6u) */
+/* ? BlockIOTag(0x1f7u) */
+/* ? BlockIOTag(0x1f8u) */
+/* ? BlockIOTag(0x1f9u) */
+/* ? BlockIOTag(0x1fau) */
+/* ? BlockIOTag(0x1fbu) */
+/* ? BlockIOTag(0x1fcu) */
+/* ? BlockIOTag(0x1fdu) */
+/* ? BlockIOTag(0x1feu) */
+/* ? BlockIOTag(0x1ffu) */
+
+/* Definitions for MEM_CNTL's CTL_MEM_?????_APER_ENDIAN fields */
+#define CTL_MEM_APER_BYTE_ENDIAN 0x00u
+#define CTL_MEM_APER_WORD_ENDIAN 0x01u
+#define CTL_MEM_APER_LONG_ENDIAN 0x02u
+/* ? 0x03u */
+
+/* Definitions for an ICS2595's programme word */
+#define ICS2595_CLOCK 0x000001f0ul
+#define ICS2595_FB_DIV 0x0001fe00ul /* Feedback divider */
+#define ICS2595_POST_DIV 0x000c0000ul /* Post-divider */
+#define ICS2595_STOP 0x00300000ul /* Stop bits */
+#define ICS2595_TOGGLE (ICS2595_POST_DIV | ICS2595_STOP)
+
+/* Definitions for internal PLL registers on a 264xT */
+#define PLL_MPLL_CNTL 0x00u
+#define MPLL_PC_GAIN 0x07u
+#define MPLL_VC_GAIN 0x18u
+#define MPLL_D_CYC 0x60u
+#define MPLL_RANGE 0x80u
+#define VPLL_CNTL 0x01u
+#define VPLL_PC_GAIN 0x07u
+#define VPLL_VC_GAIN 0x18u
+#define VPLL_D_CYC 0x60u
+#define VPLL_RANGE 0x80u
+#define PLL_REF_DIV 0x02u
+#define PLL_GEN_CNTL 0x03u
+#define PLL_OVERRIDE 0x01u
+#define PLL_SLEEP 0x01u /* GTPro */
+#define PLL_MCLK_RESET 0x02u
+#define PLL_OSC_EN 0x04u
+#define PLL_EXT_CLK_EN 0x08u
+#define PLL_MCLK_SRC_SEL 0x70u
+#define PLL_EXT_CLK_CNTL 0x80u /* CT/ET */
+#define PLL_DLL_PWDN 0x80u /* VTB/GTB/LT */
+#define PLL_MCLK_FB_DIV 0x04u
+#define PLL_VCLK_CNTL 0x05u
+#define PLL_VCLK_SRC_SEL 0x03u
+#define PLL_VCLK_RESET 0x04u
+#define PLL_VCLK_INVERT 0x08u
+#define PLL_ECP_DIV 0x30u /* VT/GT */
+#define PLL_ERATE_GT_XRATE 0x40u /* VT/GT */
+#define PLL_SCALER_LOCK_EN 0x80u /* VT/GT */
+#define PLL_VCLK_POST_DIV 0x06u
+#define PLL_VCLK0_POST_DIV 0x03u
+#define PLL_VCLK1_POST_DIV 0x0cu
+#define PLL_VCLK2_POST_DIV 0x30u
+#define PLL_VCLK3_POST_DIV 0xc0u
+#define PLL_VCLK0_FB_DIV 0x07u
+#define PLL_VCLK1_FB_DIV 0x08u
+#define PLL_VCLK2_FB_DIV 0x09u
+#define PLL_VCLK3_FB_DIV 0x0au
+#define PLL_XCLK_CNTL 0x0bu /* VT/GT */
+#define PLL_XCLK_MCLK_RATIO 0x03u
+#define PLL_XCLK_SRC_SEL 0x07u /* VTB/GTB/LT */
+#define PLL_MFB_TIMES_4_2B 0x08u
+#define PLL_VCLK0_XDIV 0x10u
+#define PLL_VCLK1_XDIV 0x20u
+#define PLL_VCLK2_XDIV 0x40u
+#define PLL_VCLK3_XDIV 0x80u
+#define PLL_FCP_CNTL 0x0cu /* VT/GT */
+#define PLL_FCP_POST_DIV 0x0fu
+#define PLL_FCP_SRC_SEL 0x70u
+#define PLL_DCLK_BY2_EN 0x80u
+#define PLL_DLL_CNTL 0x0cu /* VTB/GTB/LT */
+#define PLL_DLL_REF_SRC 0x03u
+#define PLL_DLL_FB_SRC 0x0cu
+#define PLL_DLL_GAIN 0x30u
+#define PLL_DLL_RESET 0x40u
+#define PLL_DLL_HCLK_OUT_EN 0x80u
+#define PLL_VFC_CNTL 0x0du /* VT/GT */
+#define PLL_DCLK_INVB 0x01u
+#define PLL_DCLKBY2_EN 0x02u
+#define PLL_VFC_2PHASE 0x04u
+#define PLL_VFC_DELAY 0x18u
+#define PLL_VFC_DCLKBY2_SHIFT 0x20u
+/* ? 0x40u */
+#define PLL_TST_SRC_SEL_BIT5 0x80u /* VTB/GTB/LT */
+#define PLL_TEST_CNTL 0x0eu
+#define PLL_TST_SRC_SEL 0x1fu
+#define PLL_TST_DIVIDERS 0x20u
+#define PLL_TST_MASK_READ 0x40u
+#define PLL_TST_ANALOG_MON_EN 0x80u
+#define PLL_TEST_COUNT 0x0fu
+#define PLL_LVDSPLL_CNTL0 0x10u /* LT */
+#define PLL_FPDI_NS_TIMING 0x01u
+#define PLL_CURR_LEVEL 0x0eu
+#define PLL_LVDS_TEST_MODE 0xf0u
+#define PLL_LVDSPLL_CNTL1 0x11u /* LT */
+#define PLL_LPPL_RANGE 0x01u
+#define PLL_LPLL_DUTY 0x06u
+#define PLL_LPLL_VC_GAIN 0x18u
+#define PLL_LPLL_CP_GAIN 0xe0u
+#define PLL_AGP1_CNTL 0x12u /* GTPro */
+#define PLL_AGP2_CNTL 0x13u /* GTPro */
+#define PLL_DLL2_CNTL 0x14u /* GTPro */
+#define PLL_SCLK_FB_DIV 0x15u /* GTPro */
+#define PLL_SPLL_CNTL1 0x16u /* GTPro */
+#define PLL_SPLL_CNTL2 0x17u /* GTPro */
+#define PLL_APLL_STRAPS 0x18u /* GTPro */
+#define PLL_EXT_VPLL_CNTL 0x19u /* GTPro */
+#define PLL_EXT_VPLL_REF_SRC 0x03u
+#define PLL_EXT_VPLL_EN 0x04u
+#define PLL_EXT_VPLL_VGA_EN 0x08u
+#define PLL_EXT_VPLL_INSYNC 0x10u
+/* ? 0x60u */
+#define PLL_EXT_V2PLL_EN 0x80u
+#define PLL_EXT_VPLL_REF_DIV 0x1au /* GTPro */
+#define PLL_EXT_VPLL_FB_DIV 0x1bu /* GTPro */
+#define PLL_EXT_VPLL_MSB 0x1cu /* GTPro */
+#define PLL_HTOTAL_CNTL 0x1du /* GTPro */
+#define PLL_BYTE_CLK_CNTL 0x1eu /* GTPro */
+#define PLL_TV_REF_DIV 0x1fu /* LTPro */
+#define PLL_TV_FB_DIV 0x20u /* LTPro */
+#define PLL_TV_CNTL 0x21u /* LTPro */
+#define PLL_TV_GEN_CNTL 0x22u /* LTPro */
+#define PLL_V2_CNTL 0x23u /* LTPro */
+#define PLL_V2_GEN_CNTL 0x24u /* LTPro */
+#define PLL_V2_REF_DIV 0x25u /* LTPro */
+#define PLL_V2_FB_DIV 0x26u /* LTPro */
+#define PLL_V2_MSB 0x27u /* LTPro */
+#define PLL_HTOTAL2_CNTL 0x28u /* LTPro */
+#define PLL_YCLK_CNTL 0x29u /* XC/XL */
+#define PM_DYN_CLK_CNTL 0x2au /* XC/XL */
+/* ? 0x2bu */
+/* ? 0x2cu */
+/* ? 0x2du */
+/* ? 0x2eu */
+/* ? 0x2fu */
+/* ? 0x30u */
+/* ? 0x31u */
+/* ? 0x32u */
+/* ? 0x33u */
+/* ? 0x34u */
+/* ? 0x35u */
+/* ? 0x36u */
+/* ? 0x37u */
+/* ? 0x38u */
+/* ? 0x39u */
+/* ? 0x3au */
+/* ? 0x3bu */
+/* ? 0x3cu */
+/* ? 0x3du */
+/* ? 0x3eu */
+/* ? 0x3fu */
+
+/* Definitions for an LTPro's 32-bit LCD registers */
+#define LCD_CONFIG_PANEL 0x00u /* See LT's CONFIG_PANEL (0x1d) */
+#define LCD_GEN_CNTL 0x01u /* See LT's LCD_GEN_CTRL (0x35) */
+#define LCD_DSTN_CONTROL 0x02u /* See LT's DSTN_CONTROL (0x1f) */
+#define LCD_HFB_PITCH_ADDR 0x03u /* See LT's HFB_PITCH_ADDR (0x2a) */
+#define LCD_HORZ_STRETCHING 0x04u /* See LT's HORZ_STRETCHING (0x32) */
+#define LCD_VERT_STRETCHING 0x05u /* See LT's VERT_STRETCHING (0x33) */
+#define LCD_EXT_VERT_STRETCH 0x06u
+#define VERT_STRETCH_RATIO3 0x000003fful
+#define FORCE_DAC_DATA 0x000000fful
+#define FORCE_DAC_DATA_SEL 0x00000300ul
+#define VERT_STRETCH_MODE 0x00000400ul
+#define VERT_PANEL_SIZE 0x003ff800ul
+#define AUTO_VERT_RATIO 0x00400000ul
+#define USE_AUTO_FP_POS 0x00800000ul
+#define USE_AUTO_LCD_VSYNC 0x01000000ul
+/* ? 0xfe000000ul */
+#define LCD_LT_GIO 0x07u /* See LT's LT_GIO (0x2f) */
+#define LCD_POWER_MANAGEMENT 0x08u /* See LT's POWER_MANAGEMENT (0x36) */
+#define LCD_ZVGPIO 0x09u
+#define LCD_ICON_CLR0 0x0au /* Mobility */
+#define LCD_ICON_CLR1 0x0bu /* Mobility */
+#define LCD_ICON_OFFSET 0x0cu /* Mobility */
+#define LCD_ICON_HORZ_VERT_POSN 0x0du /* Mobility */
+#define LCD_ICON_HORZ_VERT_OFF 0x0eu /* Mobility */
+#define LCD_ICON2_CLR0 0x0fu /* Mobility */
+#define LCD_ICON2_CLR1 0x10u /* Mobility */
+#define LCD_ICON2_OFFSET 0x11u /* Mobility */
+#define LCD_ICON2_HORZ_VERT_POSN 0x12u /* Mobility */
+#define LCD_ICON2_HORZ_VERT_OFF 0x13u /* Mobility */
+#define LCD_MISC_CNTL 0x14u /* XC/XL */
+#define BL_MOD_LEVEL 0x000000fful
+#define BIAS_MOD_LEVEL 0x0000ff00ul
+#define BLMOD_EN 0x00010000ul
+#define BIASMOD_EN 0x00020000ul
+/* ? 0x00040000ul */
+#define PWRSEQ_MODE 0x00080000ul
+#define APC_EN 0x00100000ul
+#define MONITOR_DET_EN 0x00200000ul
+#define FORCE_DAC_DATA_SEL_X 0x00c00000ul
+#define FORCE_DAC_DATA_X 0xff000000ul
+#define LCD_TMDS_CNTL 0x15u /* XC/XL */
+#define LCD_SCRATCH_PAD_4M 0x15u /* Mobility */
+#define LCD_TMDS_SYNC_CHAR_SETA 0x16u /* XC/XL */
+#define LCD_SCRATCH_PAD_5M 0x16u /* Mobility */
+#define LCD_TMDS_SYNC_CHAR_SETB 0x17u /* XC/XL */
+#define LCD_SCRATCH_PAD_6M 0x17u /* Mobility */
+#define LCD_TMDS_SRC 0x18u /* XC/XL */
+#define LCD_SCRATCH_PAD_7M 0x18u /* Mobility */
+#define LCD_PLTSTBLK_CNTL 0x19u /* XC/XL */
+#define LCD_SCRATCH_PAD_8M 0x19u /* Mobility */
+#define LCD_SYNC_GEN_CNTL 0x1au /* XC/XL */
+#define LCD_PATTERN_GEN_SEED 0x1bu /* XC/XL */
+#define LCD_APC_CNTL 0x1cu /* XC/XL */
+#define LCD_POWER_MANAGEMENT_2 0x1du /* XC/XL */
+#define LCD_XCLK_DISP_PM_EN 0x00000001ul
+#define LCD_XCLK_DISP2_PM_EN 0x00000002ul /* Mobility */
+#define LCD_XCLK_VID_PM_EN 0x00000004ul
+#define LCD_XCLK_SCL_PM_EN 0x00000008ul
+#define LCD_XCLK_GUI_PM_EN 0x00000010ul
+#define LCD_XCLK_SUB_PM_EN 0x00000020ul
+/* ? 0x000000c0ul */
+#define LCD_MCLK_PM_EN 0x00000100ul
+#define LCD_SS_EN 0x00000200ul
+#define LCD_BLON_DIGON_EN 0x00000400ul
+/* ? 0x00000800ul */
+#define LCD_PM_DYN_XCLK_SYNC 0x00003000ul
+#define LCD_SEL_W4MS 0x00004000ul
+/* ? 0x00008000ul */
+#define LCD_PM_DYN_XCLK_EN 0x00010000ul
+#define LCD_PM_XCLK_ALWAYS 0x00020000ul
+#define LCD_PM_DYN_XCLK_STATUS 0x00040000ul
+#define LCD_PCI_ACC_DIS 0x00080000ul
+#define LCD_PM_DYN_XCLK_DISP 0x00100000ul
+#define LCD_PM_DYN_XCLK_DISP2 0x00200000ul /* Mobility */
+#define LCD_PM_DYN_XCLK_VID 0x00400000ul
+#define LCD_PM_DYN_XCLK_HFB 0x00800000ul
+#define LCD_PM_DYN_XCLK_SCL 0x01000000ul
+#define LCD_PM_DYN_XCLK_SUB 0x02000000ul
+#define LCD_PM_DYN_XCLK_GUI 0x04000000ul
+#define LCD_PM_DYN_XCLK_HOST 0x08000000ul
+/* ? 0xf0000000ul */
+#define LCD_PRI_ERR_PATTERN 0x1eu /* XC/XL */
+#define LCD_CUR_ERR_PATTERN 0x1fu /* XC/XL */
+#define LCD_PLTSTBLK_RPT 0x20u /* XC/XL */
+#define LCD_SYNC_RPT 0x21u /* XC/XL */
+#define LCD_CRC_PATTERN_RPT 0x22u /* XC/XL */
+#define LCD_PL_TRANSMITTER_CNTL 0x23u /* XC/XL */
+#define LCD_PL_PLL_CNTL 0x24u /* XC/XL */
+#define LCD_ALPHA_BLENDING 0x25u /* Mobility */
+#define LCD_PORTRAIT_GEN_CNTL 0x26u /* Mobility */
+#define LCD_APC_CTRL_IO 0x27u /* Mobility */
+#define LCD_TEST_IO 0x28u /* XC/XL */
+/* ? 0x29u */
+#define LCD_DP1_MEM_ACCESS 0x2au /* XC/XL */
+#define LCD_DP0_MEM_ACCESS 0x2bu /* XC/XL */
+#define LCD_DP0_DEBUG_A 0x2cu /* XC/XL */
+#define LCD_DP0_DEBUG_B 0x2du /* XC/XL */
+#define LCD_DP1_DEBUG_A 0x2eu /* XC/XL */
+#define LCD_DP1_DEBUG_B 0x2fu /* XC/XL */
+#define LCD_DPCTRL_DEBUG_A 0x30u /* XC/XL */
+#define LCD_DPCTRL_DEBUG_B 0x31u /* XC/XL */
+#define LCD_MEMBLK_DEBUG 0x32u /* XC/XL */
+#define LCD_APC_LUT_AB 0x33u /* Mobility */
+#define LCD_SCRATCH_PAD_4X 0x33u /* XL/XC */
+#define LCD_APC_LUT_CD 0x34u /* Mobility */
+#define LCD_SCRATCH_PAD_5X 0x34u /* XL/XC */
+#define LCD_APC_LUT_EF 0x35u /* Mobility */
+#define LCD_SCRATCH_PAD_6X 0x35u /* XL/XC */
+#define LCD_APC_LUT_GH 0x36u /* Mobility */
+#define LCD_SCRATCH_PAD_7X 0x36u /* XL/XC */
+#define LCD_APC_LUT_IJ 0x37u /* Mobility */
+#define LCD_SCRATCH_PAD_8X 0x37u /* XL/XC */
+#define LCD_APC_LUT_KL 0x38u /* Mobility */
+#define LCD_APC_LUT_MN 0x39u /* Mobility */
+#define LCD_APC_LUT_OP 0x3au /* Mobility */
+/* ? 0x3bu */
+/* ? 0x3cu */
+/* ? 0x3du */
+/* ? 0x3eu */
+/* ? 0x3fu */
+
+/* Definitions for an LTPro's TV registers */
+/* ? 0x00u */
+/* ? 0x01u */
+/* ? 0x02u */
+/* ? 0x03u */
+/* ? 0x04u */
+/* ? 0x05u */
+/* ? 0x06u */
+/* ? 0x07u */
+/* ? 0x08u */
+/* ? 0x09u */
+/* ? 0x0au */
+/* ? 0x0bu */
+/* ? 0x0cu */
+/* ? 0x0du */
+/* ? 0x0eu */
+/* ? 0x0fu */
+#define TV_MASTER_CNTL 0x10u
+/* ? 0x11u */
+#define TV_RGB_CNTL 0x12u
+/* ? 0x13u */
+#define TV_SYNC_CNTL 0x14u
+/* ? 0x15u */
+/* ? 0x16u */
+/* ? 0x17u */
+/* ? 0x18u */
+/* ? 0x19u */
+/* ? 0x1au */
+/* ? 0x1bu */
+/* ? 0x1cu */
+/* ? 0x1du */
+/* ? 0x1eu */
+/* ? 0x1fu */
+#define TV_HTOTAL 0x20u
+#define TV_HDISP 0x21u
+#define TV_HSIZE 0x22u
+#define TV_HSTART 0x23u
+#define TV_HCOUNT 0x24u
+#define TV_VTOTAL 0x25u
+#define TV_VDISP 0x26u
+#define TV_VCOUNT 0x27u
+#define TV_FTOTAL 0x28u
+#define TV_FCOUNT 0x29u
+#define TV_FRESTART 0x2au
+#define TV_HRESTART 0x2bu
+#define TV_VRESTART 0x2cu
+/* ? 0x2du */
+/* ? 0x2eu */
+/* ? 0x2fu */
+/* ? 0x30u */
+/* ? 0x31u */
+/* ? 0x32u */
+/* ? 0x33u */
+/* ? 0x34u */
+/* ? 0x35u */
+/* ? 0x36u */
+/* ? 0x37u */
+/* ? 0x38u */
+/* ? 0x39u */
+/* ? 0x3au */
+/* ? 0x3bu */
+/* ? 0x3cu */
+/* ? 0x3du */
+/* ? 0x3eu */
+/* ? 0x3fu */
+/* ? 0x40u */
+/* ? 0x41u */
+/* ? 0x42u */
+/* ? 0x43u */
+/* ? 0x44u */
+/* ? 0x45u */
+/* ? 0x46u */
+/* ? 0x47u */
+/* ? 0x48u */
+/* ? 0x49u */
+/* ? 0x4au */
+/* ? 0x4bu */
+/* ? 0x4cu */
+/* ? 0x4du */
+/* ? 0x4eu */
+/* ? 0x4fu */
+/* ? 0x50u */
+/* ? 0x51u */
+/* ? 0x52u */
+/* ? 0x53u */
+/* ? 0x54u */
+/* ? 0x55u */
+/* ? 0x56u */
+/* ? 0x57u */
+/* ? 0x58u */
+/* ? 0x59u */
+/* ? 0x5au */
+/* ? 0x5bu */
+/* ? 0x5cu */
+/* ? 0x5du */
+/* ? 0x5eu */
+/* ? 0x5fu */
+#define TV_HOST_READ_DATA 0x60u
+#define TV_HOST_WRITE_DATA 0x61u
+#define TV_HOST_RD_WT_CNTL 0x62u
+/* ? 0x63u */
+/* ? 0x64u */
+/* ? 0x65u */
+/* ? 0x66u */
+/* ? 0x67u */
+/* ? 0x68u */
+/* ? 0x69u */
+/* ? 0x6au */
+/* ? 0x6bu */
+/* ? 0x6cu */
+/* ? 0x6du */
+/* ? 0x6eu */
+/* ? 0x6fu */
+#define TV_VSCALER_CNTL 0x70u
+#define TV_TIMING_CNTL 0x71u
+#define TV_GAMMA_CNTL 0x72u
+#define TV_Y_FALL_CNTL 0x73u
+#define TV_Y_RISE_CNTL 0x74u
+#define TV_Y_SAW_TOOTH_CNTL 0x75u
+/* ? 0x76u */
+/* ? 0x77u */
+/* ? 0x78u */
+/* ? 0x79u */
+/* ? 0x7au */
+/* ? 0x7bu */
+/* ? 0x7cu */
+/* ? 0x7du */
+/* ? 0x7eu */
+/* ? 0x7fu */
+#define TV_MODULATOR_CNTL1 0x80u
+#define TV_MODULATOR_CNTL2 0x81u
+/* ? 0x82u */
+/* ? 0x83u */
+/* ? 0x84u */
+/* ? 0x85u */
+/* ? 0x86u */
+/* ? 0x87u */
+/* ? 0x88u */
+/* ? 0x89u */
+/* ? 0x8au */
+/* ? 0x8bu */
+/* ? 0x8cu */
+/* ? 0x8du */
+/* ? 0x8eu */
+/* ? 0x8fu */
+#define TV_PRE_DAC_MUX_CNTL 0x90u
+/* ? 0x91u */
+/* ? 0x92u */
+/* ? 0x93u */
+/* ? 0x94u */
+/* ? 0x95u */
+/* ? 0x96u */
+/* ? 0x97u */
+/* ? 0x98u */
+/* ? 0x99u */
+/* ? 0x9au */
+/* ? 0x9bu */
+/* ? 0x9cu */
+/* ? 0x9du */
+/* ? 0x9eu */
+/* ? 0x9fu */
+#define TV_DAC_CNTL 0xa0u
+/* ? 0xa1u */
+/* ? 0xa2u */
+/* ? 0xa3u */
+/* ? 0xa4u */
+/* ? 0xa5u */
+/* ? 0xa6u */
+/* ? 0xa7u */
+/* ? 0xa8u */
+/* ? 0xa9u */
+/* ? 0xaau */
+/* ? 0xabu */
+/* ? 0xacu */
+/* ? 0xadu */
+/* ? 0xaeu */
+/* ? 0xafu */
+#define TV_CRC_CNTL 0xb0u
+#define TV_VIDEO_PORT_SIG 0xb1u
+/* ? 0xb2u */
+/* ? 0xb3u */
+/* ? 0xb4u */
+/* ? 0xb5u */
+/* ? 0xb6u */
+/* ? 0xb7u */
+#define TV_VBI_CC_CNTL 0xb8u
+#define TV_VBI_EDS_CNTL 0xb9u
+#define TV_VBI_20BIT_CNTL 0xbau
+/* ? 0xbbu */
+/* ? 0xbcu */
+#define TV_VBI_DTO_CNTL 0xbdu
+#define TV_VBI_LEVEL_CNTL 0xbeu
+/* ? 0xbfu */
+#define TV_UV_ADR 0xc0u
+#define TV_FIFO_TEST_CNTL 0xc1u
+/* ? 0xc2u */
+/* ? 0xc3u */
+/* ? 0xc4u */
+/* ? 0xc5u */
+/* ? 0xc6u */
+/* ? 0xc7u */
+/* ? 0xc8u */
+/* ? 0xc9u */
+/* ? 0xcau */
+/* ? 0xcbu */
+/* ? 0xccu */
+/* ? 0xcdu */
+/* ? 0xceu */
+/* ? 0xcfu */
+/* ? 0xd0u */
+/* ? 0xd1u */
+/* ? 0xd2u */
+/* ? 0xd3u */
+/* ? 0xd4u */
+/* ? 0xd5u */
+/* ? 0xd6u */
+/* ? 0xd7u */
+/* ? 0xd8u */
+/* ? 0xd9u */
+/* ? 0xdau */
+/* ? 0xdbu */
+/* ? 0xdcu */
+/* ? 0xddu */
+/* ? 0xdeu */
+/* ? 0xdfu */
+/* ? 0xe0u */
+/* ? 0xe1u */
+/* ? 0xe2u */
+/* ? 0xe3u */
+/* ? 0xe4u */
+/* ? 0xe5u */
+/* ? 0xe6u */
+/* ? 0xe7u */
+/* ? 0xe8u */
+/* ? 0xe9u */
+/* ? 0xeau */
+/* ? 0xebu */
+/* ? 0xecu */
+/* ? 0xedu */
+/* ? 0xeeu */
+/* ? 0xefu */
+/* ? 0xf0u */
+/* ? 0xf1u */
+/* ? 0xf2u */
+/* ? 0xf3u */
+/* ? 0xf4u */
+/* ? 0xf5u */
+/* ? 0xf6u */
+/* ? 0xf7u */
+/* ? 0xf8u */
+/* ? 0xf9u */
+/* ? 0xfau */
+/* ? 0xfbu */
+/* ? 0xfcu */
+/* ? 0xfdu */
+/* ? 0xfeu */
+/* ? 0xffu */
+
+/* Some ImpacTV definitions */
+#define IT_SDA_GET 0x40u
+#define IT_SDA_SET 0x20u
+#define IT_SDA_DIR 0x10u
+#define IT_SCL_GET 0x04u
+#define IT_SCL_SET 0x02u
+#define IT_SCL_DIR 0x01u
+
+#define IT_I2C_CNTL 0x0015u
+
+/* Miscellaneous */
+
+/* Current X, Y & Dest X, Y mask */
+#define COORD_MASK 0x07ffu
+
+/* Pixel widths */
+#define PIX_WIDTH_1BPP 0x00u
+#define PIX_WIDTH_4BPP 0x01u /* CRTC2: 8bpp */
+#define PIX_WIDTH_8BPP 0x02u /* CRTC2: Undefined */
+#define PIX_WIDTH_15BPP 0x03u
+#define PIX_WIDTH_16BPP 0x04u
+#define PIX_WIDTH_24BPP 0x05u
+#define PIX_WIDTH_32BPP 0x06u
+#define PIX_WIDTH_YUV422 0x07u /* CRTC2 only */
+
+/* Source definitions */
+#define SRC_BKGD 0x00u
+#define SRC_FRGD 0x01u
+#define SRC_HOST 0x02u
+#define SRC_BLIT 0x03u
+#define SRC_PATTERN 0x04u
+#define SRC_SCALER_3D 0x05u
+/* ? 0x06u */
+/* ? 0x07u */
+
+/* The Mixes */
+#define MIX_MASK 0x001fu
+
+#define MIX_NOT_DST 0x0000u
+#define MIX_0 0x0001u
+#define MIX_1 0x0002u
+#define MIX_DST 0x0003u
+#define MIX_NOT_SRC 0x0004u
+#define MIX_XOR 0x0005u
+#define MIX_XNOR 0x0006u
+#define MIX_SRC 0x0007u
+#define MIX_NAND 0x0008u
+#define MIX_NOT_SRC_OR_DST 0x0009u
+#define MIX_SRC_OR_NOT_DST 0x000au
+#define MIX_OR 0x000bu
+#define MIX_AND 0x000cu
+#define MIX_SRC_AND_NOT_DST 0x000du
+#define MIX_NOT_SRC_AND_DST 0x000eu
+#define MIX_NOR 0x000fu
+
+#define MIX_MIN 0x0010u
+#define MIX_DST_MINUS_SRC 0x0011u
+#define MIX_SRC_MINUS_DST 0x0012u
+#define MIX_PLUS 0x0013u
+#define MIX_MAX 0x0014u
+#define MIX_HALF__DST_MINUS_SRC 0x0015u
+#define MIX_HALF__SRC_MINUS_DST 0x0016u
+#define MIX_AVERAGE 0x0017u
+#define MIX_DST_MINUS_SRC_SAT 0x0018u
+#define MIX_SRC_MINUS_DST_SAT 0x001au
+#define MIX_HALF__DST_MINUS_SRC_SAT 0x001cu
+#define MIX_HALF__SRC_MINUS_DST_SAT 0x001eu
+#define MIX_AVERAGE_SAT 0x001fu
+#define MIX_FN_PAINT MIX_SRC
+
+#endif /* ___ATIREGS_H___ */
diff --git a/src/atirgb514.c b/src/atirgb514.c
new file mode 100644
index 0000000..bedb794
--- /dev/null
+++ b/src/atirgb514.c
@@ -0,0 +1,280 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atirgb514.c,v 1.4 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "aticrtc.h"
+#include "atimach64io.h"
+#include "atirgb514.h"
+
+/*
+ * ATIRGB514PreInit --
+ *
+ * This function fills in the IBM RGB 514 portion of an ATIHWRec that is common
+ * to all video modes generated by the server.
+ */
+void
+ATIRGB514PreInit
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ /* Get a work copy of IBM RGB 514 registers */
+ ATIRGB514Save(pATI, pATIHW);
+
+ /* Miscellaneous Clock Control */
+ pATIHW->ibmrgb514[0x0002U] = 0x01U;
+
+ /* Sync Control */
+ pATIHW->ibmrgb514[0x0003U] &= ~0x80U;
+
+ /* Horizontal Sync Control */
+ pATIHW->ibmrgb514[0x0004U] = 0x00U;
+
+ /* Power Management */
+ pATIHW->ibmrgb514[0x0005U] = 0x00U;
+
+ /* DAC Operation */
+ pATIHW->ibmrgb514[0x0006U] &= ~0x04U;
+
+ /* Palette Control */
+ pATIHW->ibmrgb514[0x0007U] = 0x00U;
+
+ /* PLL Control */
+ pATIHW->ibmrgb514[0x0010U] = 0x01U;
+
+ /* Cursor control */
+ pATIHW->ibmrgb514[0x0030U] &= ~0x03U; /* For now */
+
+ /* Border (i.e. overscan) */
+ pATIHW->ibmrgb514[0x0060U] = 0x00U;
+ pATIHW->ibmrgb514[0x0061U] = 0x00U;
+ pATIHW->ibmrgb514[0x0062U] = 0x00U;
+
+ /* Miscellaneous Control */
+ pATIHW->ibmrgb514[0x0070U] &= ~0x20U;
+ pATIHW->ibmrgb514[0x0071U] = 0x41U; /* See workaround in ATIRGB514Set() */
+
+#ifndef AVOID_CPIO
+
+ if (pATIHW->crtc == ATI_CRTC_VGA)
+ {
+ /* Pixel Format */
+ pATIHW->ibmrgb514[0x000AU] = 0x03U;
+
+ /* Miscellaneous Control */
+ pATIHW->ibmrgb514[0x0070U] |= 0x40U;
+
+ /* VRAM Mask */
+ pATIHW->ibmrgb514[0x0090U] = 0x03U;
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ /* Miscellaneous Control */
+ pATIHW->ibmrgb514[0x0070U] &= ~0x40U;
+
+ /* VRAM Mask */
+ pATIHW->ibmrgb514[0x0090U] = 0x00U;
+ pATIHW->ibmrgb514[0x0091U] = 0x00U;
+
+ /* Pixel Format */
+ switch (pATI->depth)
+ {
+ case 8:
+ pATIHW->ibmrgb514[0x000AU] = 0x03U;
+ pATIHW->ibmrgb514[0x000BU] = 0x00U;
+ break;
+
+ case 15:
+ pATIHW->ibmrgb514[0x000AU] = 0x04U;
+ pATIHW->ibmrgb514[0x000CU] = 0xC4U;
+ break;
+
+ case 16:
+ pATIHW->ibmrgb514[0x000AU] = 0x04U;
+ pATIHW->ibmrgb514[0x000CU] = 0xC6U;
+ break;
+
+ case 24:
+ if (pATI->bitsPerPixel == 24)
+ {
+ pATIHW->ibmrgb514[0x000AU] = 0x05U;
+ pATIHW->ibmrgb514[0x000DU] = 0x01U;
+ }
+ else
+ {
+ pATIHW->ibmrgb514[0x000AU] = 0x06U;
+ pATIHW->ibmrgb514[0x000EU] = 0x03U;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (pATI->rgbBits == 8)
+ pATIHW->ibmrgb514[0x0071U] |= 0x04U;
+}
+
+/*
+ * ATIRGB514Save --
+ *
+ * This function saves IBM RGB514 related data into an ATIHWRec.
+ */
+void
+ATIRGB514Save
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ CARD32 crtc_gen_cntl, dac_cntl;
+ CARD8 index_lo, index_hi, index_ctl;
+ int Index;
+
+ /* Temporarily switch to Mach64 CRTC */
+ crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
+
+ /* Temporarily switch to IBM RGB 514 registers */
+ dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
+ outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
+
+ index_lo = in8(M64_DAC_WRITE);
+ index_hi = in8(M64_DAC_DATA);
+ index_ctl = in8(M64_DAC_READ);
+
+ out8(M64_DAC_WRITE, 0x00U);
+ out8(M64_DAC_DATA, 0x00U);
+ out8(M64_DAC_READ, 0x01U); /* Auto-increment */
+
+ /* Save IBM RGB 514 registers */
+ for (Index = 0; Index < NumberOf(pATIHW->ibmrgb514); Index++)
+ {
+ /* Need to rewrite the index every so often... */
+ if ((Index == 0x0100) || (Index == 0x0500))
+ {
+ out8(M64_DAC_WRITE, 0);
+ out8(M64_DAC_DATA, Index >> 8);
+ }
+ pATIHW->ibmrgb514[Index] = in8(M64_DAC_MASK);
+ }
+
+ /* Restore registers */
+ out8(M64_DAC_WRITE, index_lo);
+ out8(M64_DAC_DATA, index_hi);
+ out8(M64_DAC_READ, index_ctl);
+ outr(DAC_CNTL, dac_cntl);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl);
+}
+
+/*
+ * ATIRGB514Calculate --
+ *
+ * This function fills in the IBM RGB 514 portion of an ATIHWRec that is
+ * specific to a display mode. pATIHW->ibmrgb514 has already been
+ * initialised by a previous call to ATIRGB514PreInit().
+ */
+void
+ATIRGB514Calculate
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
+ pATIHW->ibmrgb514[0x0006U] |= 0x08U;
+ else
+ pATIHW->ibmrgb514[0x0006U] &= ~0x08U;
+
+ if (pMode->Flags & V_INTERLACE)
+ pATIHW->ibmrgb514[0x0071U] |= 0x20U;
+ else
+ pATIHW->ibmrgb514[0x0071U] &= ~0x20U;
+}
+
+/*
+ * ATIRGB514Set --
+ *
+ * This function is called to set an IBM RGB514's registers.
+ */
+void
+ATIRGB514Set
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ CARD32 crtc_gen_cntl, dac_cntl;
+ CARD8 index_lo, index_hi, index_ctl;
+ int Index;
+
+ /* Temporarily switch to Mach64 CRTC */
+ crtc_gen_cntl = inr(CRTC_GEN_CNTL);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
+
+ /* Temporarily switch to IBM RGB 514 registers */
+ dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
+ outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
+
+ index_lo = in8(M64_DAC_WRITE);
+ index_hi = in8(M64_DAC_DATA);
+ index_ctl = in8(M64_DAC_READ);
+
+ out8(M64_DAC_WRITE, 0x00U);
+ out8(M64_DAC_DATA, 0x00U);
+ out8(M64_DAC_READ, 0x01U); /* Auto-increment */
+
+ /* Load IBM RGB 514 registers */
+ for (Index = 0; Index < NumberOf(pATIHW->ibmrgb514); Index++)
+ out8(M64_DAC_MASK, pATIHW->ibmrgb514[Index]);
+
+#ifndef AVOID_CPIO
+
+ /* Deal with documented anomaly */
+ if (pATIHW->crtc == ATI_CRTC_VGA)
+ {
+ /* Reset Miscellaneous Control 2 */
+ out8(M64_DAC_WRITE, 0x71U);
+ out8(M64_DAC_DATA, 0x00U);
+ out8(M64_DAC_MASK, pATIHW->ibmrgb514[0x0071U] & ~0x41U);
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Restore registers */
+ out8(M64_DAC_WRITE, index_lo);
+ out8(M64_DAC_DATA, index_hi);
+ out8(M64_DAC_READ, index_ctl);
+ outr(DAC_CNTL, dac_cntl);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ outr(CRTC_GEN_CNTL, crtc_gen_cntl);
+}
diff --git a/src/atirgb514.h b/src/atirgb514.h
new file mode 100644
index 0000000..71f44d2
--- /dev/null
+++ b/src/atirgb514.h
@@ -0,0 +1,38 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atirgb514.h,v 1.3 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIRGB514_H___
+#define ___ATIRGB514_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern void ATIRGB514PreInit FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIRGB514Save FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIRGB514Calculate FunctionPrototype((ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIRGB514Set FunctionPrototype((ATIPtr, ATIHWPtr));
+
+#endif /* ___ATIRGB514_H___ */
diff --git a/src/atiscreen.c b/src/atiscreen.c
new file mode 100644
index 0000000..59b04e0
--- /dev/null
+++ b/src/atiscreen.c
@@ -0,0 +1,345 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiscreen.c,v 1.29 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiaccel.h"
+#include "aticonsole.h"
+#include "aticursor.h"
+#include "atidac.h"
+#include "atidga.h"
+#include "atiscreen.h"
+#include "atistruct.h"
+#include "atixv.h"
+
+#include "shadowfb.h"
+#include "xf86cmap.h"
+
+#include "xf1bpp.h"
+#include "xf4bpp.h"
+
+#include "fb.h"
+
+#include "mibank.h"
+#include "micmap.h"
+#include "mipointer.h"
+
+/*
+ * ATIRefreshArea --
+ *
+ * This function is called by the shadow frame buffer code to refresh the
+ * hardware frame buffer.
+ */
+static void
+ATIRefreshArea
+(
+ ScrnInfoPtr pScreenInfo,
+ int nBox,
+ BoxPtr pBox
+)
+{
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ pointer pSrc, pDst;
+ int offset, w, h;
+
+ while (nBox-- > 0)
+ {
+ w = (pBox->x2 - pBox->x1) * pATI->FBBytesPerPixel;
+ h = pBox->y2 - pBox->y1;
+ offset =
+ (pBox->y1 * pATI->FBPitch) + (pBox->x1 * pATI->FBBytesPerPixel);
+ pSrc = (char *)pATI->pShadow + offset;
+ pDst = (char *)pATI->pMemory + offset;
+
+ while (h-- > 0)
+ {
+ (void)memcpy(pDst, pSrc, w);
+ pSrc = (char *)pSrc + pATI->FBPitch;
+ pDst = (char *)pDst + pATI->FBPitch;
+ }
+
+ pBox++;
+ }
+}
+
+/*
+ * ATIScreenInit --
+ *
+ * This function is called by DIX to initialise the screen.
+ */
+Bool
+ATIScreenInit
+(
+ int iScreen,
+ ScreenPtr pScreen,
+ int argc,
+ char **argv
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ pointer pFB;
+ int VisualMask;
+
+ /* Set video hardware state */
+ if (!ATIEnterGraphics(pScreen, pScreenInfo, pATI))
+ return FALSE;
+
+ /* Re-initialise mi's visual list */
+ miClearVisualTypes();
+
+ if ((pATI->depth > 8) && (pATI->DAC == ATI_DAC_INTERNAL))
+ VisualMask = TrueColorMask;
+ else
+ VisualMask = miGetDefaultVisualMask(pATI->depth);
+
+ if (!miSetVisualTypes(pATI->depth, VisualMask, pATI->rgbBits,
+ pScreenInfo->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths())
+ return FALSE;
+
+ pFB = pATI->pMemory;
+ if (pATI->OptionShadowFB)
+ {
+ pATI->FBBytesPerPixel = pATI->bitsPerPixel >> 3;
+ pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth);
+ if ((pATI->pShadow = xalloc(pATI->FBPitch * pScreenInfo->virtualY)))
+ pFB = pATI->pShadow;
+ else
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Insufficient virtual memory for shadow frame buffer.\n");
+ pATI->OptionShadowFB = FALSE;
+ }
+ }
+
+ /* Initialise framebuffer layer */
+ switch (pATI->bitsPerPixel)
+ {
+
+#ifndef AVOID_CPIO
+
+ case 1:
+ pATI->Closeable = xf1bppScreenInit(pScreen, pFB,
+ pScreenInfo->virtualX, pScreenInfo->virtualY,
+ pScreenInfo->xDpi, pScreenInfo->yDpi, pATI->displayWidth);
+ break;
+
+ case 4:
+ pATI->Closeable = xf4bppScreenInit(pScreen, pFB,
+ pScreenInfo->virtualX, pScreenInfo->virtualY,
+ pScreenInfo->xDpi, pScreenInfo->yDpi, pATI->displayWidth);
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ pATI->Closeable = fbScreenInit(pScreen, pFB,
+ pScreenInfo->virtualX, pScreenInfo->virtualY,
+ pScreenInfo->xDpi, pScreenInfo->yDpi, pATI->displayWidth,
+ pATI->bitsPerPixel);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (!pATI->Closeable)
+ return FALSE;
+
+ /* Fixup RGB ordering */
+ if (pATI->depth > 8)
+ {
+ VisualPtr pVisual = pScreen->visuals + pScreen->numVisuals;
+
+ while (--pVisual >= pScreen->visuals)
+ {
+ if ((pVisual->class | DynamicClass) != DirectColor)
+ continue;
+
+ pVisual->offsetRed = pScreenInfo->offset.red;
+ pVisual->offsetGreen = pScreenInfo->offset.green;
+ pVisual->offsetBlue = pScreenInfo->offset.blue;
+
+ pVisual->redMask = pScreenInfo->mask.red;
+ pVisual->greenMask = pScreenInfo->mask.green;
+ pVisual->blueMask = pScreenInfo->mask.blue;
+ }
+ }
+
+ /* If applicable, initialise RENDER extension */
+ if (pATI->bitsPerPixel > 4)
+ {
+ if (pATI->OptionShadowFB)
+ {
+ if (serverGeneration == 1)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "RENDER extension not supported with a shadowed"
+ " framebuffer.\n");
+ }
+
+#ifndef AVOID_CPIO
+
+ else if (pATI->BankInfo.BankSize)
+ {
+ if (serverGeneration == 1)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "RENDER extension not supported with a banked"
+ " framebuffer.\n");
+ }
+
+#endif /* AVOID_CPIO */
+
+ else if (!fbPictureInit(pScreen, NULL, 0) &&
+ (serverGeneration == 1))
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "RENDER extension initialisation failed.\n");
+ }
+
+ xf86SetBlackWhitePixels(pScreen);
+
+#ifndef AVOID_CPIO
+
+ /* Initialise banking if needed */
+ if (!miInitializeBanking(pScreen,
+ pScreenInfo->virtualX, pScreenInfo->virtualY,
+ pATI->displayWidth, &pATI->BankInfo))
+ return FALSE;
+
+#endif /* AVOID_CPIO */
+
+ /* Setup acceleration */
+ if (!ATIInitializeAcceleration(pScreen, pScreenInfo, pATI))
+ return FALSE;
+
+#ifndef AVOID_DGA
+
+ /* Initialise DGA support */
+ (void)ATIDGAInit(pScreenInfo, pScreen, pATI);
+
+#endif /* AVOID_DGA */
+
+ /* Initialise backing store */
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+
+ /* Initialise cursor */
+ if (!ATIInitializeCursor(pScreen, pATI))
+ return FALSE;
+
+ /* Create default colourmap */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+#ifdef AVOID_CPIO
+
+ if (!xf86HandleColormaps(pScreen, 256, pATI->rgbBits, ATILoadPalette, NULL,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_LOAD_EVEN_IF_OFFSCREEN))
+ return FALSE;
+
+#else /* AVOID_CPIO */
+
+ if (pATI->depth > 1)
+ if (!xf86HandleColormaps(pScreen, (pATI->depth == 4) ? 16 : 256,
+ pATI->rgbBits, ATILoadPalette, NULL,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_LOAD_EVEN_IF_OFFSCREEN))
+ return FALSE;
+
+#endif /* AVOID_CPIO */
+
+ /* Initialise shadow framebuffer */
+ if (pATI->OptionShadowFB &&
+ !ShadowFBInit(pScreen, ATIRefreshArea))
+ return FALSE;
+
+ /* Initialise DPMS support */
+ (void)xf86DPMSInit(pScreen, ATISetDPMSMode, 0);
+
+ /* Initialise XVideo support */
+ (void)ATIInitializeXVideo(pScreen, pScreenInfo, pATI);
+
+ /* Set pScreen->SaveScreen and wrap CloseScreen vector */
+ pScreen->SaveScreen = ATISaveScreen;
+ pATI->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = ATICloseScreen;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScreenInfo->scrnIndex, pScreenInfo->options);
+
+ return TRUE;
+}
+
+/*
+ * ATICloseScreen --
+ *
+ * This function is called by DIX to close the screen.
+ */
+Bool
+ATICloseScreen
+(
+ int iScreen,
+ ScreenPtr pScreen
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ Bool Closed = TRUE;
+
+ if (pATI->pXAAInfo)
+ {
+ XAADestroyInfoRec(pATI->pXAAInfo);
+ pATI->pXAAInfo = NULL;
+ }
+
+ if ((pScreen->CloseScreen = pATI->CloseScreen))
+ {
+ pATI->CloseScreen = NULL;
+ Closed = (*pScreen->CloseScreen)(iScreen, pScreen);
+ }
+
+ pATI->Closeable = FALSE;
+
+ if (pATI->pCursorInfo)
+ {
+ xf86DestroyCursorInfoRec(pATI->pCursorInfo);
+ pATI->pCursorInfo = NULL;
+ }
+
+ ATILeaveGraphics(pScreenInfo, pATI);
+
+ xfree(pATI->ExpansionBitmapScanlinePtr[1]);
+ pATI->ExpansionBitmapScanlinePtr[0] =
+ pATI->ExpansionBitmapScanlinePtr[1] = NULL;
+
+ xfree(pATI->pShadow);
+ pATI->pShadow = NULL;
+ pScreenInfo->pScreen = NULL;
+
+ return Closed;
+}
diff --git a/src/atiscreen.h b/src/atiscreen.h
new file mode 100644
index 0000000..7397042
--- /dev/null
+++ b/src/atiscreen.h
@@ -0,0 +1,34 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiscreen.h,v 1.6 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATISCREEN_H___
+#define ___ATISCREEN_H___ 1
+
+#include "atiproto.h"
+
+#include "screenint.h"
+
+extern Bool ATIScreenInit FunctionPrototype((int, ScreenPtr, int, char **));
+extern Bool ATICloseScreen FunctionPrototype((int, ScreenPtr));
+
+#endif /* ___ATISCREEN_H___ */
diff --git a/src/atistruct.h b/src/atistruct.h
new file mode 100644
index 0000000..641fe06
--- /dev/null
+++ b/src/atistruct.h
@@ -0,0 +1,421 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atistruct.h,v 1.37 2003/01/10 20:57:58 tsi Exp $ */
+/*
+ * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATISTRUCT_H___
+#define ___ATISTRUCT_H___ 1
+
+#include "atibank.h"
+#include "aticlock.h"
+#include "atiregs.h"
+
+#include "xaa.h"
+#include "xf86Cursor.h"
+#include "xf86Pci.h"
+#include "xf86Resources.h"
+
+#define CacheSlotOf(____Register) ((____Register) / UnitOf(DWORD_SELECT))
+
+/*
+ * This is probably as good a place as any to put this note, as it applies to
+ * the entire driver, but especially here. CARD8's are used rather than the
+ * appropriate enum types because the latter would nearly quadruple storage
+ * requirements (they are stored as int's). This reduces the usefulness of
+ * enum types to their ability to declare index values. I've also elected to
+ * forgo the strong typing capabilities of enum types. C is not terribly adept
+ * at strong typing anyway.
+ */
+
+/* A structure for local data related to video modes */
+typedef struct _ATIHWRec
+{
+ /* Clock number for mode */
+ CARD8 clock;
+
+ /* The CRTC used to drive the screen (VGA, 8514, Mach64) */
+ CARD8 crtc;
+
+ /* Colour lookup table */
+ CARD8 lut[256 * 3];
+
+#ifndef AVOID_CPIO
+
+ /* VGA registers */
+ CARD8 genmo, crt[25], seq[5], gra[9], attr[21];
+
+ /* VGA Wonder registers */
+ CARD8 a3, a6, a7, ab, ac, ad, ae,
+ b0, b1, b2, b3, b5, b6, b8, b9, ba, bd, be, bf;
+
+ /* Shadow VGA CRTC registers */
+ CARD8 shadow_vga[25];
+
+#endif /* AVOID_CPIO */
+
+ /* Generic DAC registers */
+ CARD8 dac_read, dac_write, dac_mask;
+
+ /* IBM RGB 514 registers */
+ CARD8 ibmrgb514[0x0092U]; /* All that's needed for now */
+
+ /* Mach64 PLL registers */
+ CARD8 pll_vclk_cntl, pll_vclk_post_div,
+ pll_vclk0_fb_div, pll_vclk1_fb_div,
+ pll_vclk2_fb_div, pll_vclk3_fb_div,
+ pll_xclk_cntl, pll_ext_vpll_cntl;
+
+ /* Mach64 CPIO registers */
+ CARD32 crtc_h_total_disp, crtc_h_sync_strt_wid,
+ crtc_v_total_disp, crtc_v_sync_strt_wid,
+ crtc_off_pitch, crtc_gen_cntl, dsp_config, dsp_on_off,
+ ovr_clr, ovr_wid_left_right, ovr_wid_top_bottom,
+ cur_clr0, cur_clr1, cur_offset,
+ cur_horz_vert_posn, cur_horz_vert_off,
+ clock_cntl, bus_cntl, mem_cntl, mem_vga_wp_sel, mem_vga_rp_sel,
+ dac_cntl, gen_test_cntl, config_cntl, mpp_config, mpp_strobe_seq,
+ tvo_cntl;
+
+ /* LCD registers */
+ CARD32 lcd_index, config_panel, lcd_gen_ctrl,
+ horz_stretching, vert_stretching, ext_vert_stretch;
+
+ /* Shadow Mach64 CRTC registers */
+ CARD32 shadow_h_total_disp, shadow_h_sync_strt_wid,
+ shadow_v_total_disp, shadow_v_sync_strt_wid;
+
+ /* Mach64 MMIO Block 0 registers and related subfields */
+ CARD32 dst_off_pitch;
+ CARD16 dst_x, dst_y, dst_height;
+ CARD32 dst_bres_err, dst_bres_inc, dst_bres_dec, dst_cntl;
+ CARD32 src_off_pitch;
+ CARD16 src_x, src_y, src_width1, src_height1,
+ src_x_start, src_y_start, src_width2, src_height2;
+ CARD32 src_cntl;
+ CARD32 host_cntl;
+ CARD32 pat_reg0, pat_reg1, pat_cntl;
+ CARD16 sc_left, sc_right, sc_top, sc_bottom;
+ CARD32 dp_bkgd_clr, dp_frgd_clr, dp_write_mask, dp_chain_mask,
+ dp_pix_width, dp_mix, dp_src;
+ CARD32 clr_cmp_clr, clr_cmp_msk, clr_cmp_cntl;
+ CARD32 context_mask, context_load_cntl;
+
+ /* Mach64 MMIO Block 1 registers */
+ CARD32 gui_cntl;
+
+ /* Clock map pointers */
+ const CARD8 *ClockMap, *ClockUnmap;
+
+ /* Clock programming data */
+ int FeedbackDivider, ReferenceDivider, PostDivider;
+
+#ifndef AVOID_CPIO
+
+ /* This is used by ATISwap() */
+ pointer frame_buffer;
+ ATIBankProcPtr SetBank;
+ unsigned int nBank, nPlane;
+
+#endif /* AVOID_CPIO */
+
+} ATIHWRec;
+
+/*
+ * This structure defines the driver's private area.
+ */
+typedef struct _ATIRec
+{
+ /*
+ * Definitions related to XF86Config "Chipset" specifications.
+ */
+ CARD8 Chipset;
+
+ /*
+ * Adapter-related definitions.
+ */
+ CARD8 Adapter;
+
+#ifndef AVOID_CPIO
+
+ CARD8 VGAAdapter;
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Chip-related definitions.
+ */
+ CARD32 config_chip_id;
+ CARD16 ChipType;
+ CARD8 Chip;
+ CARD8 ChipClass, ChipRevision, ChipRev, ChipVersion, ChipFoundry;
+
+#ifndef AVOID_CPIO
+
+ CARD8 Coprocessor, ChipHasSUBSYS_CNTL;
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Processor I/O decoding definitions.
+ */
+ CARD8 CPIODecoding;
+ IOADDRESS CPIOBase;
+
+#ifndef AVOID_CPIO
+
+ /*
+ * Processor I/O port definition for VGA.
+ */
+ IOADDRESS CPIO_VGABase;
+
+ /*
+ * Processor I/O port definitions for VGA Wonder.
+ */
+ IOADDRESS CPIO_VGAWonder;
+ CARD8 B2Reg; /* The B2 mirror */
+ CARD8 VGAOffset; /* Low index for CPIO_VGAWonder */
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * DAC-related definitions.
+ */
+
+#ifndef AVOID_CPIO
+
+ IOADDRESS CPIO_DAC_MASK, CPIO_DAC_DATA, CPIO_DAC_READ, CPIO_DAC_WRITE,
+ CPIO_DAC_WAIT;
+
+#endif /* AVOID_CPIO */
+
+ CARD16 DAC;
+ CARD8 rgbBits;
+
+ /*
+ * Definitions related to system bus interface.
+ */
+ pciVideoPtr PCIInfo;
+ CARD8 BusType;
+ CARD8 SharedAccelerator;
+
+#ifndef AVOID_CPIO
+
+ CARD8 SharedVGA;
+ resRange VGAWonderResources[2];
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Definitions related to video memory.
+ */
+ CARD8 MemoryType;
+ int VideoRAM;
+
+ /*
+ * BIOS-related definitions.
+ */
+ unsigned long BIOSBase;
+
+ /*
+ * Definitions related to video memory apertures.
+ */
+ pointer pMemory, pShadow;
+ unsigned long LinearBase;
+ int LinearSize, FBPitch, FBBytesPerPixel;
+
+#ifndef AVOID_CPIO
+
+ /*
+ * Banking interface.
+ */
+ miBankInfoRec BankInfo;
+ pointer pBank;
+ CARD8 UseSmallApertures;
+
+#endif /* AVOID_CPIO */
+
+ /*
+ * Definitions related to MMIO register apertures.
+ */
+ pointer pMMIO, pBlock[2];
+ unsigned long Block0Base, Block1Base;
+
+ /*
+ * XAA interface.
+ */
+ XAAInfoRecPtr pXAAInfo;
+ int nAvailableFIFOEntries, nFIFOEntries, nHostFIFOEntries;
+ CARD8 EngineIsBusy, EngineIsLocked, XModifier;
+ CARD32 dst_cntl; /* For SetupFor/Subsequent communication */
+ CARD32 sc_left_right, sc_top_bottom;
+ CARD16 sc_left, sc_right, sc_top, sc_bottom; /* Current scissors */
+ pointer pHOST_DATA; /* Current HOST_DATA_* transfer window address */
+ CARD32 *ExpansionBitmapScanlinePtr[2];
+ int ExpansionBitmapWidth;
+
+ /*
+ * Cursor-related definitions.
+ */
+ xf86CursorInfoPtr pCursorInfo;
+ pointer pCursorPage, pCursorImage;
+ unsigned long CursorBase;
+ CARD32 CursorOffset;
+ CARD16 CursorXOffset, CursorYOffset;
+ CARD8 Cursor;
+
+ /*
+ * MMIO cache.
+ */
+ CARD32 MMIOCache[CacheSlotOf(DWORD_SELECT) + 1];
+ CARD8 MMIOCached[(CacheSlotOf(DWORD_SELECT) + 8) >> 3];
+
+ /*
+ * Clock-related definitions.
+ */
+ int ClockNumberToProgramme, ReferenceNumerator, ReferenceDenominator;
+ int ProgrammableClock, maxClock;
+ ClockRec ClockDescriptor;
+ CARD16 BIOSClocks[16];
+ CARD8 Clock;
+
+ /*
+ * DSP register data.
+ */
+ int XCLKFeedbackDivider, XCLKReferenceDivider, XCLKPostDivider;
+ CARD16 XCLKMaxRASDelay, XCLKPageFaultDelay,
+ DisplayLoopLatency, DisplayFIFODepth;
+
+ /*
+ * LCD panel data.
+ */
+ int LCDPanelID, LCDClock, LCDHorizontal, LCDVertical;
+ int LCDHSyncStart, LCDHSyncWidth, LCDHBlankWidth;
+ int LCDVSyncStart, LCDVSyncWidth, LCDVBlankWidth;
+ int LCDVBlendFIFOSize;
+
+ /*
+ * Data used by ATIAdjustFrame().
+ */
+ int AdjustDepth, AdjustMaxX, AdjustMaxY;
+ unsigned long AdjustMask, AdjustMaxBase;
+
+ /*
+ * DGA and non-DGA common data.
+ */
+ DisplayModePtr currentMode;
+ CARD8 depth, bitsPerPixel;
+ short int displayWidth;
+ int pitchInc;
+ rgb weight;
+
+#ifndef AVOID_DGA
+
+ /*
+ * DGA-related data.
+ */
+ DGAModePtr pDGAMode;
+ DGAFunctionRec ATIDGAFunctions;
+ int nDGAMode;
+
+ /*
+ * XAAForceTransBlit alters the behavior of 'SetupForScreenToScreenCopy',
+ * such that ~0 is interpreted as a legitimate transparency key.
+ */
+ CARD8 XAAForceTransBlit;
+
+#endif /* AVOID_DGA */
+
+ /*
+ * Data saved by ATIUnlock() and restored by ATILock().
+ */
+ struct
+ {
+ /* Mach64 registers */
+ CARD32 crtc_int_cntl, crtc_gen_cntl, i2c_cntl_0, hw_debug,
+ scratch_reg3, bus_cntl, lcd_index, mem_cntl, i2c_cntl_1,
+ dac_cntl, gen_test_cntl, mpp_config, mpp_strobe_seq, tvo_cntl;
+
+#ifndef AVOID_CPIO
+
+ CARD32 config_cntl;
+
+ /* Mach8/Mach32 registers */
+ CARD16 clock_sel, misc_options, mem_bndry, mem_cfg;
+
+ /* VGA Wonder registers */
+ CARD8 a6, ab, b1, b4, b5, b6, b8, b9, be;
+
+ /* VGA registers */
+ CARD8 crt03, crt11;
+
+ /* VGA shadow registers */
+ CARD8 shadow_crt03, shadow_crt11;
+
+#endif /* AVOID_CPIO */
+
+ } LockData;
+
+ /* Mode data */
+ ATIHWRec OldHW, NewHW;
+ int MaximumInterlacedPitch;
+ Bool InterlacedSeen;
+
+ /*
+ * Resource Access Control entity index.
+ */
+ int iEntity;
+
+ /*
+ * Driver options.
+ */
+ CARD8 OptionAccel; /* Use hardware draw engine */
+ CARD8 OptionBlend; /* Force horizontal blending */
+ CARD8 OptionCRTDisplay; /* Display on both CRT and digital panel */
+ CARD8 OptionCSync; /* Use composite sync */
+ CARD8 OptionDevel; /* Intentionally undocumented */
+
+#ifndef AVOID_CPIO
+
+ CARD8 OptionLinear; /* Use linear fb aperture when available */
+
+#endif /* AVOID_CPIO */
+
+ CARD8 OptionMMIOCache; /* Cache MMIO writes */
+ CARD8 OptionPanelDisplay; /* Prefer CRT over digital panel */
+ CARD8 OptionProbeClocks; /* Force probe for fixed clocks */
+ CARD8 OptionShadowFB; /* Use shadow frame buffer */
+ CARD8 OptionSync; /* Temporary */
+
+ /*
+ * State flags.
+ */
+ CARD8 Unlocked, Mapped, Closeable;
+ CARD8 MMIOInLinear;
+
+ /*
+ * Wrapped functions.
+ */
+ CloseScreenProcPtr CloseScreen;
+} ATIRec;
+
+#define ATIPTR(_p) ((ATIPtr)((_p)->driverPrivate))
+
+#endif /* ___ATISTRUCT_H___ */
diff --git a/src/atiutil.c b/src/atiutil.c
new file mode 100644
index 0000000..e7bb412
--- /dev/null
+++ b/src/atiutil.c
@@ -0,0 +1,114 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiutil.c,v 1.8 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiutil.h"
+
+/*
+ * ATIReduceRatio --
+ *
+ * Reduce a fraction by factoring out the largest common divider of the
+ * fraction's numerator and denominator.
+ */
+void
+ATIReduceRatio
+(
+ int *Numerator,
+ int *Denominator
+)
+{
+ int Multiplier, Divider, Remainder;
+
+ Multiplier = *Numerator;
+ Divider = *Denominator;
+
+ while ((Remainder = Multiplier % Divider))
+ {
+ Multiplier = Divider;
+ Divider = Remainder;
+ }
+
+ *Numerator /= Divider;
+ *Denominator /= Divider;
+}
+
+/*
+ * ATIDivide --
+ *
+ * Using integer arithmetic and avoiding overflows, this function finds the
+ * rounded integer that best approximates
+ *
+ * Numerator Shift
+ * ----------- * 2
+ * Denominator
+ *
+ * using the specified rounding (floor (<0), nearest (=0) or ceiling (>0)).
+ */
+int
+ATIDivide
+(
+ int Numerator,
+ int Denominator,
+ int Shift,
+ const int RoundingKind
+)
+{
+ int Rounding = 0; /* Default to floor */
+
+#define MaxInt ((int)((unsigned int)(-1) >> 2))
+
+ ATIReduceRatio(&Numerator, &Denominator);
+
+ /* Deal with left shifts but try to keep the denominator even */
+ if (Denominator & 1)
+ {
+ if (Denominator <= MaxInt)
+ {
+ Denominator <<= 1;
+ Shift++;
+ }
+ }
+ else while ((Shift > 0) && !(Denominator & 3))
+ {
+ Denominator >>= 1;
+ Shift--;
+ }
+
+ /* Deal with right shifts */
+ while (Shift < 0)
+ {
+ if ((Numerator & 1) && (Denominator <= MaxInt))
+ Denominator <<= 1;
+ else
+ Numerator >>= 1;
+
+ Shift++;
+ }
+
+ if (!RoundingKind) /* Nearest */
+ Rounding = Denominator >> 1;
+ else if (RoundingKind > 0) /* Ceiling */
+ Rounding = Denominator - 1;
+
+ return ((Numerator / Denominator) << Shift) +
+ ((((Numerator % Denominator) << Shift) + Rounding) / Denominator);
+}
diff --git a/src/atiutil.h b/src/atiutil.h
new file mode 100644
index 0000000..f43295d
--- /dev/null
+++ b/src/atiutil.h
@@ -0,0 +1,70 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiutil.h,v 1.8 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIUTIL_H___
+#define ___ATIUTIL_H___ 1
+
+#include "atiproto.h"
+
+/*
+ * Prevent the C standard's insistence on unsigned long sizeof's from causing
+ * counter-intuitive results.
+ */
+#define SizeOf(_object) ((int)sizeof(_object))
+#define NumberOf(_what) (SizeOf(_what) / SizeOf(_what[0]))
+
+#define __ONE_MICROSECOND__ 100 /* This'll need calibration */
+
+#define ATIDelay(_microseconds) \
+ { \
+ unsigned int _i, _j; \
+ for (_i = 0; _i < _microseconds; _i++) \
+ for (_j = 0; _j < __ONE_MICROSECOND__; _j++) \
+ /* Nothing */; \
+ }
+
+/*
+ * Macros to get/set a contiguous bit field. Arguments should not be
+ * self-modifying.
+ */
+#define UnitOf(___Value) \
+ (((((___Value) ^ ((___Value) - 1)) + 1) >> 1) | \
+ ((((___Value) ^ ((___Value) - 1)) >> 1) + 1))
+
+#define GetBits(__Value, _Mask) (((__Value) & (_Mask)) / UnitOf(_Mask))
+#define SetBits(__Value, _Mask) (((__Value) * UnitOf(_Mask)) & (_Mask))
+
+#define MaxBits(__Mask) GetBits(__Mask, __Mask)
+
+#define _ByteMask(__Byte) ((CARD8)(-1) << (8 * (__Byte)))
+#define GetByte(_Value, _Byte) GetBits(_Value, _ByteMask(_Byte))
+#define SetByte(_Value, _Byte) SetBits(_Value, _ByteMask(_Byte))
+
+#define _WordMask(__Word) ((CARD16)(-1) << (16 * (__Word)))
+#define GetWord(_Value, _Word) GetBits(_Value, _WordMask(_Word))
+#define SetWord(_Value, _Word) SetBits(_Value, _WordMask(_Word))
+
+extern void ATIReduceRatio FunctionPrototype((int *, int *));
+extern int ATIDivide FunctionPrototype((int, int, int, const int));
+
+#endif /* ___ATIUTIL_H___ */
diff --git a/src/ativalid.c b/src/ativalid.c
new file mode 100644
index 0000000..adc8734
--- /dev/null
+++ b/src/ativalid.c
@@ -0,0 +1,235 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.c,v 1.15 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atiadapter.h"
+#include "atichip.h"
+#include "aticrtc.h"
+#include "atistruct.h"
+#include "ativalid.h"
+
+#include "xf86.h"
+
+/*
+ * ATIValidMode --
+ *
+ * This checks for hardware-related limits on mode timings.
+ */
+int
+ATIValidMode
+(
+ int iScreen,
+ DisplayModePtr pMode,
+ Bool Verbose,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ Bool InterlacedSeen;
+ int HBlankWidth, HAdjust, VScan, VInterlace;
+
+#ifndef AVOID_CPIO
+
+ int VDisplay, VTotal;
+
+#endif /* AVOID_CPIO */
+
+ if (flags & MODECHECK_FINAL)
+ {
+ /*
+ * This is the final check before the common layer accepts a mode.
+ * pScreenInfo->displayWidth is set to the proposed virtual pitch
+ * should the mode be accepted. The only check needed here is for
+ * 18800's and 28800's, which don't support interlaced modes if the
+ * pitch is over half the chipset's maximum pitch.
+ */
+ if (pATI->MaximumInterlacedPitch)
+ {
+ /*
+ * Ensure no interlaced modes have a scanline pitch larger than the
+ * limit.
+ */
+ if (pMode->Flags & V_INTERLACE)
+ InterlacedSeen = TRUE;
+ else
+ InterlacedSeen = pATI->InterlacedSeen;
+
+ if (InterlacedSeen &&
+ (pScreenInfo->displayWidth > pATI->MaximumInterlacedPitch))
+ return MODE_INTERLACE_WIDTH;
+
+ pATI->InterlacedSeen = InterlacedSeen;
+ }
+
+ return MODE_OK;
+ }
+
+ /*
+ * The following is done for every mode in the monitor section that
+ * survives the common layer's basic checks.
+ */
+ if (pMode->VScan <= 1)
+ VScan = 1;
+ else
+ VScan = pMode->VScan;
+
+ if (pMode->Flags & V_DBLSCAN)
+ VScan <<= 1;
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ {
+ if ((pMode->CrtcHDisplay > pATI->LCDHorizontal) ||
+ (pMode->CrtcVDisplay > pATI->LCDVertical))
+ return MODE_PANEL;
+
+ if (!pATI->OptionSync || (pMode->type & M_T_BUILTIN))
+ {
+ if ((pMode->HDisplay > pATI->LCDHorizontal) ||
+ (pMode->VDisplay > pATI->LCDVertical))
+ return MODE_PANEL;
+
+ return MODE_OK;
+ }
+
+ /*
+ * Adjust effective timings for monitor checks. Here the modeline
+ * clock is ignored. Horizontal timings are scaled by the stretch
+ * ratio used for the displayed area. The vertical porch is scaled by
+ * the native resolution's aspect ratio. This seems rather arbitrary,
+ * and it is, but it does make all applicable VESA modes sync on a
+ * panel after stretching. This has the unfortunate, but necessary,
+ * side-effect of changing the mode's horizontal sync and vertical
+ * refresh rates. With some exceptions, this tends to increase the
+ * mode's horizontal sync rate, and decrease its vertical refresh rate.
+ */
+ pMode->SynthClock = pATI->LCDClock;
+
+ pMode->CrtcHTotal = pMode->CrtcHBlankEnd =
+ ATIDivide(pMode->CrtcHTotal * pATI->LCDHorizontal,
+ pMode->CrtcHDisplay, -3, 1) << 3;
+ pMode->CrtcHSyncEnd =
+ ATIDivide(pMode->CrtcHSyncEnd * pATI->LCDHorizontal,
+ pMode->CrtcHDisplay, -3, 1) << 3;
+ pMode->CrtcHSyncStart =
+ ATIDivide(pMode->CrtcHSyncStart * pATI->LCDHorizontal,
+ pMode->CrtcHDisplay, -3, -1) << 3;
+ pMode->CrtcHDisplay = pMode->CrtcHBlankStart = pATI->LCDHorizontal;
+
+ pMode->CrtcVTotal = pMode->CrtcVBlankEnd =
+ ATIDivide((pMode->CrtcVTotal - pMode->CrtcVDisplay) *
+ pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
+ pATI->LCDVertical;
+ pMode->CrtcVSyncEnd =
+ ATIDivide((pMode->CrtcVSyncEnd - pMode->CrtcVDisplay) *
+ pATI->LCDVertical, pATI->LCDHorizontal, 0, 1) +
+ pATI->LCDVertical;
+ pMode->CrtcVSyncStart =
+ ATIDivide((pMode->CrtcVSyncStart - pMode->CrtcVDisplay) *
+ pATI->LCDVertical, pATI->LCDHorizontal, 0, -1) +
+ pATI->LCDVertical;
+ pMode->CrtcVDisplay = pMode->CrtcVBlankStart = pATI->LCDVertical;
+
+ /*
+ * The CRTC only stretches the mode's displayed area, not its porches.
+ * Reverse-engineer the mode's timings back into the user specified
+ * values so that the stretched mode is produced when the CRTC is
+ * eventually programmed. The reverse-engineered mode is then checked
+ * against CRTC limits below.
+ */
+ pMode->Clock = pATI->LCDClock;
+
+ HAdjust = pATI->LCDHorizontal - pMode->HDisplay;
+# define ATIReverseHorizontal(_x) \
+ (pMode->_x - HAdjust)
+
+ pMode->HSyncStart = ATIReverseHorizontal(CrtcHSyncStart);
+ pMode->HSyncEnd = ATIReverseHorizontal(CrtcHSyncEnd);
+ pMode->HTotal = ATIReverseHorizontal(CrtcHTotal);
+
+ VInterlace = GetBits(pMode->Flags, V_INTERLACE) + 1;
+# define ATIReverseVertical(_y) \
+ ((((pMode->_y - pATI->LCDVertical) * VInterlace) / VScan) + \
+ pMode->VDisplay)
+
+ pMode->VSyncStart = ATIReverseVertical(CrtcVSyncStart);
+ pMode->VSyncEnd = ATIReverseVertical(CrtcVSyncEnd);
+ pMode->VTotal = ATIReverseVertical(CrtcVTotal);
+
+# undef ATIReverseHorizontal
+# undef ATIReverseVertical
+ }
+
+ HBlankWidth = (pMode->HTotal >> 3) - (pMode->HDisplay >> 3);
+ if (!HBlankWidth)
+ return MODE_HBLANK_NARROW;
+
+ switch (pATI->NewHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ /* Prevent overscans */
+ if (HBlankWidth > 63)
+ return MODE_HBLANK_WIDE;
+
+ if (pMode->HDisplay > 2048)
+ return MODE_BAD_HVALUE;
+
+ if (VScan > 64)
+ return MODE_BAD_VSCAN;
+
+ VDisplay = pMode->VDisplay * VScan;
+ VTotal = pMode->VTotal * VScan;
+
+ if ((pMode->Flags & V_INTERLACE) && (pATI->Chip < ATI_CHIP_264CT))
+ {
+ VDisplay >>= 1;
+ VTotal >>= 1;
+ }
+
+ if ((VDisplay > 2048) || (VTotal > 2050))
+ return MODE_BAD_VVALUE;
+
+ if (pATI->Adapter != ATI_ADAPTER_VGA)
+ break;
+
+ if ((VDisplay > 1024) || (VTotal > 1025))
+ return MODE_BAD_VVALUE;
+
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ if (VScan > 2)
+ return MODE_NO_VSCAN;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return MODE_OK;
+}
diff --git a/src/ativalid.h b/src/ativalid.h
new file mode 100644
index 0000000..055ed50
--- /dev/null
+++ b/src/ativalid.h
@@ -0,0 +1,33 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.h,v 1.8 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIVALID_H___
+#define ___ATIVALID_H___ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern int ATIValidMode FunctionPrototype((int, DisplayModePtr, Bool, int));
+
+#endif /* ___ATIVALID_H___ */
diff --git a/src/ativersion.h b/src/ativersion.h
new file mode 100644
index 0000000..082cbb1
--- /dev/null
+++ b/src/ativersion.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h,v 1.58 2003/01/10 20:57:58 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIVERSION_H___
+#define ___ATIVERSION_H___ 1
+
+#undef ATI_NAME
+#undef ATI_DRIVER_NAME
+#undef ATI_VERSION_MAJOR
+#undef ATI_VERSION_MINOR
+#undef ATI_VERSION_PATCH
+#undef ATI_VERSION_CURRENT
+#undef ATI_VERSION_EVALUATE
+#undef ATI_VERSION_STRINGIFY
+#undef ATI_VERSION_NAME
+
+#define ATI_NAME "ATI"
+#define ATI_DRIVER_NAME "ati"
+
+#define ATI_VERSION_MAJOR 6
+#define ATI_VERSION_MINOR 4
+#define ATI_VERSION_PATCH 18
+
+#ifndef ATI_VERSION_EXTRA
+#define ATI_VERSION_EXTRA ""
+#endif
+
+#define ATI_VERSION_CURRENT \
+ ((ATI_VERSION_MAJOR << 20) | (ATI_VERSION_MINOR << 10) | ATI_VERSION_PATCH)
+
+#define ATI_VERSION_EVALUATE(__x) #__x
+#define ATI_VERSION_STRINGIFY(_x) ATI_VERSION_EVALUATE(_x)
+#define ATI_VERSION_NAME \
+ ATI_VERSION_STRINGIFY(ATI_VERSION_MAJOR) "." \
+ ATI_VERSION_STRINGIFY(ATI_VERSION_MINOR) "." \
+ ATI_VERSION_STRINGIFY(ATI_VERSION_PATCH) ATI_VERSION_EXTRA
+
+#endif /* ___ATIVERSION_H___ */
diff --git a/src/ativga.c b/src/ativga.c
new file mode 100644
index 0000000..9a732a3
--- /dev/null
+++ b/src/ativga.c
@@ -0,0 +1,532 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativga.c,v 1.19 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atichip.h"
+#include "atimono.h"
+#include "atistruct.h"
+#include "ativga.h"
+#include "ativgaio.h"
+
+#ifndef DPMS_SERVER
+# define DPMS_SERVER
+#endif
+#include "extensions/dpms.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIVGAPreInit --
+ *
+ * This function is called to set up VGA-related data that is common to all
+ * video modes generated by the driver.
+ */
+void
+ATIVGAPreInit
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index;
+
+ /* Initialise sequencer register values */
+ pATIHW->seq[0] = 0x03U;
+ if (pATI->depth == 1)
+ pATIHW->seq[2] = 0x01U << BIT_PLANE;
+ else
+ pATIHW->seq[2] = 0x0FU;
+ if (pATI->depth <= 4)
+ pATIHW->seq[4] = 0x06U;
+ else if (pATI->Adapter == ATI_ADAPTER_VGA)
+ pATIHW->seq[4] = 0x0EU;
+ else
+ pATIHW->seq[4] = 0x0AU;
+
+ /* Initialise CRTC register values */
+ if ((pATI->depth >= 8) &&
+ ((pATI->Chip >= ATI_CHIP_264CT) ||
+ (pATI->CPIO_VGAWonder &&
+ (pATI->Chip <= ATI_CHIP_18800_1) &&
+ (pATI->VideoRAM == 256))))
+ pATIHW->crt[19] = pATI->displayWidth >> 3;
+ else
+ pATIHW->crt[19] = pATI->displayWidth >> 4;
+ if ((pATI->depth >= 8) && (pATI->Adapter == ATI_ADAPTER_VGA))
+ pATIHW->crt[23] = 0xC3U;
+ else
+ pATIHW->crt[23] = 0xE3U;
+ pATIHW->crt[24] = 0xFFU;
+
+ /* Initialise attribute controller register values */
+ if (pATI->depth == 1)
+ {
+ Bool FlipPixels = xf86GetFlipPixels();
+
+ for (Index = 0; Index < 16; Index++)
+ if (((Index & (0x01U << BIT_PLANE)) != 0) != FlipPixels)
+ pATIHW->attr[Index] = MONO_WHITE;
+ else
+ pATIHW->attr[Index] = MONO_BLACK;
+ pATIHW->attr[16] = 0x01U;
+ pATIHW->attr[17] = MONO_OVERSCAN;
+ }
+ else
+ {
+ for (Index = 0; Index < 16; Index++)
+ pATIHW->attr[Index] = Index;
+ if (pATI->depth <= 4)
+ pATIHW->attr[16] = 0x81U;
+ else if (pATI->Adapter == ATI_ADAPTER_VGA)
+ pATIHW->attr[16] = 0x41U;
+ else
+ pATIHW->attr[16] = 0x01U;
+ pATIHW->attr[17] = 0xFFU;
+ }
+ pATIHW->attr[18] = 0x0FU;
+
+ /* Initialise graphics controller register values */
+ if (pATI->depth == 1)
+ pATIHW->gra[4] = BIT_PLANE;
+ else if (pATI->depth <= 4)
+ pATIHW->gra[5] = 0x02U;
+ else if (pATI->Chip >= ATI_CHIP_264CT)
+ pATIHW->gra[5] = 0x40U;
+ if (pATI->UseSmallApertures && (pATI->Chip >= ATI_CHIP_264CT) &&
+ ((pATI->Chip >= ATI_CHIP_264VT) || !pATI->LinearBase))
+ pATIHW->gra[6] = 0x01U; /* 128kB aperture */
+ else
+ pATIHW->gra[6] = 0x05U; /* 64kB aperture */
+ pATIHW->gra[7] = 0x0FU;
+ pATIHW->gra[8] = 0xFFU;
+}
+
+/*
+ * ATIVGASave --
+ *
+ * This function is called to save the VGA portion of the current video state.
+ */
+void
+ATIVGASave
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index;
+
+ /* Save miscellaneous output register */
+ pATIHW->genmo = inb(R_GENMO);
+ ATISetVGAIOBase(pATI, pATIHW->genmo);
+
+ /* Save sequencer registers */
+ for (Index = 0; Index < NumberOf(pATIHW->seq); Index++)
+ pATIHW->seq[Index] = GetReg(SEQX, Index);
+
+ /* Save CRTC registers */
+ for (Index = 0; Index < NumberOf(pATIHW->crt); Index++)
+ pATIHW->crt[Index] = GetReg(CRTX(pATI->CPIO_VGABase), Index);
+
+ /* Save attribute controller registers */
+ for (Index = 0; Index < NumberOf(pATIHW->attr); Index++)
+ {
+ (void)inb(GENS1(pATI->CPIO_VGABase)); /* Reset flip-flop */
+ pATIHW->attr[Index] = GetReg(ATTRX, Index);
+ }
+
+ /* Save graphics controller registers */
+ for (Index = 0; Index < NumberOf(pATIHW->gra); Index++)
+ pATIHW->gra[Index] = GetReg(GRAX, Index);
+}
+
+/*
+ * ATIVGACalculate --
+ *
+ * This function fills in the VGA portion of an ATIHWRec.
+ */
+void
+ATIVGACalculate
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ int Index, VDisplay;
+
+ /* If not already done, adjust horizontal timings */
+ if (!pMode->CrtcHAdjusted)
+ {
+ pMode->CrtcHAdjusted = TRUE;
+ pMode->CrtcHDisplay = (pMode->HDisplay >> 3) - 1;
+ pMode->CrtcHBlankStart = (pMode->HDisplay >> 3);
+ if ((pATI->Chip == ATI_CHIP_18800_1) ||
+ (pATI->Chip >= ATI_CHIP_264CT))
+ pMode->CrtcHBlankStart--;
+ pMode->CrtcHSyncStart = pMode->HSyncStart >> 3;
+ pMode->CrtcHSyncEnd = pMode->HSyncEnd >> 3;
+ pMode->CrtcHBlankEnd = (pMode->HTotal >> 3) - 1;
+ pMode->CrtcHTotal = (pMode->HTotal >> 3) - 5;
+ pMode->CrtcHSkew = pMode->HSkew;
+
+ /* Check sync pulse width */
+ Index = pMode->CrtcHSyncEnd - pMode->CrtcHSyncStart - 0x1F;
+ if (Index > 0)
+ {
+ pMode->CrtcHSyncStart += Index / 2;
+ pMode->CrtcHSyncEnd = pMode->CrtcHSyncStart + 0x1F;
+ }
+
+ /* Check blank pulse width */
+ Index = pMode->CrtcHBlankEnd - pMode->CrtcHBlankStart - 0x3F;
+ if (Index > 0)
+ {
+ if ((pMode->CrtcHBlankEnd - Index) > pMode->CrtcHSyncEnd)
+ {
+ pMode->CrtcHBlankStart += Index / 2;
+ if (pMode->CrtcHBlankStart >= pMode->CrtcHSyncStart)
+ pMode->CrtcHBlankStart = pMode->CrtcHSyncStart - 1;
+ pMode->CrtcHBlankEnd = pMode->CrtcHBlankStart + 0x3F;
+ }
+ else
+ {
+ Index -= 0x40;
+ if (Index > 0)
+ {
+ pMode->CrtcHBlankStart += Index / 2;
+ if (pMode->CrtcHBlankStart >= pMode->CrtcHSyncStart)
+ pMode->CrtcHBlankStart = pMode->CrtcHSyncStart - 1;
+ pMode->CrtcHBlankEnd = pMode->CrtcHBlankStart + 0x7F;
+ }
+ }
+ }
+ }
+
+ /*
+ * Because of the use of CRTC[23] bit 0x04's for vertical doubling, it is
+ * necessary to always re-adjust vertical timings here.
+ */
+ pMode->CrtcVDisplay = pMode->VDisplay;
+ pMode->CrtcVBlankStart = pMode->VDisplay;
+ pMode->CrtcVSyncStart = pMode->VSyncStart;
+ pMode->CrtcVSyncEnd = pMode->VSyncEnd;
+ pMode->CrtcVBlankEnd = pMode->VTotal;
+ pMode->CrtcVTotal = pMode->VTotal;
+
+ /* Adjust for doublescanned modes */
+ if (pMode->Flags & V_DBLSCAN)
+ {
+ pMode->CrtcVDisplay <<= 1;
+ pMode->CrtcVBlankStart <<= 1;
+ pMode->CrtcVSyncStart <<= 1;
+ pMode->CrtcVSyncEnd <<= 1;
+ pMode->CrtcVBlankEnd <<= 1;
+ pMode->CrtcVTotal <<= 1;
+ }
+
+ /* Adjust for multiscanned modes */
+ if (pMode->VScan > 1)
+ {
+ pMode->CrtcVDisplay *= pMode->VScan;
+ pMode->CrtcVBlankStart *= pMode->VScan;
+ pMode->CrtcVSyncStart *= pMode->VScan;
+ pMode->CrtcVSyncEnd *= pMode->VScan;
+ pMode->CrtcVBlankEnd *= pMode->VScan;
+ pMode->CrtcVTotal *= pMode->VScan;
+ }
+
+ /* Set up miscellaneous output register value */
+ pATIHW->genmo = 0x23U;
+ if ((pMode->Flags & (V_PHSYNC | V_NHSYNC)) &&
+ (pMode->Flags & (V_PVSYNC | V_NVSYNC)))
+ {
+ if (pMode->Flags & V_NHSYNC)
+ pATIHW->genmo |= 0x40U;
+ if (pMode->Flags & V_NVSYNC)
+ pATIHW->genmo |= 0x80U;
+ }
+ else
+ {
+ pMode->Flags &= ~(V_PHSYNC | V_NHSYNC | V_PVSYNC | V_NVSYNC);
+
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ VDisplay = pATI->LCDVertical;
+ else
+ VDisplay = pMode->CrtcVDisplay;
+
+ if (VDisplay < 400)
+ {
+ pMode->Flags |= V_PHSYNC | V_NVSYNC;
+ pATIHW->genmo |= 0x80U;
+ }
+ else if (VDisplay < 480)
+ {
+ pMode->Flags |= V_NHSYNC | V_PVSYNC;
+ pATIHW->genmo |= 0x40U;
+ }
+ else if (VDisplay < 768)
+ {
+ pMode->Flags |= V_NHSYNC | V_NVSYNC;
+ pATIHW->genmo |= 0xC0U;
+ }
+ else
+ {
+ pMode->Flags |= V_PHSYNC | V_PVSYNC;
+ }
+ }
+
+ /* Adjust for interlaced modes */
+ if ((pMode->Flags & V_INTERLACE) && (pATI->Chip < ATI_CHIP_264CT))
+ {
+ pMode->CrtcVDisplay >>= 1;
+ pMode->CrtcVBlankStart >>= 1;
+ pMode->CrtcVSyncStart >>= 1;
+ pMode->CrtcVSyncEnd >>= 1;
+ pMode->CrtcVBlankEnd >>= 1;
+ pMode->CrtcVTotal >>= 1;
+ }
+
+ if (pMode->CrtcVTotal > 1024)
+ {
+ pATIHW->crt[23] |= 0x04U;
+ pMode->CrtcVDisplay >>= 1;
+ pMode->CrtcVBlankStart >>= 1;
+ pMode->CrtcVSyncStart >>= 1;
+ pMode->CrtcVSyncEnd >>= 1;
+ pMode->CrtcVBlankEnd >>= 1;
+ pMode->CrtcVTotal >>= 1;
+ }
+ else
+ pATIHW->crt[23] &= ~0x04U;
+
+ pMode->CrtcVDisplay--;
+ if (pATI->Chip == ATI_CHIP_18800)
+ pMode->CrtcVBlankStart++;
+ else
+ pMode->CrtcVBlankStart--;
+ pMode->CrtcVBlankEnd--;
+ if (pATI->Chip < ATI_CHIP_264CT)
+ pMode->CrtcVBlankEnd--;
+ pMode->CrtcVTotal -= 2;
+ pMode->CrtcVAdjusted = TRUE; /* Redundant */
+
+ /* Check sync pulse width */
+ Index = pMode->CrtcVSyncEnd - pMode->CrtcVSyncStart - 0x0F;
+ if (Index > 0)
+ {
+ pMode->CrtcVSyncStart += Index / 2;
+ pMode->CrtcVSyncEnd = pMode->CrtcVSyncStart + 0x0F;
+ }
+
+ /* Check blank pulse width */
+ Index = pMode->CrtcVBlankEnd - pMode->CrtcVBlankStart - 0x00FF;
+ if (Index > 0)
+ {
+ if ((pMode->CrtcVBlankEnd - Index) > pMode->CrtcVSyncEnd)
+ {
+ pMode->CrtcVBlankStart += Index / 2;
+ if (pMode->CrtcVBlankStart >= pMode->CrtcVSyncStart)
+ pMode->CrtcVBlankStart = pMode->CrtcVSyncStart - 1;
+ pMode->CrtcVBlankEnd = pMode->CrtcVBlankStart + 0x00FF;
+ }
+ else
+ {
+ Index -= 0x0100;
+ if (Index > 0)
+ {
+ pMode->CrtcVBlankStart += Index / 2;
+ if (pMode->CrtcVBlankStart >= pMode->CrtcVSyncStart)
+ pMode->CrtcVBlankStart = pMode->CrtcVSyncStart - 1;
+ pMode->CrtcVBlankEnd = pMode->CrtcVBlankStart + 0x01FF;
+ }
+ }
+ }
+
+ /* Set up sequencer register values */
+ if (pMode->Flags & V_CLKDIV2)
+ pATIHW->seq[1] = 0x09U;
+ else
+ pATIHW->seq[1] = 0x01U;
+
+ /* Set up CRTC register values */
+ pATIHW->crt[0] = pMode->CrtcHTotal;
+ pATIHW->crt[1] = pMode->CrtcHDisplay;
+ pATIHW->crt[2] = pMode->CrtcHBlankStart;
+ pATIHW->crt[3] = (pMode->CrtcHBlankEnd & 0x1FU) | 0x80U;
+ Index = ((pMode->CrtcHSkew << 2) + 0x10U) & ~0x1FU;
+ if (Index < 0x0080)
+ pATIHW->crt[3] |= Index;
+ pATIHW->crt[4] = pMode->CrtcHSyncStart;
+ pATIHW->crt[5] = ((pMode->CrtcHBlankEnd & 0x20U) << 2) |
+ ((pMode->CrtcHSyncEnd & 0x1FU) );
+ pATIHW->crt[6] = pMode->CrtcVTotal & 0xFFU;
+ pATIHW->crt[7] = ((pMode->CrtcVTotal & 0x0100U) >> 8) |
+ ((pMode->CrtcVDisplay & 0x0100U) >> 7) |
+ ((pMode->CrtcVSyncStart & 0x0100U) >> 6) |
+ ((pMode->CrtcVBlankStart & 0x0100U) >> 5) |
+ 0x10U |
+ ((pMode->CrtcVTotal & 0x0200U) >> 4) |
+ ((pMode->CrtcVDisplay & 0x0200U) >> 3) |
+ ((pMode->CrtcVSyncStart & 0x0200U) >> 2);
+ pATIHW->crt[9] = ((pMode->CrtcVBlankStart & 0x0200U) >> 4) | 0x40U;
+ /*
+ * Doublescanned modes are missing the top scanline. Convert
+ * doublescanning to multiscanning, using the doublescan bit only as a last
+ * resort.
+ */
+ if ((Index = pMode->VScan) <= 0)
+ Index = 1;
+ if (pMode->Flags & V_DBLSCAN)
+ Index <<= 1;
+ Index--;
+ pATIHW->crt[9] |= (Index & 0x1FU) | ((Index & 0x20U) << 2);
+ pATIHW->crt[16] = pMode->CrtcVSyncStart & 0xFFU;
+ pATIHW->crt[17] = (pMode->CrtcVSyncEnd & 0x0FU) | 0x20U;
+ pATIHW->crt[18] = pMode->CrtcVDisplay & 0xFFU;
+ pATIHW->crt[21] = pMode->CrtcVBlankStart & 0xFFU;
+ pATIHW->crt[22] = pMode->CrtcVBlankEnd & 0xFFU;
+}
+
+/*
+ * ATIVGASet --
+ *
+ * This function is called to load the VGA portion of a video state.
+ */
+void
+ATIVGASet
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ int Index;
+
+ /* Set VGA I/O base */
+ ATISetVGAIOBase(pATI, pATIHW->genmo);
+
+ /* Load miscellaneous output register */
+ outb(GENMO, pATIHW->genmo);
+
+ /* Load sequencer in reverse index order; this also ends its reset */
+ for (Index = NumberOf(pATIHW->seq); --Index >= 0; )
+ PutReg(SEQX, Index, pATIHW->seq[Index]);
+
+ /* Load CRTC registers */
+ for (Index = 0; Index < NumberOf(pATIHW->crt); Index++)
+ PutReg(CRTX(pATI->CPIO_VGABase), Index, pATIHW->crt[Index]);
+
+ /* Load attribute controller registers */
+ for (Index = 0; Index < NumberOf(pATIHW->attr); Index++)
+ {
+ (void)inb(GENS1(pATI->CPIO_VGABase)); /* Reset flip-flop & delay */
+ outb(ATTRX, Index);
+ outb(ATTRX, pATIHW->attr[Index]);
+ }
+
+ /* Load graphics controller registers */
+ for (Index = 0; Index < NumberOf(pATIHW->gra); Index++)
+ PutReg(GRAX, Index, pATIHW->gra[Index]);
+}
+
+/*
+ * ATIVGASaveScreen --
+ *
+ * This function blanks or unblanks a VGA screen.
+ */
+void
+ATIVGASaveScreen
+(
+ ATIPtr pATI,
+ int Mode
+)
+{
+ (void)inb(GENS1(pATI->CPIO_VGABase)); /* Reset flip-flop */
+
+ switch (Mode)
+ {
+ case SCREEN_SAVER_OFF:
+ case SCREEN_SAVER_FORCER:
+ outb(ATTRX, 0x20U); /* Turn PAS on */
+ break;
+
+ case SCREEN_SAVER_ON:
+ case SCREEN_SAVER_CYCLE:
+ outb(ATTRX, 0x00U); /* Turn PAS off */
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * ATIVGASetDPMSMode --
+ *
+ * This function sets a VGA's VESA Display Power Management Signaling mode.
+ */
+void
+ATIVGASetDPMSMode
+(
+ ATIPtr pATI,
+ int DPMSMode
+)
+{
+ CARD8 seq1, crt17;
+
+ switch (DPMSMode)
+ {
+ case DPMSModeOn: /* HSync on, VSync on */
+ seq1 = 0x00U;
+ crt17 = 0x80U;
+ break;
+
+ case DPMSModeStandby: /* HSync off, VSync on -- unsupported */
+ seq1 = 0x20U;
+ crt17 = 0x80U;
+ break;
+
+ case DPMSModeSuspend: /* HSync on, VSync off -- unsupported */
+ seq1 = 0x20U;
+ crt17 = 0x80U;
+ break;
+
+ case DPMSModeOff: /* HSync off, VSync off */
+ seq1 = 0x20U;
+ crt17 = 0x00U;
+ break;
+
+ default: /* Muffle compiler */
+ return;
+ }
+
+ PutReg(SEQX, 0x00U, 0x01U); /* Start synchonous reset */
+ seq1 |= GetReg(SEQX, 0x01U) & ~0x20U;
+ PutReg(SEQX, 0x01U, seq1);
+ crt17 |= GetReg(CRTX(pATI->CPIO_VGABase), 0x17U) & ~0x80U;
+ usleep(10000);
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x17U, crt17);
+ PutReg(SEQX, 0x01U, 0x03U); /* End synchonous reset */
+}
+
+#endif /* AVOID_CPIO */
diff --git a/src/ativga.h b/src/ativga.h
new file mode 100644
index 0000000..ff65b35
--- /dev/null
+++ b/src/ativga.h
@@ -0,0 +1,45 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativga.h,v 1.10 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIVGA_H___
+#define ___ATIVGA_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+#ifndef AVOID_CPIO
+
+extern void ATIVGAPreInit FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIVGASave FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIVGACalculate FunctionPrototype((ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIVGASet FunctionPrototype((ATIPtr, ATIHWPtr));
+
+extern void ATIVGASaveScreen FunctionPrototype((ATIPtr, int));
+extern void ATIVGASetDPMSMode FunctionPrototype((ATIPtr, int));
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIVGA_H___ */
diff --git a/src/ativgaio.c b/src/ativgaio.c
new file mode 100644
index 0000000..def54e2
--- /dev/null
+++ b/src/ativgaio.c
@@ -0,0 +1,46 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativgaio.c,v 1.4 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atistruct.h"
+#include "ativgaio.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATISetVGAIOBase --
+ *
+ * This sets vgaIOBase according to the value of the passed value of the
+ * miscellaneous output register.
+ */
+void
+ATISetVGAIOBase
+(
+ ATIPtr pATI,
+ const CARD8 misc
+)
+{
+ pATI->CPIO_VGABase = (misc & 0x01U) ? ColourIOBase : MonochromeIOBase;
+}
+
+#endif /* AVOID_CPIO */
diff --git a/src/ativgaio.h b/src/ativgaio.h
new file mode 100644
index 0000000..e08ecff
--- /dev/null
+++ b/src/ativgaio.h
@@ -0,0 +1,56 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativgaio.h,v 1.5 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIVGAIO_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error missing #include "ati.h" before #include "ativgaio.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIVGAIO_H___ 1
+
+#include "atiio.h"
+#include "atipriv.h"
+#include "atiproto.h"
+
+#ifndef AVOID_CPIO
+
+extern void ATISetVGAIOBase FunctionPrototype((ATIPtr, const CARD8));
+
+/* Odds and ends to ease reading and writting of indexed registers */
+#define GetReg(_Register, _Index) \
+ ( \
+ outb(_Register, _Index), \
+ inb((_Register) + 1) \
+ )
+#define PutReg(_Register, _Index, _Value) \
+ do \
+ { \
+ outb(_Register, _Index); \
+ outb((_Register) + 1, _Value); \
+ } while (0)
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIVGAIO_H___ */
diff --git a/src/atividmem.c b/src/atividmem.c
new file mode 100644
index 0000000..32ea23f
--- /dev/null
+++ b/src/atividmem.c
@@ -0,0 +1,381 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atividmem.c,v 1.14 2003/01/01 19:16:34 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atiadapter.h"
+#include "atistruct.h"
+#include "atividmem.h"
+
+/* Memory types for 68800's and 88800GX's */
+const char *ATIMemoryTypeNames_Mach[] =
+{
+ "DRAM (256Kx4)",
+ "VRAM (256Kx4, x8, x16)",
+ "VRAM (256Kx16 with short shift register)",
+ "DRAM (256Kx16)",
+ "Graphics DRAM (256Kx16)",
+ "Enhanced VRAM (256Kx4, x8, x16)",
+ "Enhanced VRAM (256Kx16 with short shift register)",
+ "Unknown video memory type"
+};
+
+/* Memory types for 88800CX's */
+const char *ATIMemoryTypeNames_88800CX[] =
+{
+ "DRAM (256Kx4, x8, x16)",
+ "EDO DRAM (256Kx4, x8, x16)",
+ "Unknown video memory type",
+ "DRAM (256Kx16 with assymetric RAS/CAS)",
+ "Unknown video memory type",
+ "Unknown video memory type",
+ "Unknown video memory type",
+ "Unknown video memory type"
+};
+
+/* Memory types for 264xT's */
+const char *ATIMemoryTypeNames_264xT[] =
+{
+ "Disabled video memory",
+ "DRAM",
+ "EDO DRAM",
+ "Pseudo-EDO DRAM",
+ "SDRAM (1:1)",
+ "SGRAM (1:1)",
+ "SGRAM (2:1) 32-bit",
+ "Unknown video memory type"
+};
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIUnmapVGA --
+ *
+ * Unmap VGA aperture.
+ */
+static void
+ATIUnmapVGA
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ if (!pATI->pBank)
+ return;
+
+ xf86UnMapVidMem(iScreen, pATI->pBank, 0x00010000U);
+
+ pATI->pBank = pATI->BankInfo.pBankA = pATI->BankInfo.pBankB = NULL;
+}
+
+#endif /* AVOID_CPIO */
+
+/*
+ * ATIUnmapLinear --
+ *
+ * Unmap linear aperture.
+ */
+static void
+ATIUnmapLinear
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+
+#ifdef AVOID_CPIO
+
+ if (!pATI->pMemory)
+ return;
+
+#else /* AVOID_CPIO */
+
+ if (pATI->pMemory != pATI->pBank)
+
+#endif /* AVOID_CPIO */
+
+ {
+ xf86UnMapVidMem(iScreen, pATI->pMemory, pATI->LinearSize);
+ }
+
+ pATI->pMemory = NULL;
+}
+
+/*
+ * ATIUnmapMMIO --
+ *
+ * Unmap MMIO registers.
+ */
+static void
+ATIUnmapMMIO
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ if (pATI->pMMIO)
+ xf86UnMapVidMem(iScreen, pATI->pMMIO, getpagesize());
+
+ pATI->pMMIO = pATI->pBlock[0] = pATI->pBlock[1] = NULL;
+}
+
+/*
+ * ATIUnmapCursor --
+ *
+ * Unmap hardware cursor image area.
+ */
+static void
+ATIUnmapCursor
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ if (pATI->pCursorPage)
+ xf86UnMapVidMem(iScreen, pATI->pCursorPage, getpagesize());
+
+ pATI->pCursorPage = pATI->pCursorImage = NULL;
+}
+
+/*
+ * ATIMapApertures --
+ *
+ * This function maps all apertures used by the driver.
+ */
+Bool
+ATIMapApertures
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ pciVideoPtr pVideo;
+ PCITAG Tag;
+ unsigned long PageSize;
+
+ if (pATI->Mapped)
+ return TRUE;
+
+#ifndef AVOID_CPIO
+
+ if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
+
+#endif /* AVOID_CPIO */
+
+ {
+ if (!pATI->LinearBase && !pATI->Block0Base)
+ return FALSE;
+ }
+
+ PageSize = getpagesize();
+
+ if ((pVideo = pATI->PCIInfo))
+ Tag = ((pciConfigPtr)(pVideo->thisCard))->tag;
+ else
+ Tag = 0;
+
+#ifndef AVOID_CPIO
+
+ /* Map VGA aperture */
+ if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
+ {
+ /*
+ * No relocation, resizing, caching or write-combining of this
+ * aperture is supported. Hence, the hard-coded values here...
+ */
+ if (pVideo)
+ pATI->pBank = xf86MapPciMem(iScreen, VIDMEM_MMIO,
+ Tag, 0x000A0000U, 0x00010000U);
+ else
+ pATI->pBank = xf86MapVidMem(iScreen, VIDMEM_MMIO,
+ 0x000A0000U, 0x00010000U);
+
+ if (!pATI->pBank)
+ return FALSE;
+
+ pATI->pMemory =
+ pATI->BankInfo.pBankA =
+ pATI->BankInfo.pBankB = pATI->pBank;
+
+ pATI->Mapped = TRUE;
+ }
+
+#endif /* AVOID_CPIO */
+
+ /* Map linear aperture */
+ if (pATI->LinearBase)
+ {
+ if (pVideo)
+ pATI->pMemory = xf86MapPciMem(iScreen, VIDMEM_FRAMEBUFFER,
+ Tag, pATI->LinearBase, pATI->LinearSize);
+ else
+ pATI->pMemory = xf86MapVidMem(iScreen, VIDMEM_FRAMEBUFFER,
+ pATI->LinearBase, pATI->LinearSize);
+
+ if (!pATI->pMemory)
+ {
+
+#ifndef AVOID_CPIO
+
+ ATIUnmapVGA(iScreen, pATI);
+
+#endif /* AVOID_CPIO */
+
+ pATI->Mapped = FALSE;
+ return FALSE;
+ }
+
+ pATI->Mapped = TRUE;
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+
+ if ((pATI->CursorBase >= pATI->LinearBase) &&
+ ((pATI->CursorOffset + 0x00000400UL) <= (CARD32)pATI->LinearSize))
+ pATI->pCursorImage = (char *)pATI->pMemory + pATI->CursorOffset;
+
+#endif /* X_BYTE_ORDER */
+
+ }
+
+ /* Map MMIO aperture */
+ if (pATI->Block0Base)
+ {
+ unsigned long MMIOBase = pATI->Block0Base & ~(PageSize - 1);
+
+ if (pVideo)
+ pATI->pMMIO = xf86MapPciMem(iScreen, VIDMEM_MMIO,
+ Tag, MMIOBase, PageSize);
+ else
+ pATI->pMMIO = xf86MapVidMem(iScreen, VIDMEM_MMIO,
+ MMIOBase, PageSize);
+
+ if (!pATI->pMMIO)
+ {
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+
+ ATIUnmapCursor(iScreen, pATI);
+
+#endif /* X_BYTE_ORDER */
+
+ ATIUnmapLinear(iScreen, pATI);
+
+#ifndef AVOID_CPIO
+
+ ATIUnmapVGA(iScreen, pATI);
+
+#endif /* AVOID_CPIO */
+
+ pATI->Mapped = FALSE;
+ return FALSE;
+ }
+
+ pATI->Mapped = TRUE;
+
+ pATI->pBlock[0] = (char *)pATI->pMMIO +
+ (pATI->Block0Base - MMIOBase);
+
+ if (pATI->Block1Base)
+ pATI->pBlock[1] = (char *)pATI->pBlock[0] - 0x00000400U;
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+
+ if (!pATI->pCursorImage)
+
+#endif /* X_BYTE_ORDER */
+
+ {
+ if ((pATI->CursorBase >= MMIOBase) &&
+ ((pATI->CursorBase + 0x00000400UL) <= (MMIOBase + PageSize)))
+ pATI->pCursorImage = (char *)pATI->pMMIO +
+ (pATI->CursorBase - MMIOBase);
+ }
+ }
+
+ /* Map hardware cursor image area */
+ if (pATI->CursorBase && !pATI->pCursorImage)
+ {
+ unsigned long CursorBase = pATI->CursorBase & ~(PageSize - 1);
+
+ if (pVideo)
+ pATI->pCursorPage = xf86MapPciMem(iScreen, VIDMEM_FRAMEBUFFER,
+ Tag, CursorBase, PageSize);
+ else
+ pATI->pCursorPage = xf86MapVidMem(iScreen, VIDMEM_FRAMEBUFFER,
+ CursorBase, PageSize);
+
+ if (!pATI->pCursorPage)
+ {
+ ATIUnmapCursor(iScreen, pATI);
+ ATIUnmapMMIO(iScreen, pATI);
+ ATIUnmapLinear(iScreen, pATI);
+
+#ifndef AVOID_CPIO
+
+ ATIUnmapVGA(iScreen, pATI);
+
+#endif /* AVOID_CPIO */
+
+ pATI->Mapped = FALSE;
+ return FALSE;
+ }
+
+ pATI->pCursorImage = (char *)pATI->pCursorPage +
+ (pATI->CursorBase - CursorBase);
+ }
+
+ return TRUE;
+}
+
+/*
+ * ATIUnmapApertures --
+ *
+ * This function unmaps all apertures used by the driver.
+ */
+void
+ATIUnmapApertures
+(
+ int iScreen,
+ ATIPtr pATI
+)
+{
+ if (!pATI->Mapped)
+ return;
+ pATI->Mapped = FALSE;
+
+ /* Unmap hardware cursor image area */
+ ATIUnmapCursor(iScreen, pATI);
+
+ /* Unmap MMIO area */
+ ATIUnmapMMIO(iScreen, pATI);
+
+ /* Unmap linear aperture */
+ ATIUnmapLinear(iScreen, pATI);
+
+#ifndef AVOID_CPIO
+
+ /* Unmap VGA aperture */
+ ATIUnmapVGA(iScreen, pATI);
+
+#endif /* AVOID_CPIO */
+
+}
diff --git a/src/atividmem.h b/src/atividmem.h
new file mode 100644
index 0000000..7e4c26c
--- /dev/null
+++ b/src/atividmem.h
@@ -0,0 +1,75 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atividmem.h,v 1.9 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIVIDMEM_H___
+#define ___ATIVIDMEM_H___ 1
+
+#include "atiproto.h"
+#include "atipriv.h"
+
+/* Memory types for 68800's and 88800GX's */
+typedef enum
+{
+ MEM_MACH_DRAMx4,
+ MEM_MACH_VRAM,
+ MEM_MACH_VRAMssr,
+ MEM_MACH_DRAMx16,
+ MEM_MACH_GDRAM,
+ MEM_MACH_EVRAM,
+ MEM_MACH_EVRAMssr,
+ MEM_MACH_TYPE_7
+} ATIMachMemoryType;
+extern const char *ATIMemoryTypeNames_Mach[];
+
+/* Memory types for 88800CX's */
+typedef enum
+{
+ MEM_CX_DRAM,
+ MEM_CX_EDO,
+ MEM_CX_TYPE_2,
+ MEM_CX_DRAM_A,
+ MEM_CX_TYPE_4,
+ MEM_CX_TYPE_5,
+ MEM_CX_TYPE_6,
+ MEM_CX_TYPE_7
+} ATICXMemoryType;
+extern const char *ATIMemoryTypeNames_88800CX[];
+
+/* Memory types for 264xT's */
+typedef enum
+{
+ MEM_264_NONE,
+ MEM_264_DRAM,
+ MEM_264_EDO,
+ MEM_264_PSEUDO_EDO,
+ MEM_264_SDRAM,
+ MEM_264_SGRAM,
+ MEM_264_SGRAM32,
+ MEM_264_TYPE_7
+} ATI264MemoryType;
+extern const char *ATIMemoryTypeNames_264xT[];
+
+extern Bool ATIMapApertures FunctionPrototype((int, ATIPtr));
+extern void ATIUnmapApertures FunctionPrototype((int, ATIPtr));
+
+#endif /* ___ATIVIDMEM_H___ */
diff --git a/src/atiwonder.c b/src/atiwonder.c
new file mode 100644
index 0000000..404aeaf
--- /dev/null
+++ b/src/atiwonder.c
@@ -0,0 +1,303 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiwonder.c,v 1.14 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * The ATI x8800 chips use special registers for their extended VGA features.
+ * These registers are accessible through an index I/O port and a data I/O
+ * port. BIOS initialisation stores the index port number in the Graphics
+ * register bank (0x03CE), indices 0x50 and 0x51. Unfortunately, for all but
+ * the 18800-x series of adapters, these registers are write-only (a.k.a. black
+ * holes). On all but 88800's, the index port number can be found in the short
+ * integer at offset 0x10 in the BIOS. For 88800's, this driver will use
+ * 0x01CE or 0x03CE as the index port number, depending on the I/O port
+ * decoding used. The data port number is one more than the index port number
+ * (i.e. 0x01CF). These ports differ slightly in their I/O behaviour from the
+ * normal VGA ones:
+ *
+ * write: outw(0x01CE, (data << 8) | index); (16-bit, not used)
+ * outb(0x01CE, index); outb(0x01CF, data); (8-bit)
+ * read: outb(0x01CE, index); data = inb(0x01CF);
+ *
+ * Two consecutive byte-writes to the data port will not work. Furthermore an
+ * index written to 0x01CE is usable only once. Note also that the setting of
+ * ATI extended registers (especially those with clock selection bits) should
+ * be bracketed by a sequencer reset.
+ *
+ * The number of these extended VGA registers varies by chipset. The 18800
+ * series have 16, the 28800 series have 32, while 68800's and 88800's have 64.
+ * The last 16 on each have almost identical definitions. Thus, the BIOS sets
+ * up an indexing scheme whereby the last 16 extended VGA registers are
+ * accessed at indices 0xB0 through 0xBF on all chipsets.
+ */
+
+#include "ati.h"
+#include "atichip.h"
+#include "atiwonder.h"
+#include "atiwonderio.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIVGAWonderPreInit --
+ *
+ * This function is called to initialise the VGA Wonder part of an ATIHWRec
+ * that is common to all modes generated by the driver.
+ */
+void
+ATIVGAWonderPreInit
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ pATIHW->b3 = ATIGetExtReg(0xB3U) & 0x20U;
+ if (pATI->depth <= 4)
+ pATIHW->b6 = 0x40U;
+ else
+ pATIHW->b6 = 0x04U;
+ if (pATI->Chip <= ATI_CHIP_18800)
+ pATIHW->ba = 0x08U;
+ else if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ if (pATI->VideoRAM > 256)
+ pATIHW->b6 |= 0x01U;
+ pATIHW->bf = ATIGetExtReg(0xBFU) & 0x5FU;
+ pATIHW->a3 = ATIGetExtReg(0xA3U) & 0x67U;
+ pATIHW->ab = ATIGetExtReg(0xABU) & 0xE7U;
+ pATIHW->ae = ATIGetExtReg(0xAEU) & 0xE0U;
+ }
+}
+
+/*
+ * ATIVGAWonderSave --
+ *
+ * This function is called to save the VGA Wonder portion of the current video
+ * state.
+ */
+void
+ATIVGAWonderSave
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ pATIHW->b0 = ATIGetExtReg(0xB0U);
+ pATIHW->b1 = ATIGetExtReg(0xB1U);
+ pATIHW->b2 = ATIGetExtReg(0xB2U);
+ pATIHW->b3 = ATIGetExtReg(0xB3U);
+ pATIHW->b5 = ATIGetExtReg(0xB5U);
+ pATIHW->b6 = ATIGetExtReg(0xB6U);
+ pATIHW->b8 = ATIGetExtReg(0xB8U);
+ pATIHW->b9 = ATIGetExtReg(0xB9U);
+ pATIHW->ba = ATIGetExtReg(0xBAU);
+ pATIHW->bd = ATIGetExtReg(0xBDU);
+ if (pATI->Chip > ATI_CHIP_18800)
+ {
+ pATIHW->be = ATIGetExtReg(0xBEU);
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ pATIHW->bf = ATIGetExtReg(0xBFU);
+ pATIHW->a3 = ATIGetExtReg(0xA3U);
+ pATIHW->a6 = ATIGetExtReg(0xA6U);
+ pATIHW->a7 = ATIGetExtReg(0xA7U);
+ pATIHW->ab = ATIGetExtReg(0xABU);
+ pATIHW->ac = ATIGetExtReg(0xACU);
+ pATIHW->ad = ATIGetExtReg(0xADU);
+ pATIHW->ae = ATIGetExtReg(0xAEU);
+ }
+ }
+}
+
+/*
+ * ATIVGAWonderCalculate --
+ *
+ * This function fills in the VGA Wonder portion of an ATIHWRec structure
+ * occurrence.
+ */
+void
+ATIVGAWonderCalculate
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW,
+ DisplayModePtr pMode
+)
+{
+ /* Set up the default horizontal display enable skew */
+ if ((pATI->Chip >= ATI_CHIP_28800_2) && (pATI->Chip <= ATI_CHIP_28800_6) &&
+ !(pMode->Flags & V_HSKEW))
+ {
+ /*
+ * Modes using the higher clock frequencies need a non-zero Display
+ * Enable Skew. The following number has been empirically determined
+ * to be somewhere between 4.2 and 4.7 MHz.
+ */
+# define DisplayEnableSkewThreshold 4500
+
+ /* Set a reasonable default Display Enable Skew */
+ pMode->HSkew = pMode->CrtcHSkew =
+ ATIDivide(pMode->SynthClock, DisplayEnableSkewThreshold, 0, 0);
+ }
+ pMode->Flags |= V_HSKEW;
+
+ /*
+ * Fill in mode-specific VGA Wonder data.
+ */
+ pATIHW->b0 = 0x00U;
+ if (pATI->depth >= 8)
+ pATIHW->b0 = 0x20U;
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ if (pATI->VideoRAM > 512)
+ pATIHW->b0 |= 0x08U;
+ else if (pATI->VideoRAM > 256)
+ pATIHW->b0 |= 0x10U;
+ }
+ else if (pATI->depth <= 4)
+ {
+ if (pATI->VideoRAM > 256)
+ pATIHW->b0 |= 0x08U;
+ }
+ else
+ {
+ if (pATI->VideoRAM > 256)
+ pATIHW->b0 |= 0x18U;
+ else
+ pATIHW->b0 |= 0x06U;
+ }
+ pATIHW->b1 = ATIGetExtReg(0xB1U) & 0x04U;
+ /*
+ * Setting the following bit causes hangs on return to text mode from
+ * packed modes on 18800-1's. The hang occurs because the adapter's I/O
+ * response is completely disabled when the register is rewritten. The
+ * adapter can then only be re-enabled with a powerdown. The bit, when on,
+ * blanks out the overscan.
+ */
+ if ((pATI->Chip == ATI_CHIP_18800_1) && (pATI->depth >= 8))
+ pATIHW->b5 = 0x00U;
+ else
+ pATIHW->b5 = 0x01U;
+ pATIHW->b8 = ATIGetExtReg(0xB8U) & 0xC0U;
+ pATIHW->b9 = ATIGetExtReg(0xB9U) & 0x7FU;
+ pATIHW->bd = ATIGetExtReg(0xBDU) & 0x02U;
+ if (pATI->Chip <= ATI_CHIP_18800)
+ pATIHW->b2 = ATIGetExtReg(0xB2U) & 0xC0U;
+ else
+ {
+ pATIHW->b2 = 0x00U;
+ pATIHW->be = (ATIGetExtReg(0xBEU) & 0x30U) | 0x09U;
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ pATIHW->a6 = (ATIGetExtReg(0xA6U) & 0x38U) | 0x04U;
+ pATIHW->a7 = (ATIGetExtReg(0xA7U) & 0xBEU) ;
+ pATIHW->ac = (ATIGetExtReg(0xACU) & 0x8EU) ;
+ }
+ }
+ if (pMode->Flags & V_INTERLACE)
+ { /* Enable interlace */
+ if (pATI->Chip <= ATI_CHIP_18800)
+ pATIHW->b2 |= 0x01U;
+ else
+ pATIHW->be |= 0x02U;
+ }
+#if 0 /* This is no longer needed but is left in for reference */
+ if (pMode->Flags & V_DBLSCAN) /* Enable doublescan */
+ pATIHW->b1 |= 0x08U;
+#endif
+ if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
+ pATIHW->bd |= 0x08U; /* Enable composite sync */
+ if (pMode->Flags & V_NCSYNC)
+ pATIHW->bd |= 0x09U; /* Invert composite sync */
+ if (pMode->HSkew > 0)
+ {
+ if (pMode->HSkew <= 3)
+ pATIHW->b5 |= 0x04U;
+ else if (pATI->Chip >= ATI_CHIP_28800_2)
+ switch ((pMode->HSkew + 4) >> 3)
+ {
+ case 1: /* Use ATI override */
+ pATIHW->crt[3] &= ~0x60U;
+ pATIHW->b0 |= 0x01U;
+ break;
+ case 2: /* Use ATI override */
+ pATIHW->crt[3] &= ~0x60U;
+ pATIHW->a6 |= 0x01U;
+ break;
+ case 3:
+ pATIHW->crt[3] |= 0x60U;
+ break;
+ case 4:
+ pATIHW->a7 |= 0x40U;
+ break;
+ case 5:
+ pATIHW->ac |= 0x10U;
+ break;
+ case 6:
+ pATIHW->ac |= 0x20U;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * ATIVGAWonderSet --
+ *
+ * This function loads the VGA Wonder portion of a video state.
+ */
+void
+ATIVGAWonderSet
+(
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+ if (pATI->Chip <= ATI_CHIP_18800)
+ ATIModifyExtReg(pATI, 0xB2U, -1, 0x00U, pATIHW->b2);
+ else
+ {
+ ATIModifyExtReg(pATI, 0xBEU, -1, 0x00U, pATIHW->be);
+ if (pATI->Chip >= ATI_CHIP_28800_2)
+ {
+ ATIModifyExtReg(pATI, 0xBFU, -1, 0x00U, pATIHW->bf);
+ ATIModifyExtReg(pATI, 0xA3U, -1, 0x00U, pATIHW->a3);
+ ATIModifyExtReg(pATI, 0xA6U, -1, 0x00U, pATIHW->a6);
+ ATIModifyExtReg(pATI, 0xA7U, -1, 0x00U, pATIHW->a7);
+ ATIModifyExtReg(pATI, 0xABU, -1, 0x00U, pATIHW->ab);
+ ATIModifyExtReg(pATI, 0xACU, -1, 0x00U, pATIHW->ac);
+ ATIModifyExtReg(pATI, 0xADU, -1, 0x00U, pATIHW->ad);
+ ATIModifyExtReg(pATI, 0xAEU, -1, 0x00U, pATIHW->ae);
+ }
+ }
+ ATIModifyExtReg(pATI, 0xB0U, -1, 0x00U, pATIHW->b0);
+ ATIModifyExtReg(pATI, 0xB1U, -1, 0x00U, pATIHW->b1);
+ ATIModifyExtReg(pATI, 0xB3U, -1, 0x00U, pATIHW->b3);
+ ATIModifyExtReg(pATI, 0xB5U, -1, 0x00U, pATIHW->b5);
+ ATIModifyExtReg(pATI, 0xB6U, -1, 0x00U, pATIHW->b6);
+ ATIModifyExtReg(pATI, 0xB8U, -1, 0x00U, pATIHW->b8);
+ ATIModifyExtReg(pATI, 0xB9U, -1, 0x00U, pATIHW->b9);
+ ATIModifyExtReg(pATI, 0xBAU, -1, 0x00U, pATIHW->ba);
+ ATIModifyExtReg(pATI, 0xBDU, -1, 0x00U, pATIHW->bd);
+}
+
+#endif /* AVOID_CPIO */
diff --git a/src/atiwonder.h b/src/atiwonder.h
new file mode 100644
index 0000000..34f19cf
--- /dev/null
+++ b/src/atiwonder.h
@@ -0,0 +1,42 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiwonder.h,v 1.9 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIWONDER_H___
+#define ___ATIWONDER_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+#ifndef AVOID_CPIO
+
+extern void ATIVGAWonderPreInit FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIVGAWonderSave FunctionPrototype((ATIPtr, ATIHWPtr));
+extern void ATIVGAWonderCalculate FunctionPrototype((ATIPtr, ATIHWPtr,
+ DisplayModePtr));
+extern void ATIVGAWonderSet FunctionPrototype((ATIPtr, ATIHWPtr));
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIWONDER_H___ */
diff --git a/src/atiwonderio.c b/src/atiwonderio.c
new file mode 100644
index 0000000..064e49e
--- /dev/null
+++ b/src/atiwonderio.c
@@ -0,0 +1,86 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiwonderio.c,v 1.4 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ati.h"
+#include "atichip.h"
+#include "atiwonderio.h"
+
+#ifndef AVOID_CPIO
+
+/*
+ * ATIModifyExtReg --
+ *
+ * This function is called to modify certain bits in an ATI extended VGA
+ * register while preserving its other bits. The function will not write the
+ * register if it turns out its value would not change. This helps prevent
+ * server hangs on older adapters.
+ */
+void
+ATIModifyExtReg
+(
+ ATIPtr pATI,
+ const CARD8 Index,
+ int CurrentValue,
+ const CARD8 CurrentMask,
+ CARD8 NewValue
+)
+{
+ /* Possibly retrieve the current value */
+ if (CurrentValue < 0)
+ CurrentValue = ATIGetExtReg(Index);
+
+ /* Compute new value */
+ NewValue &= (CARD8)(~CurrentMask);
+ NewValue |= CurrentValue & CurrentMask;
+
+ /* Check if value will be changed */
+ if (CurrentValue == NewValue)
+ return;
+
+ /*
+ * The following is taken from ATI's VGA Wonder programmer's reference
+ * manual which says that this is needed to "ensure the proper state of the
+ * 8/16 bit ROM toggle". I suspect a timing glitch appeared in the 18800
+ * after its die was cast. 18800-1 and later chips do not exhibit this
+ * problem.
+ */
+ if ((pATI->Chip <= ATI_CHIP_18800) && (Index == 0xB2U) &&
+ ((NewValue ^ 0x40U) & CurrentValue & 0x40U))
+ {
+ CARD8 misc = inb(R_GENMO);
+ CARD8 bb = ATIGetExtReg(0xBBU);
+
+ outb(GENMO, (misc & 0xF3U) | 0x04U | ((bb & 0x10U) >> 1));
+ CurrentValue &= (CARD8)(~0x40U);
+ ATIPutExtReg(0xB2U, CurrentValue);
+ ATIDelay(5);
+ outb(GENMO, misc);
+ ATIDelay(5);
+ if (CurrentValue != NewValue)
+ ATIPutExtReg(0xB2U, NewValue);
+ }
+ else
+ ATIPutExtReg(Index, NewValue);
+}
+
+#endif /* AVOID_CPIO */
diff --git a/src/atiwonderio.h b/src/atiwonderio.h
new file mode 100644
index 0000000..dd0fa58
--- /dev/null
+++ b/src/atiwonderio.h
@@ -0,0 +1,48 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiwonderio.h,v 1.4 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIWONDERIO_H___
+
+#if !defined(___ATI_H___) && defined(XFree86Module)
+# error missing #include "ati.h" before #include "atiwonderio.h"
+# undef XFree86Module
+#endif
+
+#define ___ATIWONDERIO_H___ 1
+
+#include "atistruct.h"
+#include "ativgaio.h"
+
+#ifndef AVOID_CPIO
+
+extern void ATIModifyExtReg FunctionPrototype((ATIPtr, const CARD8, int,
+ const CARD8, CARD8));
+
+#define ATIGetExtReg(_Index) \
+ GetReg(pATI->CPIO_VGAWonder, _Index)
+#define ATIPutExtReg(_Index, _Value) \
+ PutReg(pATI->CPIO_VGAWonder, _Index, _Value)
+
+#endif /* AVOID_CPIO */
+
+#endif /* ___ATIWONDERIO_H___ */
diff --git a/src/atixv.c b/src/atixv.c
new file mode 100644
index 0000000..b15aa53
--- /dev/null
+++ b/src/atixv.c
@@ -0,0 +1,52 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.c,v 1.3 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "atistruct.h"
+#include "atixv.h"
+
+#include "xf86xv.h"
+
+/*
+ * ATIInitializeXVideo --
+ *
+ * This function is called to initialise XVideo extension support on a screen.
+ */
+Bool
+ATIInitializeXVideo
+(
+ ScreenPtr pScreen,
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ XF86VideoAdaptorPtr *ppAdaptor;
+ int nAdaptor;
+
+ if (!(pScreenInfo->memPhysBase = pATI->LinearBase))
+ return FALSE;
+
+ pScreenInfo->fbOffset = 0;
+
+ nAdaptor = xf86XVListGenericAdaptors(pScreenInfo, &ppAdaptor);
+ return xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor);
+}
diff --git a/src/atixv.h b/src/atixv.h
new file mode 100644
index 0000000..a5a3de6
--- /dev/null
+++ b/src/atixv.h
@@ -0,0 +1,35 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.h,v 1.3 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ___ATIXV_H___
+#define ___ATIXV_H___ 1
+
+#include "atipriv.h"
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+extern Bool ATIInitializeXVideo FunctionPrototype((ScreenPtr, ScrnInfoPtr,
+ ATIPtr));
+
+#endif /* ___ATIXV_H___ */
diff --git a/src/r128.h b/src/r128.h
new file mode 100644
index 0000000..d856fd8
--- /dev/null
+++ b/src/r128.h
@@ -0,0 +1,554 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.24 2002/12/16 16:19:10 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef _R128_H_
+#define _R128_H_
+
+#include "xf86str.h"
+
+ /* PCI support */
+#include "xf86Pci.h"
+
+ /* XAA and Cursor Support */
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+ /* DDC support */
+#include "xf86DDC.h"
+
+ /* Xv support */
+#include "xf86xv.h"
+
+ /* DRI support */
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "r128_dripriv.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#endif
+
+#define R128_DEBUG 0 /* Turn off debugging output */
+#define R128_IDLE_RETRY 32 /* Fall out of idle loops after this count */
+#define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */
+#define R128_MMIOSIZE 0x4000
+
+#define R128_VBIOS_SIZE 0x00010000
+
+#if R128_DEBUG
+#define R128TRACE(x) \
+ do { \
+ ErrorF("(**) %s(%d): ", R128_NAME, pScrn->scrnIndex); \
+ ErrorF x; \
+ } while (0);
+#else
+#define R128TRACE(x)
+#endif
+
+
+/* Other macros */
+#define R128_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define R128_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
+#define R128PTR(pScrn) ((R128InfoPtr)(pScrn)->driverPrivate)
+
+typedef struct { /* All values in XCLKS */
+ int ML; /* Memory Read Latency */
+ int MB; /* Memory Burst Length */
+ int Trcd; /* RAS to CAS delay */
+ int Trp; /* RAS percentage */
+ int Twr; /* Write Recovery */
+ int CL; /* CAS Latency */
+ int Tr2w; /* Read to Write Delay */
+ int Rloop; /* Loop Latency */
+ int Rloop_fudge; /* Add to ML to get Rloop */
+ char *name;
+} R128RAMRec, *R128RAMPtr;
+
+typedef struct {
+ /* Common registers */
+ CARD32 ovr_clr;
+ CARD32 ovr_wid_left_right;
+ CARD32 ovr_wid_top_bottom;
+ CARD32 ov0_scale_cntl;
+ CARD32 mpp_tb_config;
+ CARD32 mpp_gp_config;
+ CARD32 subpic_cntl;
+ CARD32 viph_control;
+ CARD32 i2c_cntl_1;
+ CARD32 gen_int_cntl;
+ CARD32 cap0_trig_cntl;
+ CARD32 cap1_trig_cntl;
+ CARD32 bus_cntl;
+ CARD32 config_cntl;
+
+ /* Other registers to save for VT switches */
+ CARD32 dp_datatype;
+ CARD32 gen_reset_cntl;
+ CARD32 clock_cntl_index;
+ CARD32 amcgpio_en_reg;
+ CARD32 amcgpio_mask;
+
+ /* CRTC registers */
+ CARD32 crtc_gen_cntl;
+ CARD32 crtc_ext_cntl;
+ CARD32 dac_cntl;
+ CARD32 crtc_h_total_disp;
+ CARD32 crtc_h_sync_strt_wid;
+ CARD32 crtc_v_total_disp;
+ CARD32 crtc_v_sync_strt_wid;
+ CARD32 crtc_offset;
+ CARD32 crtc_offset_cntl;
+ CARD32 crtc_pitch;
+
+ /* CRTC2 registers */
+ CARD32 crtc2_gen_cntl;
+
+ /* Flat panel registers */
+ CARD32 fp_crtc_h_total_disp;
+ CARD32 fp_crtc_v_total_disp;
+ CARD32 fp_gen_cntl;
+ CARD32 fp_h_sync_strt_wid;
+ CARD32 fp_horz_stretch;
+ CARD32 fp_panel_cntl;
+ CARD32 fp_v_sync_strt_wid;
+ CARD32 fp_vert_stretch;
+ CARD32 lvds_gen_cntl;
+ CARD32 tmds_crc;
+ CARD32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ CARD32 dot_clock_freq;
+ CARD32 pll_output_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ CARD32 ppll_ref_div;
+ CARD32 ppll_div_3;
+ CARD32 htotal_cntl;
+
+ /* DDA register */
+ CARD32 dda_config;
+ CARD32 dda_on_off;
+
+ /* Pallet */
+ Bool palette_valid;
+ CARD32 palette[256];
+} R128SaveRec, *R128SavePtr;
+
+typedef struct {
+ CARD16 reference_freq;
+ CARD16 reference_div;
+ CARD32 min_pll_freq;
+ CARD32 max_pll_freq;
+ CARD16 xclk;
+} R128PLLRec, *R128PLLPtr;
+
+typedef struct {
+ int bitsPerPixel;
+ int depth;
+ int displayWidth;
+ int pixel_code;
+ int pixel_bytes;
+ DisplayModePtr mode;
+} R128FBLayout;
+
+typedef struct {
+ EntityInfoPtr pEnt;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ int Chipset;
+ Bool Primary;
+
+ Bool FBDev;
+
+ unsigned long LinearAddr; /* Frame buffer physical address */
+ unsigned long MMIOAddr; /* MMIO region physical address */
+ unsigned long BIOSAddr; /* BIOS physical address */
+
+ unsigned char *MMIO; /* Map of MMIO region */
+ unsigned char *FB; /* Map of frame buffer */
+
+ CARD32 MemCntl;
+ CARD32 BusCntl;
+ unsigned long FbMapSize; /* Size of frame buffer, in bytes */
+ int Flags; /* Saved copy of mode flags */
+
+ CARD8 BIOSDisplay; /* Device the BIOS is set to display to */
+
+ Bool HasPanelRegs; /* Current chip can connect to a FP */
+ CARD8 *VBIOS; /* Video BIOS for mode validation on FPs */
+ int FPBIOSstart; /* Start of the flat panel info */
+
+ /* Computed values for FPs */
+ int PanelXRes;
+ int PanelYRes;
+ int HOverPlus;
+ int HSyncWidth;
+ int HBlank;
+ int VOverPlus;
+ int VSyncWidth;
+ int VBlank;
+ int PanelPwrDly;
+
+ R128PLLRec pll;
+ R128RAMPtr ram;
+
+ R128SaveRec SavedReg; /* Original (text) mode */
+ R128SaveRec ModeReg; /* Current mode */
+ Bool (*CloseScreen)(int, ScreenPtr);
+ void (*BlockHandler)(int, pointer, pointer, pointer);
+
+ Bool PaletteSavedOnVT; /* Palette saved on last VT switch */
+
+ XAAInfoRecPtr accel;
+ Bool accelOn;
+ xf86CursorInfoPtr cursor;
+ unsigned long cursor_start;
+ unsigned long cursor_end;
+
+ /*
+ * XAAForceTransBlit is used to change the behavior of the XAA
+ * SetupForScreenToScreenCopy function, to make it DGA-friendly.
+ */
+ Bool XAAForceTransBlit;
+
+ int fifo_slots; /* Free slots in the FIFO (64 max) */
+ int pix24bpp; /* Depth of pixmap for 24bpp framebuffer */
+ Bool dac6bits; /* Use 6 bit DAC? */
+
+ /* Computed values for Rage 128 */
+ int pitch;
+ int datatype;
+ CARD32 dp_gui_master_cntl;
+
+ /* Saved values for ScreenToScreenCopy */
+ int xdir;
+ int ydir;
+
+ /* ScanlineScreenToScreenColorExpand support */
+ unsigned char *scratch_buffer[1];
+ unsigned char *scratch_save;
+ int scanline_x;
+ int scanline_y;
+ int scanline_w;
+ int scanline_h;
+#ifdef XF86DRI
+ int scanline_hpass;
+ int scanline_x1clip;
+ int scanline_x2clip;
+ int scanline_rop;
+ int scanline_fg;
+ int scanline_bg;
+#endif /* XF86DRI */
+ int scanline_words;
+ int scanline_direct;
+ int scanline_bpp; /* Only used for ImageWrite */
+
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+ DGAFunctionRec DGAFuncs;
+
+ R128FBLayout CurrentLayout;
+#ifdef XF86DRI
+ Bool directRenderingEnabled;
+ DRIInfoPtr pDRIInfo;
+ int drmFD;
+ drmContext drmCtx;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ R128ConfigPrivPtr pVisualConfigsPriv;
+
+ drmHandle fbHandle;
+
+ drmSize registerSize;
+ drmHandle registerHandle;
+
+ Bool IsPCI; /* Current card is a PCI card */
+ drmSize pciSize;
+ drmHandle pciMemHandle;
+ unsigned char *PCI; /* Map */
+
+ drmSize agpSize;
+ drmHandle agpMemHandle; /* Handle from drmAgpAlloc */
+ unsigned long agpOffset;
+ unsigned char *AGP; /* Map */
+ int agpMode;
+
+ Bool CCEInUse; /* CCE is currently active */
+ int CCEMode; /* CCE mode that server/clients use */
+ int CCEFifoSize; /* Size of the CCE command FIFO */
+ Bool CCESecure; /* CCE security enabled */
+ int CCEusecTimeout; /* CCE timeout in usecs */
+
+ /* CCE ring buffer data */
+ unsigned long ringStart; /* Offset into AGP space */
+ drmHandle ringHandle; /* Handle from drmAddMap */
+ drmSize ringMapSize; /* Size of map */
+ int ringSize; /* Size of ring (in MB) */
+ unsigned char *ring; /* Map */
+ int ringSizeLog2QW;
+
+ unsigned long ringReadOffset; /* Offset into AGP space */
+ drmHandle ringReadPtrHandle; /* Handle from drmAddMap */
+ drmSize ringReadMapSize; /* Size of map */
+ unsigned char *ringReadPtr; /* Map */
+
+ /* CCE vertex/indirect buffer data */
+ unsigned long bufStart; /* Offset into AGP space */
+ drmHandle bufHandle; /* Handle from drmAddMap */
+ drmSize bufMapSize; /* Size of map */
+ int bufSize; /* Size of buffers (in MB) */
+ unsigned char *buf; /* Map */
+ int bufNumBufs; /* Number of buffers */
+ drmBufMapPtr buffers; /* Buffer map */
+
+ /* CCE AGP Texture data */
+ unsigned long agpTexStart; /* Offset into AGP space */
+ drmHandle agpTexHandle; /* Handle from drmAddMap */
+ drmSize agpTexMapSize; /* Size of map */
+ int agpTexSize; /* Size of AGP tex space (in MB) */
+ unsigned char *agpTex; /* Map */
+ int log2AGPTexGran;
+
+ /* CCE 2D accleration */
+ drmBufPtr indirectBuffer;
+ int indirectStart;
+
+ /* DRI screen private data */
+ int fbX;
+ int fbY;
+ int backX;
+ int backY;
+ int depthX;
+ int depthY;
+
+ int frontOffset;
+ int frontPitch;
+ int backOffset;
+ int backPitch;
+ int depthOffset;
+ int depthPitch;
+ int spanOffset;
+ int textureOffset;
+ int textureSize;
+ int log2TexGran;
+
+ /* Saved scissor values */
+ CARD32 sc_left;
+ CARD32 sc_right;
+ CARD32 sc_top;
+ CARD32 sc_bottom;
+
+ CARD32 re_top_left;
+ CARD32 re_width_height;
+
+ CARD32 aux_sc_cntl;
+
+ int irq;
+ CARD32 gen_int_cntl;
+
+ Bool DMAForXv;
+#endif
+
+ XF86VideoAdaptorPtr adaptor;
+ void (*VideoTimerCallback)(ScrnInfoPtr, Time);
+ int videoKey;
+ Bool showCache;
+ OptionInfoPtr Options;
+
+ Bool isDFP;
+ Bool isPro2;
+ I2CBusPtr pI2CBus;
+ CARD32 DDCReg;
+
+} R128InfoRec, *R128InfoPtr;
+
+#define R128WaitForFifo(pScrn, entries) \
+do { \
+ if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
+ info->fifo_slots -= entries; \
+} while (0)
+
+extern void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
+extern void R128WaitForIdle(ScrnInfoPtr pScrn);
+extern void R128EngineReset(ScrnInfoPtr pScrn);
+extern void R128EngineFlush(ScrnInfoPtr pScrn);
+
+extern unsigned R128INPLL(ScrnInfoPtr pScrn, int addr);
+extern void R128WaitForVerticalSync(ScrnInfoPtr pScrn);
+
+extern Bool R128AccelInit(ScreenPtr pScreen);
+extern void R128EngineInit(ScrnInfoPtr pScrn);
+extern Bool R128CursorInit(ScreenPtr pScreen);
+extern Bool R128DGAInit(ScreenPtr pScreen);
+
+extern int R128MinBits(int val);
+
+extern void R128InitVideo(ScreenPtr pScreen);
+
+#ifdef XF86DRI
+extern Bool R128DRIScreenInit(ScreenPtr pScreen);
+extern void R128DRICloseScreen(ScreenPtr pScreen);
+extern Bool R128DRIFinishScreenInit(ScreenPtr pScreen);
+
+#define R128CCE_START(pScrn, info) \
+do { \
+ int _ret = drmCommandNone(info->drmFD, DRM_R128_CCE_START); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CCE start %d\n", __FUNCTION__, _ret); \
+ } \
+} while (0)
+
+#define R128CCE_STOP(pScrn, info) \
+do { \
+ int _ret = R128CCEStop(pScrn); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CCE stop %d\n", __FUNCTION__, _ret); \
+ } \
+} while (0)
+
+#define R128CCE_RESET(pScrn, info) \
+do { \
+ if (info->directRenderingEnabled \
+ && R128CCE_USE_RING_BUFFER(info->CCEMode)) { \
+ int _ret = drmCommandNone(info->drmFD, DRM_R128_CCE_RESET); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CCE reset %d\n", __FUNCTION__, _ret); \
+ } \
+ } \
+} while (0)
+
+extern drmBufPtr R128CCEGetBuffer(ScrnInfoPtr pScrn);
+#endif
+
+extern void R128CCEFlushIndirect(ScrnInfoPtr pScrn, int discard);
+extern void R128CCEReleaseIndirect(ScrnInfoPtr pScrn);
+extern void R128CCEWaitForIdle(ScrnInfoPtr pScrn);
+extern int R128CCEStop(ScrnInfoPtr pScrn);
+
+
+#define CCE_PACKET0( reg, n ) \
+ (R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 ) \
+ (R128_CCE_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2() \
+ (R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n ) \
+ (R128_CCE_PACKET3 | (pkt) | ((n) << 16))
+
+
+#define R128_VERBOSE 0
+
+#define RING_LOCALS CARD32 *__head; int __count;
+
+#define R128CCE_REFRESH(pScrn, info) \
+do { \
+ if ( R128_VERBOSE ) { \
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO, "REFRESH( %d ) in %s\n", \
+ !info->CCEInUse , __FUNCTION__ ); \
+ } \
+ if ( !info->CCEInUse ) { \
+ R128CCEWaitForIdle(pScrn); \
+ BEGIN_RING( 6 ); \
+ OUT_RING_REG( R128_RE_TOP_LEFT, info->re_top_left ); \
+ OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height ); \
+ OUT_RING_REG( R128_AUX_SC_CNTL, info->aux_sc_cntl ); \
+ ADVANCE_RING(); \
+ info->CCEInUse = TRUE; \
+ } \
+} while (0)
+
+#define BEGIN_RING( n ) do { \
+ if ( R128_VERBOSE ) { \
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO, \
+ "BEGIN_RING( %d ) in %s\n", n, __FUNCTION__ ); \
+ } \
+ if ( !info->indirectBuffer ) { \
+ info->indirectBuffer = R128CCEGetBuffer( pScrn ); \
+ info->indirectStart = 0; \
+ } else if ( (info->indirectBuffer->used + 4*(n)) > \
+ info->indirectBuffer->total ) { \
+ R128CCEFlushIndirect( pScrn, 1 ); \
+ } \
+ __head = (pointer)((char *)info->indirectBuffer->address + \
+ info->indirectBuffer->used); \
+ __count = 0; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( R128_VERBOSE ) { \
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO, \
+ "ADVANCE_RING() used: %d+%d=%d/%d\n", \
+ info->indirectBuffer->used - info->indirectStart, \
+ __count * sizeof(CARD32), \
+ info->indirectBuffer->used - info->indirectStart + \
+ __count * sizeof(CARD32), \
+ info->indirectBuffer->total - info->indirectStart ); \
+ } \
+ info->indirectBuffer->used += __count * (int)sizeof(CARD32); \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( R128_VERBOSE ) { \
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO, \
+ " OUT_RING( 0x%08x )\n", (unsigned int)(x) ); \
+ } \
+ MMIO_OUT32(&__head[__count++], 0, (x)); \
+} while (0)
+
+#define OUT_RING_REG( reg, val ) \
+do { \
+ OUT_RING( CCE_PACKET0( reg, 0 ) ); \
+ OUT_RING( val ); \
+} while (0)
+
+#define FLUSH_RING() \
+do { \
+ if ( R128_VERBOSE ) \
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO, \
+ "FLUSH_RING in %s\n", __FUNCTION__ ); \
+ if ( info->indirectBuffer ) { \
+ R128CCEFlushIndirect( pScrn, 0 ); \
+ } \
+} while (0)
+
+#endif
diff --git a/src/r128_accel.c b/src/r128_accel.c
new file mode 100644
index 0000000..9329ad2
--- /dev/null
+++ b/src/r128_accel.c
@@ -0,0 +1,1806 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.16 2002/11/15 03:01:35 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * Credits:
+ *
+ * Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for
+ * providing source code to their 3.3.x Rage 128 driver. Portions of
+ * this file are based on the acceleration code for that driver.
+ *
+ * References:
+ *
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ * Notes on unimplemented XAA optimizations:
+ *
+ * SetClipping: The Rage128 doesn't support the full 16bit registers needed
+ * for XAA clip rect support.
+ * SolidFillTrap: This will probably work if we can compute the correct
+ * Bresenham error values.
+ * TwoPointLine: The Rage 128 supports Bresenham lines instead.
+ * DashedLine with non-power-of-two pattern length: Apparently, there is
+ * no way to set the length of the pattern -- it is always
+ * assumed to be 8 or 32 (or 1024?).
+ * ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference
+ * Manual where it states that monochrome expansion of frame
+ * buffer data is not supported.
+ * CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid
+ * direct/indirect method. If we had more data registers,
+ * then we could do better. If XAA supported a trigger write
+ * address, the code would be simpler.
+ * (Alan Hourihane) Update. We now use purely indirect and clip the full
+ * rectangle. Seems as the direct method has some problems
+ * with this, although this indirect method is much faster
+ * than the old method of setting up the engine per scanline.
+ * This code was the basis of the Radeon work we did.
+ * Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8
+ * pattern from frame buffer memory.
+ * ImageWrites: See CPUToScreenColorExpandFill.
+ *
+ */
+
+#define R128_TRAPEZOIDS 0 /* Trapezoids don't work */
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_reg.h"
+#include "r128_sarea.h"
+#ifdef XF86DRI
+#include "r128_sarea.h"
+#define _XF86DRI_SERVER_
+#include "r128_dri.h"
+#endif
+
+ /* Line support */
+#include "miline.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+static struct {
+ int rop;
+ int pattern;
+} R128_ROP[] = {
+ { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear */
+ { R128_ROP3_DSa, R128_ROP3_DPa }, /* Gxand */
+ { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse */
+ { R128_ROP3_S, R128_ROP3_P }, /* GXcopy */
+ { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted */
+ { R128_ROP3_D, R128_ROP3_D }, /* GXnoop */
+ { R128_ROP3_DSx, R128_ROP3_DPx }, /* GXxor */
+ { R128_ROP3_DSo, R128_ROP3_DPo }, /* GXor */
+ { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor */
+ { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv */
+ { R128_ROP3_Dn, R128_ROP3_Dn }, /* GXinvert */
+ { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse */
+ { R128_ROP3_Sn, R128_ROP3_Pn }, /* GXcopyInverted */
+ { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted */
+ { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand */
+ { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */
+};
+
+/* Flush all dirty data in the Pixel Cache to memory. */
+void R128EngineFlush(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ OUTREGP(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, ~R128_PC_FLUSH_ALL);
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) break;
+ }
+}
+
+/* Reset graphics card to known state. */
+void R128EngineReset(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 clock_cntl_index;
+ CARD32 mclk_cntl;
+ CARD32 gen_reset_cntl;
+
+ R128EngineFlush(pScrn);
+
+ clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
+ mclk_cntl = INPLL(pScrn, R128_MCLK_CNTL);
+
+ OUTPLL(R128_MCLK_CNTL, mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
+
+ gen_reset_cntl = INREG(R128_GEN_RESET_CNTL);
+
+ OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+ INREG(R128_GEN_RESET_CNTL);
+ OUTREG(R128_GEN_RESET_CNTL,
+ gen_reset_cntl & (CARD32)(~R128_SOFT_RESET_GUI));
+ INREG(R128_GEN_RESET_CNTL);
+
+ OUTPLL(R128_MCLK_CNTL, mclk_cntl);
+ OUTREG(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl);
+}
+
+/* The FIFO has 64 slots. This routines waits until at least `entries' of
+ these slots are empty. */
+void R128WaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ info->fifo_slots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+ if (info->fifo_slots >= entries) return;
+ }
+ R128TRACE(("FIFO timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
+ INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
+ INREG(R128_GUI_STAT),
+ INREG(R128_GUI_PROBE)));
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "FIFO timed out, resetting engine...\n");
+ R128EngineReset(pScrn);
+#ifdef XF86DRI
+ R128CCE_RESET(pScrn, info);
+ if (info->directRenderingEnabled) {
+ R128CCE_START(pScrn, info);
+ }
+#endif
+ }
+}
+
+/* Wait for the graphics engine to be completely idle: the FIFO has
+ drained, the Pixel Cache is flushed, and the engine is idle. This is a
+ standard "sync" function that will make the hardware "quiescent". */
+void R128WaitForIdle(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ R128WaitForFifoFunction(pScrn, 64);
+
+ for (;;) {
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (!(INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+ R128EngineFlush(pScrn);
+ return;
+ }
+ }
+ R128TRACE(("Idle timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
+ INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
+ INREG(R128_GUI_STAT),
+ INREG(R128_GUI_PROBE)));
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Idle timed out, resetting engine...\n");
+ R128EngineReset(pScrn);
+#ifdef XF86DRI
+ R128CCE_RESET(pScrn, info);
+ if (info->directRenderingEnabled) {
+ R128CCE_START(pScrn, info);
+ }
+#endif
+ }
+}
+
+#ifdef XF86DRI
+/* Wait until the CCE is completely idle: the FIFO has drained and the
+ * CCE is idle.
+ */
+void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int ret, i;
+
+ FLUSH_RING();
+
+ for (;;) {
+ i = 0;
+ do {
+ ret = drmCommandNone(info->drmFD, DRM_R128_CCE_IDLE);
+ } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+
+ if (ret && ret != -EBUSY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%s: CCE idle %d\n", __FUNCTION__, ret);
+ }
+
+ if (ret == 0) return;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Idle timed out, resetting engine...\n");
+ R128EngineReset(pScrn);
+
+ /* Always restart the engine when doing CCE 2D acceleration */
+ R128CCE_RESET(pScrn, info);
+ R128CCE_START(pScrn, info);
+ }
+}
+
+int R128CCEStop(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ drmR128CCEStop stop;
+ int ret, i;
+
+ stop.flush = 1;
+ stop.idle = 1;
+
+ ret = drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) );
+
+ if ( ret == 0 ) {
+ return 0;
+ } else if ( errno != EBUSY ) {
+ return -errno;
+ }
+
+ stop.flush = 0;
+
+ i = 0;
+ do {
+ ret = drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) );
+ } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+
+ if ( ret == 0 ) {
+ return 0;
+ } else if ( errno != EBUSY ) {
+ return -errno;
+ }
+
+ stop.idle = 0;
+
+ if ( drmCommandWrite( info->drmFD, DRM_R128_CCE_STOP,
+ &stop, sizeof(drmR128CCEStop) )) {
+ return -errno;
+ } else {
+ return 0;
+ }
+}
+
+#endif
+
+/* Setup for XAA SolidFill. */
+static void R128SetupForSolidFill(ScrnInfoPtr pScrn,
+ int color, int rop, unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 4);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].pattern));
+ OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+ OUTREG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT
+ | R128_DST_Y_TOP_TO_BOTTOM));
+}
+
+/* Subsequent XAA SolidFillRect.
+
+ Tests: xtest CH06/fllrctngl, xterm
+*/
+static void R128SubsequentSolidFillRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 2);
+ OUTREG(R128_DST_Y_X, (y << 16) | x);
+ OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
+}
+
+/* Setup for XAA solid lines. */
+static void R128SetupForSolidLine(ScrnInfoPtr pScrn,
+ int color, int rop, unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].pattern));
+ OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+}
+
+
+/* Subsequent XAA solid Bresenham line.
+
+ Tests: xtest CH06/drwln, ico, Mark Vojkovich's linetest program
+
+ [See http://www.xfree86.org/devel/archives/devel/1999-Jun/0102.shtml for
+ Mark Vojkovich's linetest program, posted 2Jun99 to devel@xfree86.org.]
+
+ x11perf -line500
+ 1024x768@76Hz 1024x768@76Hz
+ 8bpp 32bpp
+ not used: 39700.0/sec 34100.0/sec
+ used: 47600.0/sec 36800.0/sec
+*/
+static void R128SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
+ int x, int y,
+ int major, int minor,
+ int err, int len, int octant)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int flags = 0;
+
+ if (octant & YMAJOR) flags |= R128_DST_Y_MAJOR;
+ if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
+ if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
+
+ R128WaitForFifo(pScrn, 6);
+ OUTREG(R128_DP_CNTL_XDIR_YDIR_YMAJOR, flags);
+ OUTREG(R128_DST_Y_X, (y << 16) | x);
+ OUTREG(R128_DST_BRES_ERR, err);
+ OUTREG(R128_DST_BRES_INC, minor);
+ OUTREG(R128_DST_BRES_DEC, -major);
+ OUTREG(R128_DST_BRES_LNTH, len);
+}
+
+/* Subsequent XAA solid horizontal and vertical lines
+
+ 1024x768@76Hz 8bpp
+ Without With
+ x11perf -hseg500 87600.0/sec 798000.0/sec
+ x11perf -vseg500 38100.0/sec 38000.0/sec
+*/
+static void R128SubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
+ int x, int y, int len, int dir )
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 1);
+ OUTREG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT
+ | R128_DST_Y_TOP_TO_BOTTOM));
+
+ if (dir == DEGREES_0) {
+ R128SubsequentSolidFillRect(pScrn, x, y, len, 1);
+ } else {
+ R128SubsequentSolidFillRect(pScrn, x, y, 1, len);
+ }
+}
+
+/* Setup for XAA dashed lines.
+
+ Tests: xtest CH05/stdshs, XFree86/drwln
+
+ NOTE: Since we can only accelerate lines with power-of-2 patterns of
+ length <= 32, these x11perf numbers are not representative of the
+ speed-up on appropriately-sized patterns.
+
+ 1024x768@76Hz 8bpp
+ Without With
+ x11perf -dseg100 218000.0/sec 222000.0/sec
+ x11perf -dline100 215000.0/sec 221000.0/sec
+ x11perf -ddline100 178000.0/sec 180000.0/sec
+*/
+static void R128SetupForDashedLine(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop, unsigned int planemask,
+ int length, unsigned char *pattern)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 pat = *(CARD32 *)(pointer)pattern;
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+# define PAT_SHIFT(pat,n) pat << n
+#else
+# define PAT_SHIFT(pat,n) pat >> n
+#endif
+
+ switch (length) {
+ case 2: pat |= PAT_SHIFT(pat,2); /* fall through */
+ case 4: pat |= PAT_SHIFT(pat,4); /* fall through */
+ case 8: pat |= PAT_SHIFT(pat,8); /* fall through */
+ case 16: pat |= PAT_SHIFT(pat,16);
+ }
+
+ R128WaitForFifo(pScrn, 5);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | (bg == -1
+ ? R128_GMC_BRUSH_32x1_MONO_FG_LA
+ : R128_GMC_BRUSH_32x1_MONO_FG_BG)
+ | R128_ROP[rop].pattern
+ | R128_GMC_BYTE_LSB_TO_MSB));
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+ OUTREG(R128_DP_BRUSH_FRGD_CLR, fg);
+ OUTREG(R128_DP_BRUSH_BKGD_CLR, bg);
+ OUTREG(R128_BRUSH_DATA0, pat);
+}
+
+/* Subsequent XAA dashed line. */
+static void R128SubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
+ int x, int y,
+ int major, int minor,
+ int err, int len, int octant,
+ int phase)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int flags = 0;
+
+ if (octant & YMAJOR) flags |= R128_DST_Y_MAJOR;
+ if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
+ if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
+
+ R128WaitForFifo(pScrn, 7);
+ OUTREG(R128_DP_CNTL_XDIR_YDIR_YMAJOR, flags);
+ OUTREG(R128_DST_Y_X, (y << 16) | x);
+ OUTREG(R128_BRUSH_Y_X, (phase << 16) | phase);
+ OUTREG(R128_DST_BRES_ERR, err);
+ OUTREG(R128_DST_BRES_INC, minor);
+ OUTREG(R128_DST_BRES_DEC, -major);
+ OUTREG(R128_DST_BRES_LNTH, len);
+}
+
+#if R128_TRAPEZOIDS
+ /* This doesn't work. Except in the
+ lower-left quadrant, all of the pixel
+ errors appear to be because eL and eR
+ are not correct. Drawing from right to
+ left doesn't help. Be aware that the
+ non-_SUB registers set the sub-pixel
+ values to 0.5 (0x08), which isn't what
+ XAA wants. */
+/* Subsequent XAA SolidFillTrap. XAA always passes data that assumes we
+ fill from top to bottom, so dyL and dyR are always non-negative. */
+static void R128SubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h,
+ int left, int dxL, int dyL, int eL,
+ int right, int dxR, int dyR, int eR)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int flags = 0;
+ int Lymajor = 0;
+ int Rymajor = 0;
+ int origdxL = dxL;
+ int origdxR = dxR;
+
+ R128TRACE(("Trap %d %d; L %d %d %d %d; R %d %d %d %d\n",
+ y, h,
+ left, dxL, dyL, eL,
+ right, dxR, dyR, eR));
+
+ if (dxL < 0) dxL = -dxL; else flags |= (1 << 0) /* | (1 << 8) */;
+ if (dxR < 0) dxR = -dxR; else flags |= (1 << 6);
+
+ R128WaitForFifo(pScrn, 11);
+
+#if 1
+ OUTREG(R128_DP_CNTL, flags | (1 << 1) | (1 << 7));
+ OUTREG(R128_DST_Y_SUB, ((y) << 4) | 0x0 );
+ OUTREG(R128_DST_X_SUB, ((left) << 4)|0x0);
+ OUTREG(R128_TRAIL_BRES_ERR, eR-dxR);
+ OUTREG(R128_TRAIL_BRES_INC, dxR);
+ OUTREG(R128_TRAIL_BRES_DEC, -dyR);
+ OUTREG(R128_TRAIL_X_SUB, ((right) << 4) | 0x0);
+ OUTREG(R128_LEAD_BRES_ERR, eL-dxL);
+ OUTREG(R128_LEAD_BRES_INC, dxL);
+ OUTREG(R128_LEAD_BRES_DEC, -dyL);
+ OUTREG(R128_LEAD_BRES_LNTH_SUB, ((h) << 4) | 0x00);
+#else
+ OUTREG(R128_DP_CNTL, flags | (1 << 1) );
+ OUTREG(R128_DST_Y_SUB, (y << 4));
+ OUTREG(R128_DST_X_SUB, (right << 4));
+ OUTREG(R128_TRAIL_BRES_ERR, eL);
+ OUTREG(R128_TRAIL_BRES_INC, dxL);
+ OUTREG(R128_TRAIL_BRES_DEC, -dyL);
+ OUTREG(R128_TRAIL_X_SUB, (left << 4) | 0);
+ OUTREG(R128_LEAD_BRES_ERR, eR);
+ OUTREG(R128_LEAD_BRES_INC, dxR);
+ OUTREG(R128_LEAD_BRES_DEC, -dyR);
+ OUTREG(R128_LEAD_BRES_LNTH_SUB, h << 4);
+#endif
+}
+#endif
+
+/* Setup for XAA screen-to-screen copy.
+
+ Tests: xtest CH06/fllrctngl (also tests transparency).
+*/
+static void R128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
+ int xdir, int ydir, int rop,
+ unsigned int planemask,
+ int trans_color)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ info->xdir = xdir;
+ info->ydir = ydir;
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].rop
+ | R128_DP_SRC_SOURCE_MEMORY));
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+ OUTREG(R128_DP_CNTL, ((xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0)
+ | (ydir >= 0
+ ? R128_DST_Y_TOP_TO_BOTTOM
+ : 0)));
+
+ if ((trans_color != -1) || (info->XAAForceTransBlit == TRUE)) {
+ /* Set up for transparency */
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_CLR_CMP_CLR_SRC, trans_color);
+ OUTREG(R128_CLR_CMP_MASK, R128_CLR_CMP_MSK);
+ OUTREG(R128_CLR_CMP_CNTL, (R128_SRC_CMP_NEQ_COLOR
+ | R128_CLR_CMP_SRC_SOURCE));
+ }
+}
+
+/* Subsequent XAA screen-to-screen copy. */
+static void R128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ if (info->xdir < 0) xa += w - 1, xb += w - 1;
+ if (info->ydir < 0) ya += h - 1, yb += h - 1;
+
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_SRC_Y_X, (ya << 16) | xa);
+ OUTREG(R128_DST_Y_X, (yb << 16) | xb);
+ OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
+}
+
+/* Setup for XAA mono 8x8 pattern color expansion. Patterns with
+ transparency use `bg == -1'. This routine is only used if the XAA
+ pixmap cache is turned on.
+
+ Tests: xtest XFree86/fllrctngl (no other test will test this routine with
+ both transparency and non-transparency)
+
+ 1024x768@76Hz 8bpp
+ Without With
+ x11perf -srect100 38600.0/sec 85700.0/sec
+ x11perf -osrect100 38600.0/sec 85700.0/sec
+*/
+static void R128SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int patternx, int patterny,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 6);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | (bg == -1
+ ? R128_GMC_BRUSH_8X8_MONO_FG_LA
+ : R128_GMC_BRUSH_8X8_MONO_FG_BG)
+ | R128_ROP[rop].pattern
+ | R128_GMC_BYTE_LSB_TO_MSB));
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+ OUTREG(R128_DP_BRUSH_FRGD_CLR, fg);
+ OUTREG(R128_DP_BRUSH_BKGD_CLR, bg);
+ OUTREG(R128_BRUSH_DATA0, patternx);
+ OUTREG(R128_BRUSH_DATA1, patterny);
+}
+
+/* Subsequent XAA 8x8 pattern color expansion. Because they are used in
+ the setup function, `patternx' and `patterny' are not used here. */
+static void R128SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int patternx, int patterny,
+ int x, int y, int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_BRUSH_Y_X, (patterny << 8) | patternx);
+ OUTREG(R128_DST_Y_X, (y << 16) | x);
+ OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
+}
+
+#if 0
+/* Setup for XAA color 8x8 pattern fill.
+
+ Tests: xtest XFree86/fllrctngl (with Mono8x8PatternFill off)
+*/
+static void R128SetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int rop, unsigned int planemask,
+ int trans_color)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128TRACE(("Color8x8 %d %d %d\n", trans_color, patx, paty));
+
+ R128WaitForFifo(pScrn, 2);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_8x8_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].rop
+ | R128_DP_SRC_SOURCE_MEMORY));
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+
+ if (trans_color != -1) {
+ /* Set up for transparency */
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_CLR_CMP_CLR_SRC, trans_color);
+ OUTREG(R128_CLR_CMP_MASK, R128_CLR_CMP_MSK);
+ OUTREG(R128_CLR_CMP_CNTL, (R128_SRC_CMP_NEQ_COLOR
+ | R128_CLR_CMP_SRC_SOURCE));
+ }
+}
+
+/* Subsequent XAA 8x8 pattern color expansion. */
+static void R128SubsequentColor8x8PatternFillRect( ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y, int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128TRACE(("Color8x8 %d,%d %d,%d %d %d\n", patx, paty, x, y, w, h));
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_SRC_Y_X, (paty << 16) | patx);
+ OUTREG(R128_DST_Y_X, (y << 16) | x);
+ OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
+}
+#endif
+
+/* Setup for XAA indirect CPU-to-screen color expansion (indirect).
+ Because of how the scratch buffer is initialized, this is really a
+ mainstore-to-screen color expansion. Transparency is supported when `bg
+ == -1'.
+
+ x11perf -ftext (pure indirect):
+ 1024x768@76Hz 1024x768@76Hz
+ 8bpp 32bpp
+ not used: 685000.0/sec 794000.0/sec
+ used: 1070000.0/sec 1080000.0/sec
+
+ We could improve this indirect routine by about 10% if the hardware
+ could accept DWORD padded scanlines, or if XAA could provide bit-packed
+ data. We might also be able to move to a direct routine if there were
+ more HOST_DATA registers.
+
+ Implementing the hybrid indirect/direct scheme improved performance in a
+ few areas:
+
+ 1024x768@76 8bpp
+ Indirect Hybrid
+ x11perf -oddsrect10 50100.0/sec 71700.0/sec
+ x11perf -oddsrect100 4240.0/sec 6660.0/sec
+ x11perf -bigsrect10 50300.0/sec 71100.0/sec
+ x11perf -bigsrect100 4190.0/sec 6800.0/sec
+ x11perf -polytext 584000.0/sec 714000.0/sec
+ x11perf -polytext16 154000.0/sec 172000.0/sec
+ x11perf -seg1 1780000.0/sec 1880000.0/sec
+ x11perf -copyplane10 42900.0/sec 58300.0/sec
+ x11perf -copyplane100 4400.0/sec 6710.0/sec
+ x11perf -putimagexy10 5090.0/sec 6670.0/sec
+ x11perf -putimagexy100 424.0/sec 575.0/sec
+
+ 1024x768@76 -depth 24 -fbbpp 32
+ Indirect Hybrid
+ x11perf -oddsrect100 4240.0/sec 6670.0/sec
+ x11perf -bigsrect100 4190.0/sec 6800.0/sec
+ x11perf -polytext 585000.0/sec 719000.0/sec
+ x11perf -seg1 2960000.0/sec 2990000.0/sec
+ x11perf -copyplane100 4400.0/sec 6700.0/sec
+ x11perf -putimagexy100 138.0/sec 191.0/sec
+
+*/
+static void R128SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int
+ planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128WaitForFifo(pScrn, 4);
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_DST_CLIPPING
+ | R128_GMC_BRUSH_NONE
+ | (bg == -1
+ ? R128_GMC_SRC_DATATYPE_MONO_FG_LA
+ : R128_GMC_SRC_DATATYPE_MONO_FG_BG)
+ | R128_ROP[rop].rop
+ | R128_GMC_BYTE_LSB_TO_MSB
+ | R128_DP_SRC_SOURCE_HOST_DATA));
+#else /* X_BYTE_ORDER == X_BIG_ENDIAN */
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_DST_CLIPPING
+ | R128_GMC_BRUSH_NONE
+ | (bg == -1
+ ? R128_GMC_SRC_DATATYPE_MONO_FG_LA
+ : R128_GMC_SRC_DATATYPE_MONO_FG_BG)
+ | R128_ROP[rop].rop
+ | R128_DP_SRC_SOURCE_HOST_DATA));
+#endif
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+ OUTREG(R128_DP_SRC_FRGD_CLR, fg);
+ OUTREG(R128_DP_SRC_BKGD_CLR, bg);
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion. This is only
+ called once for each rectangle. */
+static void R128SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int x1clip = x+skipleft;
+ int x2clip = x+w;
+
+ info->scanline_h = h;
+ info->scanline_words = (w + 31) >> 5;
+
+#if 0
+ /* Seems as though the Rage128's doesn't like blitting directly
+ * as we must be overwriting something too quickly, therefore we
+ * render to the buffer first and then blit */
+ if ((info->scanline_words * h) <= 9) {
+ /* Turn on direct for less than 9 dword colour expansion */
+ info->scratch_buffer[0]
+ = (unsigned char *)(ADDRREG(R128_HOST_DATA_LAST)
+ - (info->scanline_words - 1));
+ info->scanline_direct = 1;
+ } else
+#endif
+ {
+ /* Use indirect for anything else */
+ info->scratch_buffer[0] = info->scratch_save;
+ info->scanline_direct = 0;
+ }
+
+ if (pScrn->bitsPerPixel == 24) {
+ x1clip *= 3;
+ x2clip *= 3;
+ }
+
+ R128WaitForFifo(pScrn, 4 + (info->scanline_direct ?
+ (info->scanline_words * h) : 0) );
+ OUTREG(R128_SC_TOP_LEFT, (y << 16) | (x1clip & 0xffff));
+ OUTREG(R128_SC_BOTTOM_RIGHT, ((y+h-1) << 16) | ((x2clip-1) & 0xffff));
+ OUTREG(R128_DST_Y_X, (y << 16) | (x & 0xffff));
+ /* Have to pad the width here and use clipping engine */
+ OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | ((w + 31) & ~31));
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion. This is called
+ once for each scanline. */
+static void R128SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 *p = (pointer)info->scratch_buffer[bufno];
+ int i;
+ int left = info->scanline_words;
+ volatile CARD32 *d;
+
+ if (info->scanline_direct) return;
+ --info->scanline_h;
+ while (left) {
+ write_mem_barrier();
+ if (left <= 8) {
+ /* Last scanline - finish write to DATA_LAST */
+ if (info->scanline_h == 0) {
+ R128WaitForFifo(pScrn, left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA_LAST) - (left - 1); left; --left)
+ *d++ = *p++;
+ return;
+ } else {
+ R128WaitForFifo(pScrn, left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA7) - (left - 1); left; --left)
+ *d++ = *p++;
+ }
+ } else {
+ R128WaitForFifo(pScrn, 8);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA0), i = 0; i < 8; i++)
+ *d++ = *p++;
+ left -= 8;
+ }
+ }
+}
+
+/* Setup for XAA indirect image write.
+
+ 1024x768@76Hz 8bpp
+ Without With
+ x11perf -putimage10 37500.0/sec 39300.0/sec
+ x11perf -putimage100 2150.0/sec 1170.0/sec
+ x11perf -putimage500 108.0/sec 49.8/sec
+ */
+static void R128SetupForScanlineImageWrite(ScrnInfoPtr pScrn,
+ int rop,
+ unsigned int planemask,
+ int trans_color,
+ int bpp,
+ int depth)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ info->scanline_bpp = bpp;
+
+ R128WaitForFifo(pScrn, 2);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_DST_CLIPPING
+ | R128_GMC_BRUSH_1X8_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].rop
+ | R128_GMC_BYTE_LSB_TO_MSB
+ | R128_DP_SRC_SOURCE_HOST_DATA));
+ OUTREG(R128_DP_WRITE_MASK, planemask);
+
+ if (trans_color != -1) {
+ /* Set up for transparency */
+ R128WaitForFifo(pScrn, 3);
+ OUTREG(R128_CLR_CMP_CLR_SRC, trans_color);
+ OUTREG(R128_CLR_CMP_MASK, R128_CLR_CMP_MSK);
+ OUTREG(R128_CLR_CMP_CNTL, (R128_SRC_CMP_NEQ_COLOR
+ | R128_CLR_CMP_SRC_SOURCE));
+ }
+}
+
+/* Subsequent XAA indirect image write. This is only called once for each
+ rectangle. */
+static void R128SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int x1clip = x+skipleft;
+ int x2clip = x+w;
+
+ int shift = 0; /* 32bpp */
+
+ if (pScrn->bitsPerPixel == 8) shift = 3;
+ else if (pScrn->bitsPerPixel == 16) shift = 1;
+
+ info->scanline_h = h;
+ info->scanline_words = (w * info->scanline_bpp + 31) >> 5;
+
+#if 0
+ /* Seeing as the CPUToScreen doesn't like this, I've done this
+ * here too, as it uses pretty much the same path. */
+ if ((info->scanline_words * h) <= 9) {
+ /* Turn on direct for less than 9 dword colour expansion */
+ info->scratch_buffer[0]
+ = (unsigned char *)(ADDRREG(R128_HOST_DATA_LAST)
+ - (info->scanline_words - 1));
+ info->scanline_direct = 1;
+ } else
+#endif
+ {
+ /* Use indirect for anything else */
+ info->scratch_buffer[0] = info->scratch_save;
+ info->scanline_direct = 0;
+ }
+
+ if (pScrn->bitsPerPixel == 24) {
+ x1clip *= 3;
+ x2clip *= 3;
+ }
+
+ R128WaitForFifo(pScrn, 4 + (info->scanline_direct ?
+ (info->scanline_words * h) : 0) );
+ OUTREG(R128_SC_TOP_LEFT, (y << 16) | (x1clip & 0xffff));
+ OUTREG(R128_SC_BOTTOM_RIGHT, ((y+h-1) << 16) | ((x2clip-1) & 0xffff));
+ OUTREG(R128_DST_Y_X, (y << 16) | (x & 0xffff));
+ /* Have to pad the width here and use clipping engine */
+ OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | ((w + shift) & ~shift));
+}
+
+/* Subsequent XAA indirect iamge write. This is called once for each
+ scanline. */
+static void R128SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 *p = (pointer)info->scratch_buffer[bufno];
+ int i;
+ int left = info->scanline_words;
+ volatile CARD32 *d;
+
+ if (info->scanline_direct) return;
+ --info->scanline_h;
+ while (left) {
+ write_mem_barrier();
+ if (left <= 8) {
+ /* Last scanline - finish write to DATA_LAST */
+ if (info->scanline_h == 0) {
+ R128WaitForFifo(pScrn, left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA_LAST) - (left - 1); left; --left)
+ *d++ = *p++;
+ return;
+ } else {
+ R128WaitForFifo(pScrn, left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA7) - (left - 1); left; --left)
+ *d++ = *p++;
+ }
+ } else {
+ R128WaitForFifo(pScrn, 8);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(R128_HOST_DATA0), i = 0; i < 8; i++)
+ *d++ = *p++;
+ left -= 8;
+ }
+ }
+}
+
+/* Initialize the acceleration hardware. */
+void R128EngineInit(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ R128TRACE(("EngineInit (%d/%d)\n", info->CurrentLayout.pixel_code, info->CurrentLayout.bitsPerPixel));
+
+ OUTREG(R128_SCALE_3D_CNTL, 0);
+ R128EngineReset(pScrn);
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8: info->datatype = 2; break;
+ case 15: info->datatype = 3; break;
+ case 16: info->datatype = 4; break;
+ case 24: info->datatype = 5; break;
+ case 32: info->datatype = 6; break;
+ default:
+ R128TRACE(("Unknown depth/bpp = %d/%d (code = %d)\n",
+ info->CurrentLayout.depth, info->CurrentLayout.bitsPerPixel,
+ info->CurrentLayout.pixel_code));
+ }
+ info->pitch = (info->CurrentLayout.displayWidth / 8) * (info->CurrentLayout.pixel_bytes == 3 ? 3 : 1);
+
+ R128TRACE(("Pitch for acceleration = %d\n", info->pitch));
+
+ R128WaitForFifo(pScrn, 2);
+ OUTREG(R128_DEFAULT_OFFSET, 0);
+ OUTREG(R128_DEFAULT_PITCH, info->pitch);
+
+ R128WaitForFifo(pScrn, 4);
+ OUTREG(R128_AUX_SC_CNTL, 0);
+ OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
+ | R128_DEFAULT_SC_BOTTOM_MAX));
+ OUTREG(R128_SC_TOP_LEFT, 0);
+ OUTREG(R128_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
+ | R128_DEFAULT_SC_BOTTOM_MAX));
+
+ info->dp_gui_master_cntl = ((info->datatype << R128_GMC_DST_DATATYPE_SHIFT)
+ | R128_GMC_CLR_CMP_CNTL_DIS
+ | R128_GMC_AUX_CLIP_DIS);
+ R128WaitForFifo(pScrn, 1);
+ OUTREG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR));
+
+ R128WaitForFifo(pScrn, 8);
+ OUTREG(R128_DST_BRES_ERR, 0);
+ OUTREG(R128_DST_BRES_INC, 0);
+ OUTREG(R128_DST_BRES_DEC, 0);
+ OUTREG(R128_DP_BRUSH_FRGD_CLR, 0xffffffff);
+ OUTREG(R128_DP_BRUSH_BKGD_CLR, 0x00000000);
+ OUTREG(R128_DP_SRC_FRGD_CLR, 0xffffffff);
+ OUTREG(R128_DP_SRC_BKGD_CLR, 0x00000000);
+ OUTREG(R128_DP_WRITE_MASK, 0xffffffff);
+
+ R128WaitForFifo(pScrn, 1);
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* FIXME: this is a kludge for texture uploads in the 3D driver. Look at
+ * how the radeon driver handles HOST_DATA_SWAP if you want to implement
+ * CCE ImageWrite acceleration or anything needing this bit */
+#ifdef XF86DRI
+ if (info->directRenderingEnabled)
+ OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN);
+ else
+#endif
+ OUTREGP(R128_DP_DATATYPE,
+ R128_HOST_BIG_ENDIAN_EN, ~R128_HOST_BIG_ENDIAN_EN);
+#else /* X_LITTLE_ENDIAN */
+ OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN);
+#endif
+
+#ifdef XF86DRI
+ info->sc_left = 0x00000000;
+ info->sc_right = R128_DEFAULT_SC_RIGHT_MAX;
+ info->sc_top = 0x00000000;
+ info->sc_bottom = R128_DEFAULT_SC_BOTTOM_MAX;
+
+ info->re_top_left = 0x00000000;
+ info->re_width_height = ((0x7ff << R128_RE_WIDTH_SHIFT) |
+ (0x7ff << R128_RE_HEIGHT_SHIFT));
+
+ info->aux_sc_cntl = 0x00000000;
+#endif
+
+ R128WaitForIdle(pScrn);
+}
+
+#ifdef XF86DRI
+
+/* Setup for XAA SolidFill. */
+static void R128CCESetupForSolidFill(ScrnInfoPtr pScrn,
+ int color, int rop,
+ unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 8 );
+
+ OUT_RING_REG( R128_DP_GUI_MASTER_CNTL,
+ (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].pattern) );
+
+ OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, color );
+ OUT_RING_REG( R128_DP_WRITE_MASK, planemask );
+ OUT_RING_REG( R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT |
+ R128_DST_Y_TOP_TO_BOTTOM));
+ ADVANCE_RING();
+}
+
+/* Subsequent XAA SolidFillRect.
+
+ Tests: xtest CH06/fllrctngl, xterm
+*/
+static void R128CCESubsequentSolidFillRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING_REG( R128_DST_Y_X, (y << 16) | x );
+ OUT_RING_REG( R128_DST_WIDTH_HEIGHT, (w << 16) | h );
+
+ ADVANCE_RING();
+}
+
+/* Setup for XAA screen-to-screen copy.
+
+ Tests: xtest CH06/fllrctngl (also tests transparency).
+*/
+static void R128CCESetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
+ int xdir, int ydir, int rop,
+ unsigned int planemask,
+ int trans_color)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ info->xdir = xdir;
+ info->ydir = ydir;
+
+ BEGIN_RING( 6 );
+
+ OUT_RING_REG( R128_DP_GUI_MASTER_CNTL,
+ (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_NONE
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].rop
+ | R128_DP_SRC_SOURCE_MEMORY) );
+
+ OUT_RING_REG( R128_DP_WRITE_MASK, planemask );
+ OUT_RING_REG( R128_DP_CNTL,
+ ((xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
+ (ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)) );
+
+ ADVANCE_RING();
+
+ if ((trans_color != -1) || (info->XAAForceTransBlit == TRUE)) {
+ BEGIN_RING( 6 );
+
+ OUT_RING_REG( R128_CLR_CMP_CLR_SRC, trans_color );
+ OUT_RING_REG( R128_CLR_CMP_MASK, R128_CLR_CMP_MSK );
+ OUT_RING_REG( R128_CLR_CMP_CNTL, (R128_SRC_CMP_NEQ_COLOR |
+ R128_CLR_CMP_SRC_SOURCE) );
+
+ ADVANCE_RING();
+ }
+}
+
+/* Subsequent XAA screen-to-screen copy. */
+static void R128CCESubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ if (info->xdir < 0) xa += w - 1, xb += w - 1;
+ if (info->ydir < 0) ya += h - 1, yb += h - 1;
+
+ BEGIN_RING( 6 );
+
+ OUT_RING_REG( R128_SRC_Y_X, (ya << 16) | xa );
+ OUT_RING_REG( R128_DST_Y_X, (yb << 16) | xb );
+ OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (h << 16) | w );
+
+ ADVANCE_RING();
+}
+
+
+/*
+ * XAA scanline color expansion
+ *
+ * We use HOSTDATA_BLT CCE packets, dividing the image in chunks that fit into
+ * the indirect buffer if necessary.
+ */
+static void R128CCESetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int
+ planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 2 );
+ OUT_RING_REG(R128_DP_WRITE_MASK, planemask);
+ ADVANCE_RING();
+
+ info->scanline_rop = rop;
+ info->scanline_fg = fg;
+ info->scanline_bg = bg;
+}
+
+/* Helper function to write out a HOSTDATA_BLT packet into the indirect buffer
+ and set the XAA scratch buffer address appropriately */
+static void R128CCEScanlineCPUToScreenColorExpandFillPacket(ScrnInfoPtr pScrn,
+ int bufno)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int chunk_words = info->scanline_hpass * info->scanline_words;
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( chunk_words+9 );
+
+ OUT_RING( CCE_PACKET3( R128_CCE_PACKET3_CNTL_HOSTDATA_BLT, chunk_words+9-2 ) );
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ OUT_RING( (info->dp_gui_master_cntl
+ | R128_GMC_DST_CLIPPING
+ | R128_GMC_BRUSH_NONE
+ | (info->scanline_bg == -1
+ ? R128_GMC_SRC_DATATYPE_MONO_FG_LA
+ : R128_GMC_SRC_DATATYPE_MONO_FG_BG)
+ | R128_ROP[info->scanline_rop].rop
+ | R128_GMC_BYTE_LSB_TO_MSB
+ | R128_DP_SRC_SOURCE_HOST_DATA));
+#else /* X_BYTE_ORDER == X_BIG_ENDIAN */
+ OUT_RING( (info->dp_gui_master_cntl
+ | R128_GMC_DST_CLIPPING
+ | R128_GMC_BRUSH_NONE
+ | (info->scanline_bg == -1
+ ? R128_GMC_SRC_DATATYPE_MONO_FG_LA
+ : R128_GMC_SRC_DATATYPE_MONO_FG_BG)
+ | R128_ROP[info->scanline_rop].rop
+ | R128_DP_SRC_SOURCE_HOST_DATA));
+#endif
+ OUT_RING( (info->scanline_y << 16) | (info->scanline_x1clip & 0xffff) );
+ OUT_RING( ((info->scanline_y+info->scanline_hpass-1) << 16) | ((info->scanline_x2clip-1) & 0xffff) );
+ OUT_RING( info->scanline_fg );
+ OUT_RING( info->scanline_bg );
+ OUT_RING( (info->scanline_y << 16) | (info->scanline_x & 0xffff));
+
+ /* Have to pad the width here and use clipping engine */
+ OUT_RING( (info->scanline_hpass << 16) | ((info->scanline_w + 31) & ~31));
+
+ OUT_RING( chunk_words );
+
+ info->scratch_buffer[bufno] = (unsigned char *) &__head[__count];
+ __count += chunk_words;
+
+ ADVANCE_RING();
+
+ info->scanline_y += info->scanline_hpass;
+ info->scanline_h -= info->scanline_hpass;
+
+ if ( R128_VERBOSE )
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "%s: hpass=%d, words=%d => chunk_words=%d, y=%d, h=%d\n",
+ __FUNCTION__, info->scanline_hpass, info->scanline_words,
+ chunk_words, info->scanline_y, info->scanline_h );
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion. This is only
+ called once for each rectangle. */
+static void R128CCESubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+#define BUFSIZE ( R128_BUFFER_SIZE/4-9 )
+
+ info->scanline_x = x;
+ info->scanline_y = y;
+ info->scanline_w = w;
+ info->scanline_h = h;
+
+ info->scanline_x1clip = x+skipleft;
+ info->scanline_x2clip = x+w;
+
+ info->scanline_words = (w + 31) >> 5;
+ info->scanline_hpass = min(h,(BUFSIZE/info->scanline_words));
+
+ if ( R128_VERBOSE )
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "%s: x=%d, y=%d, w=%d, h=%d, skipleft=%d => x1clip=%d, x2clip=%d, hpass=%d, words=%d\n",
+ __FUNCTION__, x, y, w, h, skipleft, info->scanline_x1clip, info->scanline_x2clip,
+ info->scanline_hpass, info->scanline_words );
+
+ R128CCEScanlineCPUToScreenColorExpandFillPacket(pScrn, 0);
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion. This is called
+ once for each scanline. */
+static void R128CCESubsequentColorExpandScanline(ScrnInfoPtr pScrn,
+ int bufno)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if ( R128_VERBOSE )
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "%s enter: scanline_hpass=%d, scanline_h=%d\n",
+ __FUNCTION__, info->scanline_hpass, info->scanline_h );
+
+ if (--info->scanline_hpass) {
+ info->scratch_buffer[bufno] += 4 * info->scanline_words;
+ }
+ else if(info->scanline_h) {
+ info->scanline_hpass = min(info->scanline_h,(BUFSIZE/info->scanline_words));
+ R128CCEScanlineCPUToScreenColorExpandFillPacket(pScrn, bufno);
+ }
+
+ if ( R128_VERBOSE )
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ "%s exit: scanline_hpass=%d, scanline_h=%d\n",
+ __FUNCTION__, info->scanline_hpass, info->scanline_h );
+}
+
+/* Solid lines */
+static void R128CCESetupForSolidLine(ScrnInfoPtr pScrn,
+ int color, int rop, unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 6 );
+
+ OUT_RING_REG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | R128_GMC_BRUSH_SOLID_COLOR
+ | R128_GMC_SRC_DATATYPE_COLOR
+ | R128_ROP[rop].pattern));
+ OUT_RING_REG(R128_DP_BRUSH_FRGD_CLR, color);
+ OUT_RING_REG(R128_DP_WRITE_MASK, planemask);
+
+ ADVANCE_RING();
+}
+
+static void R128CCESubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
+ int x, int y,
+ int major, int minor,
+ int err, int len, int octant)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int flags = 0;
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ if (octant & YMAJOR) flags |= R128_DST_Y_MAJOR;
+ if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
+ if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
+
+ BEGIN_RING( 12 );
+
+ OUT_RING_REG(R128_DP_CNTL_XDIR_YDIR_YMAJOR, flags);
+ OUT_RING_REG(R128_DST_Y_X, (y << 16) | x);
+ OUT_RING_REG(R128_DST_BRES_ERR, err);
+ OUT_RING_REG(R128_DST_BRES_INC, minor);
+ OUT_RING_REG(R128_DST_BRES_DEC, -major);
+ OUT_RING_REG(R128_DST_BRES_LNTH, len);
+
+ ADVANCE_RING();
+}
+
+static void R128CCESubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
+ int x, int y, int len, int dir )
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING_REG(R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT
+ | R128_DST_Y_TOP_TO_BOTTOM));
+
+ ADVANCE_RING();
+
+ if (dir == DEGREES_0) {
+ R128CCESubsequentSolidFillRect(pScrn, x, y, len, 1);
+ } else {
+ R128CCESubsequentSolidFillRect(pScrn, x, y, 1, len);
+ }
+}
+
+/* Dashed lines */
+static void R128CCESetupForDashedLine(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop, unsigned int planemask,
+ int length, unsigned char *pattern)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ CARD32 pat = *(CARD32 *)(pointer)pattern;
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+# define PAT_SHIFT(pat,n) pat << n
+#else
+# define PAT_SHIFT(pat,n) pat >> n
+#endif
+
+ switch (length) {
+ case 2: pat |= PAT_SHIFT(pat,2); /* fall through */
+ case 4: pat |= PAT_SHIFT(pat,4); /* fall through */
+ case 8: pat |= PAT_SHIFT(pat,8); /* fall through */
+ case 16: pat |= PAT_SHIFT(pat,16);
+ }
+
+ BEGIN_RING( 10 );
+
+ OUT_RING_REG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | (bg == -1
+ ? R128_GMC_BRUSH_32x1_MONO_FG_LA
+ : R128_GMC_BRUSH_32x1_MONO_FG_BG)
+ | R128_ROP[rop].pattern
+ | R128_GMC_BYTE_LSB_TO_MSB));
+ OUT_RING_REG(R128_DP_WRITE_MASK, planemask);
+ OUT_RING_REG(R128_DP_BRUSH_FRGD_CLR, fg);
+ OUT_RING_REG(R128_DP_BRUSH_BKGD_CLR, bg);
+ OUT_RING_REG(R128_BRUSH_DATA0, pat);
+
+ ADVANCE_RING();
+}
+
+static void R128CCESubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
+ int x, int y,
+ int major, int minor,
+ int err, int len, int octant,
+ int phase)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int flags = 0;
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ if (octant & YMAJOR) flags |= R128_DST_Y_MAJOR;
+ if (!(octant & XDECREASING)) flags |= R128_DST_X_DIR_LEFT_TO_RIGHT;
+ if (!(octant & YDECREASING)) flags |= R128_DST_Y_DIR_TOP_TO_BOTTOM;
+
+ BEGIN_RING( 14 );
+
+ OUT_RING_REG(R128_DP_CNTL_XDIR_YDIR_YMAJOR, flags);
+ OUT_RING_REG(R128_DST_Y_X, (y << 16) | x);
+ OUT_RING_REG(R128_BRUSH_Y_X, (phase << 16) | phase);
+ OUT_RING_REG(R128_DST_BRES_ERR, err);
+ OUT_RING_REG(R128_DST_BRES_INC, minor);
+ OUT_RING_REG(R128_DST_BRES_DEC, -major);
+ OUT_RING_REG(R128_DST_BRES_LNTH, len);
+
+ ADVANCE_RING();
+}
+
+/* Mono 8x8 pattern color expansion */
+static void R128CCESetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int patternx, int patterny,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 12 );
+
+ OUT_RING_REG(R128_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | (bg == -1
+ ? R128_GMC_BRUSH_8X8_MONO_FG_LA
+ : R128_GMC_BRUSH_8X8_MONO_FG_BG)
+ | R128_ROP[rop].pattern
+ | R128_GMC_BYTE_LSB_TO_MSB));
+ OUT_RING_REG(R128_DP_WRITE_MASK, planemask);
+ OUT_RING_REG(R128_DP_BRUSH_FRGD_CLR, fg);
+ OUT_RING_REG(R128_DP_BRUSH_BKGD_CLR, bg);
+ OUT_RING_REG(R128_BRUSH_DATA0, patternx);
+ OUT_RING_REG(R128_BRUSH_DATA1, patterny);
+
+ ADVANCE_RING();
+}
+
+static void R128CCESubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int patternx, int patterny,
+ int x, int y, int w, int h)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ RING_LOCALS;
+
+ R128CCE_REFRESH( pScrn, info );
+
+ BEGIN_RING( 6 );
+
+ OUT_RING_REG(R128_BRUSH_Y_X, (patterny << 8) | patternx);
+ OUT_RING_REG(R128_DST_Y_X, (y << 16) | x);
+ OUT_RING_REG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
+
+ ADVANCE_RING();
+}
+
+/* Get an indirect buffer for the CCE 2D acceleration commands.
+ */
+drmBufPtr R128CCEGetBuffer( ScrnInfoPtr pScrn )
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ drmDMAReq dma;
+ drmBufPtr buf = NULL;
+ int indx = 0;
+ int size = 0;
+ int ret, i = 0;
+
+#if 0
+ /* FIXME: pScrn->pScreen has not been initialized when this is first
+ called from RADEONSelectBuffer via RADEONDRICPInit. We could use
+ the screen index from pScrn, which is initialized, and then get
+ the screen from screenInfo.screens[index], but that is a hack. */
+ dma.context = DRIGetContext(pScrn->pScreen);
+#else
+ dma.context = 0x00000001; /* This is the X server's context */
+#endif
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = R128_BUFFER_SIZE;
+ dma.request_list = &indx;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+ while ( 1 ) {
+ do {
+ ret = drmDMA( info->drmFD, &dma );
+ if ( ret && ret != -EAGAIN ) {
+ xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
+ "%s: CCE GetBuffer %d\n", __FUNCTION__, ret );
+ }
+ } while ( ( ret == -EAGAIN ) && ( i++ < R128_TIMEOUT ) );
+
+ if ( ret == 0 ) {
+ buf = &info->buffers->list[indx];
+ buf->used = 0;
+ if ( R128_VERBOSE ) {
+ xf86DrvMsg( pScrn->scrnIndex, X_INFO,
+ " GetBuffer returning %d\n", buf->idx );
+ }
+ return buf;
+ }
+
+ xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
+ "GetBuffer timed out, resetting engine...\n");
+ R128EngineReset( pScrn );
+ /* R128EngineRestore( pScrn ); FIXME ??? */
+
+ /* Always restart the engine when doing CCE 2D acceleration */
+ R128CCE_RESET( pScrn, info );
+ R128CCE_START( pScrn, info );
+ }
+}
+
+/* Flush the indirect buffer to the kernel for submission to the card.
+ */
+void R128CCEFlushIndirect( ScrnInfoPtr pScrn, int discard )
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ drmBufPtr buffer = info->indirectBuffer;
+ int start = info->indirectStart;
+ drmR128Indirect indirect;
+
+ if ( !buffer )
+ return;
+
+ if ( (start == buffer->used) && !discard )
+ return;
+
+ indirect.idx = buffer->idx;
+ indirect.start = start;
+ indirect.end = buffer->used;
+ indirect.discard = discard;
+
+ drmCommandWriteRead( info->drmFD, DRM_R128_INDIRECT,
+ &indirect, sizeof(drmR128Indirect));
+
+ if ( discard )
+ buffer = info->indirectBuffer = R128CCEGetBuffer( pScrn );
+
+ /* pad to an even number of dwords */
+ if (buffer->used & 7)
+ buffer->used = ( buffer->used+7 ) & ~7;
+
+ info->indirectStart = buffer->used;
+}
+
+/* Flush and release the indirect buffer.
+ */
+void R128CCEReleaseIndirect( ScrnInfoPtr pScrn )
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ drmBufPtr buffer = info->indirectBuffer;
+ int start = info->indirectStart;
+ drmR128Indirect indirect;
+
+ info->indirectBuffer = NULL;
+ info->indirectStart = 0;
+
+ if ( !buffer )
+ return;
+
+ indirect.idx = buffer->idx;
+ indirect.start = start;
+ indirect.end = buffer->used;
+ indirect.discard = 1;
+
+ drmCommandWriteRead( info->drmFD, DRM_R128_INDIRECT,
+ &indirect, sizeof(drmR128Indirect));
+}
+
+static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ a->Flags = (PIXMAP_CACHE
+ | OFFSCREEN_PIXMAPS
+ | LINEAR_FRAMEBUFFER);
+
+ /* Sync */
+ a->Sync = R128CCEWaitForIdle;
+
+ /* Solid Filled Rectangle */
+ a->PolyFillRectSolidFlags = 0;
+ a->SetupForSolidFill = R128CCESetupForSolidFill;
+ a->SubsequentSolidFillRect = R128CCESubsequentSolidFillRect;
+
+ /* Screen-to-screen Copy */
+ /* Transparency uses the wrong colors for
+ 24 bpp mode -- the transparent part is
+ correct, but the opaque color is wrong.
+ This can be seen with netscape's I-bar
+ cursor when editing in the URL location
+ box. */
+ a->ScreenToScreenCopyFlags = ((pScrn->bitsPerPixel == 24)
+ ? NO_TRANSPARENCY
+ : 0);
+ a->SetupForScreenToScreenCopy = R128CCESetupForScreenToScreenCopy;
+ a->SubsequentScreenToScreenCopy = R128CCESubsequentScreenToScreenCopy;
+
+ /* Indirect CPU-To-Screen Color Expand */
+ a->ScanlineCPUToScreenColorExpandFillFlags = LEFT_EDGE_CLIPPING
+ | LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ a->NumScanlineColorExpandBuffers = 1;
+ a->ScanlineColorExpandBuffers = info->scratch_buffer;
+ info->scratch_buffer[0] = NULL;
+ a->SetupForScanlineCPUToScreenColorExpandFill
+ = R128CCESetupForScanlineCPUToScreenColorExpandFill;
+ a->SubsequentScanlineCPUToScreenColorExpandFill
+ = R128CCESubsequentScanlineCPUToScreenColorExpandFill;
+ a->SubsequentColorExpandScanline = R128CCESubsequentColorExpandScanline;
+
+ /* Bresenham Solid Lines */
+ a->SetupForSolidLine = R128CCESetupForSolidLine;
+ a->SubsequentSolidBresenhamLine = R128CCESubsequentSolidBresenhamLine;
+ a->SubsequentSolidHorVertLine = R128CCESubsequentSolidHorVertLine;
+
+ /* Bresenham Dashed Lines*/
+ a->SetupForDashedLine = R128CCESetupForDashedLine;
+ a->SubsequentDashedBresenhamLine = R128CCESubsequentDashedBresenhamLine;
+ a->DashPatternMaxLength = 32;
+ a->DashedLineFlags = (LINE_PATTERN_LSBFIRST_LSBJUSTIFIED
+ | LINE_PATTERN_POWER_OF_2_ONLY);
+
+ /* Mono 8x8 Pattern Fill (Color Expand) */
+ a->SetupForMono8x8PatternFill = R128CCESetupForMono8x8PatternFill;
+ a->SubsequentMono8x8PatternFillRect = R128CCESubsequentMono8x8PatternFillRect;
+ a->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS
+ | HARDWARE_PATTERN_PROGRAMMED_ORIGIN
+ | HARDWARE_PATTERN_SCREEN_ORIGIN
+ | BIT_ORDER_IN_BYTE_LSBFIRST);
+}
+#endif
+
+static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ a->Flags = (PIXMAP_CACHE
+ | OFFSCREEN_PIXMAPS
+ | LINEAR_FRAMEBUFFER);
+
+ /* Sync */
+ a->Sync = R128WaitForIdle;
+
+ /* Solid Filled Rectangle */
+ a->PolyFillRectSolidFlags = 0;
+ a->SetupForSolidFill = R128SetupForSolidFill;
+ a->SubsequentSolidFillRect = R128SubsequentSolidFillRect;
+
+ /* Screen-to-screen Copy */
+ /* Transparency uses the wrong colors for
+ 24 bpp mode -- the transparent part is
+ correct, but the opaque color is wrong.
+ This can be seen with netscape's I-bar
+ cursor when editing in the URL location
+ box. */
+ a->ScreenToScreenCopyFlags = ((pScrn->bitsPerPixel == 24)
+ ? NO_TRANSPARENCY
+ : 0);
+ a->SetupForScreenToScreenCopy = R128SetupForScreenToScreenCopy;
+ a->SubsequentScreenToScreenCopy = R128SubsequentScreenToScreenCopy;
+
+ /* Mono 8x8 Pattern Fill (Color Expand) */
+ a->SetupForMono8x8PatternFill = R128SetupForMono8x8PatternFill;
+ a->SubsequentMono8x8PatternFillRect = R128SubsequentMono8x8PatternFillRect;
+ a->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS
+ | HARDWARE_PATTERN_PROGRAMMED_ORIGIN
+ | HARDWARE_PATTERN_SCREEN_ORIGIN
+ | BIT_ORDER_IN_BYTE_LSBFIRST);
+
+ /* Indirect CPU-To-Screen Color Expand */
+ a->ScanlineCPUToScreenColorExpandFillFlags = LEFT_EDGE_CLIPPING
+ | LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ a->NumScanlineColorExpandBuffers = 1;
+ a->ScanlineColorExpandBuffers = info->scratch_buffer;
+ info->scratch_save = xalloc(((pScrn->virtualX+31)/32*4)
+ + (pScrn->virtualX
+ * info->CurrentLayout.pixel_bytes));
+ info->scratch_buffer[0] = info->scratch_save;
+ a->SetupForScanlineCPUToScreenColorExpandFill
+ = R128SetupForScanlineCPUToScreenColorExpandFill;
+ a->SubsequentScanlineCPUToScreenColorExpandFill
+ = R128SubsequentScanlineCPUToScreenColorExpandFill;
+ a->SubsequentColorExpandScanline = R128SubsequentColorExpandScanline;
+
+ /* Bresenham Solid Lines */
+ a->SetupForSolidLine = R128SetupForSolidLine;
+ a->SubsequentSolidBresenhamLine = R128SubsequentSolidBresenhamLine;
+ a->SubsequentSolidHorVertLine = R128SubsequentSolidHorVertLine;
+
+ /* Bresenham Dashed Lines*/
+ a->SetupForDashedLine = R128SetupForDashedLine;
+ a->SubsequentDashedBresenhamLine = R128SubsequentDashedBresenhamLine;
+ a->DashPatternMaxLength = 32;
+ a->DashedLineFlags = (LINE_PATTERN_LSBFIRST_LSBJUSTIFIED
+ | LINE_PATTERN_POWER_OF_2_ONLY);
+
+ /* ImageWrite */
+ a->NumScanlineImageWriteBuffers = 1;
+ a->ScanlineImageWriteBuffers = info->scratch_buffer;
+ info->scratch_buffer[0] = info->scratch_save;
+ a->SetupForScanlineImageWrite = R128SetupForScanlineImageWrite;
+ a->SubsequentScanlineImageWriteRect= R128SubsequentScanlineImageWriteRect;
+ a->SubsequentImageWriteScanline = R128SubsequentImageWriteScanline;
+ a->ScanlineImageWriteFlags = CPU_TRANSFER_PAD_DWORD
+ /* Performance tests show that we shouldn't use GXcopy for
+ * uploads as a memcpy is faster */
+ | NO_GXCOPY
+ | LEFT_EDGE_CLIPPING
+ | LEFT_EDGE_CLIPPING_NEGATIVE_X
+ | SCANLINE_PAD_DWORD;
+}
+
+/* Initialize XAA for supported acceleration and also initialize the
+ graphics hardware for acceleration. */
+Bool R128AccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ XAAInfoRecPtr a;
+
+ if (!(a = info->accel = XAACreateInfoRec())) return FALSE;
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled)
+ R128CCEAccelInit(pScrn, a);
+ else
+#endif
+ R128MMIOAccelInit(pScrn, a);
+
+ R128EngineInit(pScrn);
+ return XAAInit(pScreen, a);
+}
diff --git a/src/r128_common.h b/src/r128_common.h
new file mode 100644
index 0000000..6f2c13a
--- /dev/null
+++ b/src/r128_common.h
@@ -0,0 +1,170 @@
+/* r128_common.h -- common header definitions for R128 2D/3D/DRM suite
+ * Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * Converted to common header format:
+ * Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h,v 1.2 2002/12/16 16:19:10 dawes Exp $
+ *
+ */
+
+#ifndef _R128_COMMON_H_
+#define _R128_COMMON_H_
+
+#include "X11/Xmd.h"
+
+/*
+ * WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (r128_drm.h)
+ */
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_R128_INIT 0x00
+#define DRM_R128_CCE_START 0x01
+#define DRM_R128_CCE_STOP 0x02
+#define DRM_R128_CCE_RESET 0x03
+#define DRM_R128_CCE_IDLE 0x04
+#define DRM_R128_UNDEFINED1 0x05
+#define DRM_R128_RESET 0x06
+#define DRM_R128_SWAP 0x07
+#define DRM_R128_CLEAR 0x08
+#define DRM_R128_VERTEX 0x09
+#define DRM_R128_INDICES 0x0a
+#define DRM_R128_BLIT 0x0b
+#define DRM_R128_DEPTH 0x0c
+#define DRM_R128_STIPPLE 0x0d
+#define DRM_R128_UNDEFINED2 0x0e
+#define DRM_R128_INDIRECT 0x0f
+#define DRM_R128_FULLSCREEN 0x10
+#define DRM_R128_CLEAR2 0x11
+#define DRM_R128_GETPARAM 0x12
+
+#define DRM_R128_FRONT_BUFFER 0x1
+#define DRM_R128_BACK_BUFFER 0x2
+#define DRM_R128_DEPTH_BUFFER 0x4
+
+typedef struct {
+ enum {
+ DRM_R128_INIT_CCE = 0x01,
+ DRM_R128_CLEANUP_CCE = 0x02
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ int cce_mode;
+ int cce_secure; /* FIXME: Deprecated, we should remove this */
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+ unsigned int span_offset;
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long ring_rptr_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+} drmR128Init;
+
+typedef struct {
+ int flush;
+ int idle;
+} drmR128CCEStop;
+
+typedef struct {
+ int idx;
+ int start;
+ int end;
+ int discard;
+} drmR128Indirect;
+
+typedef struct {
+ int idx;
+ int pitch;
+ int offset;
+ int format;
+ unsigned short x, y;
+ unsigned short width, height;
+} drmR128Blit;
+
+typedef struct {
+ enum {
+ DRM_R128_WRITE_SPAN = 0x01,
+ DRM_R128_WRITE_PIXELS = 0x02,
+ DRM_R128_READ_SPAN = 0x03,
+ DRM_R128_READ_PIXELS = 0x04
+ } func;
+ int n;
+ int *x;
+ int *y;
+ unsigned int *buffer;
+ unsigned char *mask;
+} drmR128Depth;
+
+typedef struct {
+ int prim;
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
+} drmR128Vertex;
+
+typedef struct {
+ unsigned int *mask;
+} drmR128Stipple;
+
+typedef struct {
+ unsigned int flags;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+ unsigned int depth_mask;
+} drmR128Clear;
+
+typedef struct {
+ enum {
+ DRM_R128_INIT_FULLSCREEN = 0x01,
+ DRM_R128_CLEANUP_FULLSCREEN = 0x02
+ } func;
+} drmR128Fullscreen;
+
+typedef struct drm_r128_getparam {
+ int param;
+ int *value;
+} drmR128GetParam;
+
+#define R128_PARAM_IRQ_NR 1
+
+#endif
diff --git a/src/r128_cursor.c b/src/r128_cursor.c
new file mode 100644
index 0000000..5a2ac4f
--- /dev/null
+++ b/src/r128_cursor.c
@@ -0,0 +1,263 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c,v 1.6 2003/02/13 20:28:40 tsi Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * References:
+ *
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_reg.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define P_SWAP32( a , b ) \
+ ((char *)a)[0] = ((char *)b)[3]; \
+ ((char *)a)[1] = ((char *)b)[2]; \
+ ((char *)a)[2] = ((char *)b)[1]; \
+ ((char *)a)[3] = ((char *)b)[0]
+
+#define P_SWAP16( a , b ) \
+ ((char *)a)[0] = ((char *)b)[1]; \
+ ((char *)a)[1] = ((char *)b)[0]; \
+ ((char *)a)[2] = ((char *)b)[3]; \
+ ((char *)a)[3] = ((char *)b)[2]
+#endif
+
+
+/* Set cursor foreground and background colors. */
+static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG(R128_CUR_CLR0, bg);
+ OUTREG(R128_CUR_CLR1, fg);
+}
+
+/* Set cursor position to (x,y) with offset into cursor bitmap at
+ (xorigin,yorigin). */
+static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ xf86CursorInfoPtr cursor = info->cursor;
+ int xorigin = 0;
+ int yorigin = 0;
+ int total_y = pScrn->frameY1 - pScrn->frameY0;
+
+ if (x < 0) xorigin = -x;
+ if (y < 0) yorigin = -y;
+ if (y > total_y) y = total_y;
+ if (info->Flags & V_DBLSCAN) y *= 2;
+ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
+ if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
+
+ OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin);
+ OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK
+ | ((xorigin ? 0 : x) << 16)
+ | (yorigin ? 0 : y)));
+ OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16);
+}
+
+/* Copy cursor image from `image' to video memory. R128SetCursorPosition
+ will be called after this, so we can ignore xorigin and yorigin. */
+static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 *s = (pointer)image;
+ CARD32 *d = (pointer)(info->FB + info->cursor_start);
+ int y;
+ CARD32 save;
+
+ save = INREG(R128_CRTC_GEN_CNTL);
+ OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN);
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ switch(info->CurrentLayout.pixel_bytes) {
+ case 4:
+ case 3:
+ for (y = 0; y < 64; y++) {
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ P_SWAP32(d,s);
+ d++; s++;
+ }
+ break;
+ case 2:
+ for (y = 0; y < 64; y++) {
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ P_SWAP16(d,s);
+ d++; s++;
+ }
+ break;
+ default:
+ for (y = 0; y < 64; y++) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+ }
+#else
+ for (y = 0; y < 64; y++) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+#endif
+
+ /* Set the area after the cursor to be all transparent so that we
+ won't display corrupted cursors on the screen */
+ for (y = 0; y < 64; y++) {
+ *d++ = 0xffffffff; /* The AND bits */
+ *d++ = 0xffffffff;
+ *d++ = 0x00000000; /* The XOR bits */
+ *d++ = 0x00000000;
+ }
+
+
+ OUTREG(R128_CRTC_GEN_CNTL, save);
+}
+
+/* Hide hardware cursor. */
+static void R128HideCursor(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN);
+}
+
+/* Show hardware cursor. */
+static void R128ShowCursor(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN);
+}
+
+/* Determine if hardware cursor is in use. */
+static Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ return info->cursor_start ? TRUE : FALSE;
+}
+
+/* Initialize hardware cursor support. */
+Bool R128CursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ xf86CursorInfoPtr cursor;
+ FBAreaPtr fbarea;
+ int width;
+ int height;
+ int size;
+
+
+ if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
+
+ cursor->MaxWidth = 64;
+ cursor->MaxHeight = 64;
+ cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
+ | HARDWARE_CURSOR_SHOW_TRANSPARENT
+ | HARDWARE_CURSOR_UPDATE_UNHIDDEN
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+#endif
+ | HARDWARE_CURSOR_INVERT_MASK
+ | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
+ | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
+ | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
+
+ cursor->SetCursorColors = R128SetCursorColors;
+ cursor->SetCursorPosition = R128SetCursorPosition;
+ cursor->LoadCursorImage = R128LoadCursorImage;
+ cursor->HideCursor = R128HideCursor;
+ cursor->ShowCursor = R128ShowCursor;
+ cursor->UseHWCursor = R128UseHWCursor;
+
+ size = (cursor->MaxWidth/4) * cursor->MaxHeight;
+ width = pScrn->displayWidth;
+ height = (size*2 + 1023) / pScrn->displayWidth;
+ fbarea = xf86AllocateOffscreenArea(pScreen,
+ width,
+ height,
+ 16,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!fbarea) {
+ info->cursor_start = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Hardware cursor disabled"
+ " due to insufficient offscreen memory\n");
+ } else {
+ info->cursor_start = R128_ALIGN((fbarea->box.x1
+ + width * fbarea->box.y1)
+ * info->CurrentLayout.pixel_bytes, 16);
+ info->cursor_end = info->cursor_start + size;
+ }
+
+ R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n",
+ info->cursor_start, info->cursor_end));
+
+ return xf86InitCursor(pScreen, cursor);
+}
diff --git a/src/r128_dga.c b/src/r128_dga.c
new file mode 100644
index 0000000..6c0013a
--- /dev/null
+++ b/src/r128_dga.c
@@ -0,0 +1,397 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dga.c,v 1.9 2002/10/30 12:52:12 alanh Exp $ */
+/*
+ * Authors:
+ * Ove Kåven <ovek@transgaming.com>,
+ * borrowing some code from the Chips and MGA drivers.
+ */
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_probe.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+ /* DGA support */
+#include "dgaproc.h"
+
+#ifdef XF86DRI
+#include "r128_common.h"
+#endif
+
+static Bool R128_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool R128_SetMode(ScrnInfoPtr, DGAModePtr);
+static int R128_GetViewport(ScrnInfoPtr);
+static void R128_SetViewport(ScrnInfoPtr, int, int, int);
+static void R128_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void R128_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void R128_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+
+static DGAModePtr R128SetupDGAMode(ScrnInfoPtr pScrn,
+ DGAModePtr modes,
+ int *num,
+ int bitsPerPixel,
+ int depth,
+ Bool pixmap,
+ int secondPitch,
+ unsigned long red,
+ unsigned long green,
+ unsigned long blue,
+ short visualClass)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ DGAModePtr newmodes = NULL;
+ DGAModePtr currentMode;
+ DisplayModePtr pMode;
+ DisplayModePtr firstMode;
+ unsigned int size;
+ int pitch;
+ int Bpp = bitsPerPixel >> 3;
+
+SECOND_PASS:
+
+ pMode = firstMode = pScrn->modes;
+
+ while (1) {
+ pitch = pScrn->displayWidth;
+ size = pitch * Bpp * pMode->VDisplay;
+
+ if ((!secondPitch || (pitch != secondPitch)) &&
+ (size <= info->FbMapSize)) {
+
+ if (secondPitch)
+ pitch = secondPitch;
+
+ if (!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec))))
+ break;
+
+ modes = newmodes;
+ currentMode = modes + *num;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS;
+
+ if (pixmap)
+ currentMode->flags |= DGA_PIXMAP_AVAILABLE;
+
+ if (info->accel) {
+ if (info->accel->SetupForSolidFill &&
+ info->accel->SubsequentSolidFillRect)
+ currentMode->flags |= DGA_FILL_RECT;
+ if (info->accel->SetupForScreenToScreenCopy &&
+ info->accel->SubsequentScreenToScreenCopy)
+ currentMode->flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;
+ if (currentMode->flags &
+ (DGA_PIXMAP_AVAILABLE | DGA_FILL_RECT |
+ DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS))
+ currentMode->flags &= ~DGA_CONCURRENT_ACCESS;
+ }
+ if (pMode->Flags & V_DBLSCAN)
+ currentMode->flags |= DGA_DOUBLESCAN;
+ if (pMode->Flags & V_INTERLACE)
+ currentMode->flags |= DGA_INTERLACED;
+
+ currentMode->byteOrder = pScrn->imageByteOrder;
+ currentMode->depth = depth;
+ currentMode->bitsPerPixel = bitsPerPixel;
+ currentMode->red_mask = red;
+ currentMode->green_mask = green;
+ currentMode->blue_mask = blue;
+ currentMode->visualClass = visualClass;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ currentMode->xViewportStep = 8;
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ currentMode->offset = 0;
+ currentMode->address = (unsigned char*)info->LinearAddr;
+ currentMode->bytesPerScanline = pitch * Bpp;
+ currentMode->imageWidth = pitch;
+ currentMode->imageHeight = (info->FbMapSize
+ / currentMode->bytesPerScanline);
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = (currentMode->imageWidth
+ - currentMode->viewportWidth);
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = (currentMode->imageHeight
+ - currentMode->viewportHeight);
+ (*num)++;
+ }
+
+ pMode = pMode->next;
+ if (pMode == firstMode)
+ break;
+ }
+
+ if (secondPitch) {
+ secondPitch = 0;
+ goto SECOND_PASS;
+ }
+
+ return modes;
+}
+
+Bool
+R128DGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ DGAModePtr modes = NULL;
+ int num = 0;
+
+ /* 8 */
+ modes = R128SetupDGAMode (pScrn, modes, &num, 8, 8,
+ (pScrn->bitsPerPixel == 8),
+ (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
+ 0, 0, 0, PseudoColor);
+
+ /* 15 */
+ modes = R128SetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel == 16),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7c00, 0x03e0, 0x001f, TrueColor);
+
+ modes = R128SetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel == 16),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7c00, 0x03e0, 0x001f, DirectColor);
+
+ /* 16 */
+ modes = R128SetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel == 16),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xf800, 0x07e0, 0x001f, TrueColor);
+
+ modes = R128SetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel == 16),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xf800, 0x07e0, 0x001f, DirectColor);
+
+ /* 24 */
+ modes = R128SetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xff0000, 0x00ff00, 0x0000ff, TrueColor);
+
+ modes = R128SetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xff0000, 0x00ff00, 0x0000ff, DirectColor);
+
+ /* 32 */
+ modes = R128SetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel == 32),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xff0000, 0x00ff00, 0x0000ff, TrueColor);
+
+ modes = R128SetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel == 32),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xff0000, 0x00ff00, 0x0000ff, DirectColor);
+
+ info->numDGAModes = num;
+ info->DGAModes = modes;
+
+ info->DGAFuncs.OpenFramebuffer = R128_OpenFramebuffer;
+ info->DGAFuncs.CloseFramebuffer = NULL;
+ info->DGAFuncs.SetMode = R128_SetMode;
+ info->DGAFuncs.SetViewport = R128_SetViewport;
+ info->DGAFuncs.GetViewport = R128_GetViewport;
+
+ info->DGAFuncs.Sync = NULL;
+ info->DGAFuncs.FillRect = NULL;
+ info->DGAFuncs.BlitRect = NULL;
+ info->DGAFuncs.BlitTransRect = NULL;
+
+ if (info->accel) {
+ info->DGAFuncs.Sync = info->accel->Sync;
+ if (info->accel->SetupForSolidFill &&
+ info->accel->SubsequentSolidFillRect)
+ info->DGAFuncs.FillRect = R128_FillRect;
+ if (info->accel->SetupForScreenToScreenCopy &&
+ info->accel->SubsequentScreenToScreenCopy) {
+ info->DGAFuncs.BlitRect = R128_BlitRect;
+ info->DGAFuncs.BlitTransRect = R128_BlitTransRect;
+ }
+ }
+
+ return DGAInit(pScreen, &(info->DGAFuncs), modes, num);
+}
+
+
+static Bool
+R128_SetMode(
+ ScrnInfoPtr pScrn,
+ DGAModePtr pMode
+){
+ static R128FBLayout SavedLayouts[MAXSCREENS];
+ int indx = pScrn->pScreen->myNum;
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if(!pMode) { /* restore the original mode */
+ /* put the ScreenParameters back */
+ if(info->DGAactive)
+ memcpy(&info->CurrentLayout, &SavedLayouts[indx], sizeof(R128FBLayout));
+
+ pScrn->currentMode = info->CurrentLayout.mode;
+
+ pScrn->SwitchMode(indx, pScrn->currentMode, 0);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ R128CCE_STOP(pScrn, info);
+ }
+#endif
+ if (info->accelOn)
+ R128EngineInit(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ R128CCE_START(pScrn, info);
+ }
+#endif
+ pScrn->AdjustFrame(indx, 0, 0, 0);
+ info->DGAactive = FALSE;
+ } else {
+ if(!info->DGAactive) { /* save the old parameters */
+ memcpy(&SavedLayouts[indx], &info->CurrentLayout, sizeof(R128FBLayout));
+ info->DGAactive = TRUE;
+ }
+
+ info->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
+ info->CurrentLayout.depth = pMode->depth;
+ info->CurrentLayout.displayWidth = pMode->bytesPerScanline /
+ (pMode->bitsPerPixel >> 3);
+ info->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8;
+ info->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16
+ ? pMode->bitsPerPixel
+ : pMode->depth);
+ /* R128ModeInit() will set the mode field */
+
+ pScrn->SwitchMode(indx, pMode->mode, 0);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ R128CCE_STOP(pScrn, info);
+ }
+#endif
+ if (info->accelOn)
+ R128EngineInit(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ R128CCE_START(pScrn, info);
+ }
+#endif
+ }
+
+ return TRUE;
+}
+
+
+
+static int
+R128_GetViewport(
+ ScrnInfoPtr pScrn
+){
+ R128InfoPtr info = R128PTR(pScrn);
+
+ return info->DGAViewportStatus;
+}
+
+
+static void
+R128_SetViewport(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int flags
+){
+ R128InfoPtr info = R128PTR(pScrn);
+
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ info->DGAViewportStatus = 0; /* FIXME */
+}
+
+
+static void
+R128_FillRect (
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+){
+ R128InfoPtr info = R128PTR(pScrn);
+
+ (*info->accel->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0));
+ (*info->accel->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+static void
+R128_BlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*info->accel->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, (CARD32)(~0), -1);
+ (*info->accel->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+
+static void
+R128_BlitTransRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ info->XAAForceTransBlit = TRUE;
+
+ (*info->accel->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, (CARD32)(~0), color);
+
+ info->XAAForceTransBlit = FALSE;
+
+ (*info->accel->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+
+static Bool
+R128_OpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+){
+ R128InfoPtr info = R128PTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)info->LinearAddr;
+ *size = info->FbMapSize;
+ *offset = 0;
+ *flags = /* DGA_NEED_ROOT */ 0; /* don't need root, just /dev/mem access */
+
+ return TRUE;
+}
diff --git a/src/r128_dri.c b/src/r128_dri.c
new file mode 100644
index 0000000..63cedb5
--- /dev/null
+++ b/src/r128_dri.c
@@ -0,0 +1,1337 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Rickard E. Faith <faith@valinux.com>
+ * Daryll Strauss <daryll@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_dri.h"
+#include "r128_reg.h"
+#include "r128_sarea.h"
+#include "r128_version.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+#include "windowstr.h"
+#include "xf86PciInfo.h"
+
+ /* GLX/DRI/DRM definitions */
+#define _XF86DRI_SERVER_
+#include "GL/glxtokens.h"
+#include "sarea.h"
+
+/* ?? HACK - for now, put this here... */
+/* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
+#if defined(__alpha__)
+# define DRM_PAGE_SIZE 8192
+#elif defined(__ia64__)
+# define DRM_PAGE_SIZE getpagesize()
+#else
+# define DRM_PAGE_SIZE 4096
+#endif
+
+/* Initialize the visual configs that are supported by the hardware.
+ These are combined with the visual configs that the indirect
+ rendering core supports, and the intersection is exported to the
+ client. */
+static Bool R128InitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ R128ConfigPrivPtr pR128Configs = 0;
+ R128ConfigPrivPtr *pR128ConfigPtrs = 0;
+ int i, accum, stencil, db;
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8: /* 8bpp mode is not support */
+ case 15: /* FIXME */
+ case 24: /* FIXME */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed (depth %d not supported). "
+ "Disabling DRI.\n", info->CurrentLayout.pixel_code);
+ return FALSE;
+
+#define R128_USE_ACCUM 1
+#define R128_USE_STENCIL 1
+#define R128_USE_DB 1
+
+ case 16:
+ numConfigs = 1;
+ if (R128_USE_ACCUM) numConfigs *= 2;
+ if (R128_USE_STENCIL) numConfigs *= 2;
+ if (R128_USE_DB) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pR128Configs
+ = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pR128ConfigPtrs
+ = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pR128Configs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= R128_USE_DB; db++) {
+ for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
+ for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
+ pR128ConfigPtrs[i] = &pR128Configs[i];
+
+ pConfigs[i].vid = (VisualID)(-1);
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0x00000000;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ pConfigs[i].depthSize = 16;
+ if (stencil)
+ pConfigs[i].stencilSize = 8; /* Simulated in software */
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum || stencil) {
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ numConfigs = 1;
+ if (R128_USE_ACCUM) numConfigs *= 2;
+ if (R128_USE_STENCIL) numConfigs *= 2;
+ if (R128_USE_DB) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pR128Configs
+ = (R128ConfigPrivPtr)xcalloc(sizeof(R128ConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pR128ConfigPtrs
+ = (R128ConfigPrivPtr*)xcalloc(sizeof(R128ConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pR128Configs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= R128_USE_DB; db++) {
+ for (accum = 0; accum <= R128_USE_ACCUM; accum++) {
+ for (stencil = 0; stencil <= R128_USE_STENCIL; stencil++) {
+ pR128ConfigPtrs[i] = &pR128Configs[i];
+
+ pConfigs[i].vid = (VisualID)(-1);
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+ pConfigs[i].alphaMask = 0x00000000;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 24;
+ if (stencil) {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum || stencil) {
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+ }
+
+ info->numVisualConfigs = numConfigs;
+ info->pVisualConfigs = pConfigs;
+ info->pVisualConfigsPriv = pR128Configs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pR128ConfigPtrs);
+ return TRUE;
+}
+
+/* Create the Rage 128-specific context information */
+static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ info->drmCtx = hwContext;
+ return TRUE;
+}
+
+/* Destroy the Rage 128-specific context information */
+static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+ /* Nothing yet */
+}
+
+/* Called when the X server is woken up to allow the last client's
+ context to be saved and the X server's context to be loaded. This is
+ not necessary for the Rage 128 since the client detects when it's
+ context is not currently loaded and then load's it itself. Since the
+ registers to start and stop the CCE are privileged, only the X server
+ can start/stop the engine. */
+static void R128EnterServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->accel) info->accel->NeedToSync = TRUE;
+}
+
+/* Called when the X server goes to sleep to allow the X server's
+ context to be saved and the last client's context to be loaded. This
+ is not necessary for the Rage 128 since the client detects when it's
+ context is not currently loaded and then load's it itself. Since the
+ registers to start and stop the CCE are privileged, only the X server
+ can start/stop the engine. */
+static void R128LeaveServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ if (!info->directRenderingEnabled) {
+ /* Save all hardware scissors */
+ info->sc_left = INREG(R128_SC_LEFT);
+ info->sc_right = INREG(R128_SC_RIGHT);
+ info->sc_top = INREG(R128_SC_TOP);
+ info->sc_bottom = INREG(R128_SC_BOTTOM);
+ info->aux_sc_cntl = INREG(R128_SC_BOTTOM);
+ } else if (info->CCEInUse) {
+ R128CCEReleaseIndirect(pScrn);
+
+ info->CCEInUse = FALSE;
+ }
+}
+
+/* Contexts can be swapped by the X server if necessary. This callback
+ is currently only used to perform any functions necessary when
+ entering or leaving the X server, and in the future might not be
+ necessary. */
+static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+ if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
+ R128EnterServer(pScreen);
+ }
+ if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
+ R128LeaveServer(pScreen);
+ }
+}
+
+/* Initialize the state of the back and depth buffers. */
+static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
+{
+ /* FIXME: This routine needs to have acceleration turned on */
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ BoxPtr pbox, pboxSave;
+ int nbox, nboxSave;
+ int depth;
+
+ /* FIXME: Use accel when CCE 2D code is written */
+ if (info->directRenderingEnabled)
+ return;
+
+ /* FIXME: This should be based on the __GLXvisualConfig info */
+ switch (pScrn->bitsPerPixel) {
+ case 8: depth = 0x000000ff; break;
+ case 16: depth = 0x0000ffff; break;
+ case 24: depth = 0x00ffffff; break;
+ case 32: depth = 0xffffffff; break;
+ default: depth = 0x00000000; break;
+ }
+
+ /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */
+ /* FIXME: Only initialize the back and depth buffers for contexts
+ that request them */
+
+ pboxSave = pbox = REGION_RECTS(prgn);
+ nboxSave = nbox = REGION_NUM_RECTS(prgn);
+
+ (*info->accel->SetupForSolidFill)(pScrn, 0, GXcopy, (CARD32)(-1));
+ for (; nbox; nbox--, pbox++) {
+ (*info->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + info->fbX,
+ pbox->y1 + info->fbY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ (*info->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + info->backX,
+ pbox->y1 + info->backY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ }
+
+ pbox = pboxSave;
+ nbox = nboxSave;
+
+ /* FIXME: this needs to consider depth tiling. */
+ (*info->accel->SetupForSolidFill)(pScrn, depth, GXcopy, (CARD32)(-1));
+ for (; nbox; nbox--, pbox++)
+ (*info->accel->SubsequentSolidFillRect)(pScrn,
+ pbox->x1 + info->depthX,
+ pbox->y1 + info->depthY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+
+ info->accel->NeedToSync = TRUE;
+}
+
+/* Copy the back and depth buffers when the X server moves a window. */
+static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 indx)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ /* FIXME: This routine needs to have acceleration turned on */
+ /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */
+ /* FIXME: Only initialize the back and depth buffers for contexts
+ that request them */
+
+ /* FIXME: Use accel when CCE 2D code is written */
+ if (info->directRenderingEnabled)
+ return;
+}
+
+/* Initialize the AGP state. Request memory for use in AGP space, and
+ initialize the Rage 128 registers to point to that memory. */
+static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ unsigned char *R128MMIO = info->MMIO;
+ unsigned long mode;
+ unsigned int vendor, device;
+ int ret;
+ unsigned long cntl, chunk;
+ int s, l;
+ int flags;
+ unsigned long agpBase;
+
+ if (drmAgpAcquire(info->drmFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
+ return FALSE;
+ }
+
+ /* Modify the mode if the default mode is
+ not appropriate for this particular
+ combination of graphics card and AGP
+ chipset. */
+
+ mode = drmAgpGetMode(info->drmFD); /* Default mode */
+ vendor = drmAgpVendorId(info->drmFD);
+ device = drmAgpDeviceId(info->drmFD);
+
+ mode &= ~R128_AGP_MODE_MASK;
+ switch (info->agpMode) {
+ case 4: mode |= R128_AGP_4X_MODE;
+ case 2: mode |= R128_AGP_2X_MODE;
+ case 1: default: mode |= R128_AGP_1X_MODE;
+ }
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ info->PciInfo->vendor,
+ info->PciInfo->chipType);
+
+ if (drmAgpEnable(info->drmFD, mode) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+
+ info->agpOffset = 0;
+
+ if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL,
+ &info->agpMemHandle)) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->agpMemHandle);
+
+ if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
+ drmAgpFree(info->drmFD, info->agpMemHandle);
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+
+ /* Initialize the CCE ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ /* Reserve the rest for AGP textures */
+ info->agpTexStart = info->bufStart + info->bufMapSize;
+ s = (info->agpSize*1024*1024 - info->agpTexStart);
+ l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+ info->agpTexMapSize = (s >> l) << l;
+ info->log2AGPTexGran = l;
+
+ if (info->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
+ DRM_AGP, flags, &info->ringHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+
+ if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring read ptr mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map ring read ptr\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+
+ if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
+ DRM_AGP, 0, &info->bufHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add vertex/indirect buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map vertex/indirect buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+
+ if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize,
+ DRM_AGP, 0, &info->agpTexHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add AGP texture map mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP texture map handle = 0x%08lx\n",
+ info->agpTexHandle);
+
+ if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize,
+ (drmAddressPtr)&info->agpTex) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map AGP texture map\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP Texture map mapped at 0x%08lx\n",
+ (unsigned long)info->agpTex);
+
+ /* Initialize Rage 128's AGP registers */
+ cntl = INREG(R128_AGP_CNTL);
+ cntl &= ~R128_AGP_APER_SIZE_MASK;
+ switch (info->agpSize) {
+ case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
+ case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
+ case 64: cntl |= R128_AGP_APER_SIZE_64MB; break;
+ case 32: cntl |= R128_AGP_APER_SIZE_32MB; break;
+ case 16: cntl |= R128_AGP_APER_SIZE_16MB; break;
+ case 8: cntl |= R128_AGP_APER_SIZE_8MB; break;
+ case 4: cntl |= R128_AGP_APER_SIZE_4MB; break;
+ default:
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Illegal aperture size %d kB\n",
+ info->agpSize*1024);
+ return FALSE;
+ }
+ agpBase = drmAgpBase(info->drmFD);
+ OUTREG(R128_AGP_BASE, agpBase);
+ OUTREG(R128_AGP_CNTL, cntl);
+
+ /* Disable Rage 128's PCIGART registers */
+ chunk = INREG(R128_BM_CHUNK_0_VAL);
+ chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
+ R128_BM_PM4_RD_FORCE_TO_PCI |
+ R128_BM_GLOBAL_FORCE_TO_PCI);
+ OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+
+ OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
+
+ return TRUE;
+}
+
+static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 chunk;
+ int ret;
+ int flags;
+
+ info->agpOffset = 0;
+
+ ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024,
+ &info->pciMemHandle);
+ if (ret < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->pciMemHandle);
+
+ /* Initialize the CCE ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
+
+ if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add ring mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->ring);
+
+ if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add ring read ptr mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not map ring read ptr\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring read ptr contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->ringReadPtr);
+
+ if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
+ DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add vertex/indirect buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not map vertex/indirect buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Vertex/indirect buffers contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->buf);
+
+ switch (info->Chipset) {
+ case PCI_CHIP_RAGE128LE:
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RK:
+ case PCI_CHIP_RAGE128PD:
+ case PCI_CHIP_RAGE128PP:
+ case PCI_CHIP_RAGE128PR:
+ /* This is a PCI card, do nothing */
+ break;
+
+ case PCI_CHIP_RAGE128LF:
+ case PCI_CHIP_RAGE128MF:
+ case PCI_CHIP_RAGE128ML:
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RG:
+ case PCI_CHIP_RAGE128RL:
+ case PCI_CHIP_RAGE128SM:
+ case PCI_CHIP_RAGE128PF:
+ case PCI_CHIP_RAGE128TF:
+ case PCI_CHIP_RAGE128TL:
+ case PCI_CHIP_RAGE128TR:
+ /* FIXME: ATI documentation does not specify if the following chips are
+ * AGP or PCI, it just mentions their PCI IDs. I'm assuming they're AGP
+ * until I get more correct information. <mharris@redhat.com>
+ */
+ case PCI_CHIP_RAGE128PA:
+ case PCI_CHIP_RAGE128PB:
+ case PCI_CHIP_RAGE128PC:
+ case PCI_CHIP_RAGE128PE:
+ case PCI_CHIP_RAGE128PG:
+ case PCI_CHIP_RAGE128PH:
+ case PCI_CHIP_RAGE128PI:
+ case PCI_CHIP_RAGE128PJ:
+ case PCI_CHIP_RAGE128PK:
+ case PCI_CHIP_RAGE128PL:
+ case PCI_CHIP_RAGE128PM:
+ case PCI_CHIP_RAGE128PN:
+ case PCI_CHIP_RAGE128PO:
+ case PCI_CHIP_RAGE128PQ:
+ case PCI_CHIP_RAGE128PS:
+ case PCI_CHIP_RAGE128PT:
+ case PCI_CHIP_RAGE128PU:
+ case PCI_CHIP_RAGE128PV:
+ case PCI_CHIP_RAGE128PW:
+ case PCI_CHIP_RAGE128PX:
+ case PCI_CHIP_RAGE128SE:
+ case PCI_CHIP_RAGE128SF:
+ case PCI_CHIP_RAGE128SG:
+ case PCI_CHIP_RAGE128SH:
+ case PCI_CHIP_RAGE128SK:
+ case PCI_CHIP_RAGE128SL:
+ case PCI_CHIP_RAGE128SN:
+ case PCI_CHIP_RAGE128TS:
+ case PCI_CHIP_RAGE128TT:
+ case PCI_CHIP_RAGE128TU:
+ default:
+ /* This is really an AGP card, force PCI GART mode */
+ chunk = INREG(R128_BM_CHUNK_0_VAL);
+ chunk |= (R128_BM_PTR_FORCE_TO_PCI |
+ R128_BM_PM4_RD_FORCE_TO_PCI |
+ R128_BM_GLOBAL_FORCE_TO_PCI);
+ OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+ OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
+ break;
+ }
+
+ return TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+ DRI-based clients. */
+static Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ int flags;
+
+ if (info->CCESecure) flags = DRM_READ_ONLY;
+ else flags = 0;
+
+ /* Map registers */
+ info->registerSize = R128_MMIOSIZE;
+ if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
+ DRM_REGISTERS, flags, &info->registerHandle) < 0) {
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] register handle = 0x%08lx\n", info->registerHandle);
+
+ return TRUE;
+}
+
+/* Initialize the kernel data structures. */
+static int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ drmR128Init drmInfo;
+
+ memset( &drmInfo, 0, sizeof(drmR128Init) );
+
+ drmInfo.func = DRM_R128_INIT_CCE;
+ drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ drmInfo.is_pci = info->IsPCI;
+ drmInfo.cce_mode = info->CCEMode;
+ drmInfo.cce_secure = info->CCESecure;
+ drmInfo.ring_size = info->ringSize*1024*1024;
+ drmInfo.usec_timeout = info->CCEusecTimeout;
+
+ drmInfo.fb_bpp = info->CurrentLayout.pixel_code;
+ drmInfo.depth_bpp = info->CurrentLayout.pixel_code;
+
+ drmInfo.front_offset = info->frontOffset;
+ drmInfo.front_pitch = info->frontPitch;
+
+ drmInfo.back_offset = info->backOffset;
+ drmInfo.back_pitch = info->backPitch;
+
+ drmInfo.depth_offset = info->depthOffset;
+ drmInfo.depth_pitch = info->depthPitch;
+ drmInfo.span_offset = info->spanOffset;
+
+ drmInfo.fb_offset = info->fbHandle;
+ drmInfo.mmio_offset = info->registerHandle;
+ drmInfo.ring_offset = info->ringHandle;
+ drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
+ drmInfo.buffers_offset = info->bufHandle;
+ drmInfo.agp_textures_offset = info->agpTexHandle;
+
+ if (drmCommandWrite(info->drmFD, DRM_R128_INIT,
+ &drmInfo, sizeof(drmR128Init)) < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Add a map for the vertex buffers that will be accessed by any
+ DRI-based clients. */
+static Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ /* Initialize vertex buffers */
+ if (info->IsPCI) {
+ info->bufNumBufs = drmAddBufs(info->drmFD,
+ info->bufMapSize / R128_BUFFER_SIZE,
+ R128_BUFFER_SIZE,
+ DRM_SG_BUFFER,
+ info->bufStart);
+ } else {
+ info->bufNumBufs = drmAddBufs(info->drmFD,
+ info->bufMapSize / R128_BUFFER_SIZE,
+ R128_BUFFER_SIZE,
+ DRM_AGP_BUFFER,
+ info->bufStart);
+ }
+ if (info->bufNumBufs <= 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Could not create vertex/indirect buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Added %d %d byte vertex/indirect buffers\n",
+ info->bufNumBufs, R128_BUFFER_SIZE);
+
+ if (!(info->buffers = drmMapBufs(info->drmFD))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to map vertex/indirect buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Mapped %d vertex/indirect buffers\n",
+ info->buffers->count);
+
+ return TRUE;
+}
+
+static void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (!info->irq) {
+ info->irq = drmGetInterruptFromBusID(
+ info->drmFD,
+ ((pciConfigPtr)info->PciInfo->thisCard)->busnum,
+ ((pciConfigPtr)info->PciInfo->thisCard)->devnum,
+ ((pciConfigPtr)info->PciInfo->thisCard)->funcnum);
+
+ if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding irq handler, "
+ "there is a device already using that irq\n"
+ "[drm] falling back to irq-free operation\n");
+ info->irq = 0;
+ } else {
+ unsigned char *R128MMIO = info->MMIO;
+ info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
+ }
+ }
+
+ if (info->irq)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n",
+ info->irq);
+}
+
+/* Initialize the CCE state, and start the CCE (if used by the X server) */
+static void R128DRICCEInit(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ /* Turn on bus mastering */
+ info->BusCntl &= ~R128_BUS_MASTER_DIS;
+
+ /* CCEMode is initialized in r128_driver.c */
+ switch (info->CCEMode) {
+ case R128_PM4_NONPM4: info->CCEFifoSize = 0; break;
+ case R128_PM4_192PIO: info->CCEFifoSize = 192; break;
+ case R128_PM4_192BM: info->CCEFifoSize = 192; break;
+ case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break;
+ case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
+ case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break;
+ }
+
+ if (info->directRenderingEnabled) {
+ /* Make sure the CCE is on for the X server */
+ R128CCE_START(pScrn, info);
+ } else {
+ /* Make sure the CCE is off for the X server */
+ R128CCE_STOP(pScrn, info);
+ }
+}
+
+/* Initialize the screen-specific data structures for the DRI and the
+ Rage 128. This is the main entry point to the device-specific
+ initialization code. It calls device-independent DRI functions to
+ create the DRI data structures and initialize the DRI state. */
+Bool R128DRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ R128DRIPtr pR128DRI;
+ int major, minor, patch;
+ drmVersionPtr version;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module. */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ major, minor, patch);
+ return FALSE;
+ }
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8:
+ /* These modes are not supported (yet). */
+ case 15:
+ case 24:
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed (depth %d not supported). "
+ "[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code);
+ return FALSE;
+
+ /* Only 16 and 32 color depths are supports currently. */
+ case 16:
+ case 32:
+ break;
+ }
+
+ /* Create the DRI data structure, and fill it in before calling the
+ DRIScreenInit(). */
+ if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
+
+ info->pDRIInfo = pDRIInfo;
+ pDRIInfo->drmDriverName = R128_DRIVER_NAME;
+ pDRIInfo->clientDriverName = R128_DRIVER_NAME;
+ pDRIInfo->busIdString = xalloc(64);
+ sprintf(pDRIInfo->busIdString,
+ "PCI:%d:%d:%d",
+ info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+ pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH;
+ pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr;
+ pDRIInfo->frameBufferSize = info->FbMapSize;
+ pDRIInfo->frameBufferStride = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ pDRIInfo->ddxDrawableTableEntry = R128_MAX_DRAWABLES;
+ pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES
+ < R128_MAX_DRAWABLES
+ ? SAREA_MAX_DRAWABLES
+ : R128_MAX_DRAWABLES);
+
+#ifdef NOT_DONE
+ /* FIXME: Need to extend DRI protocol to pass this size back to
+ * client for SAREA mapping that includes a device private record
+ */
+ pDRIInfo->SAREASize =
+ ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
+ /* + shared memory device private rec */
+#else
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] Data does not fit in SAREA. Disabling DRI.\n");
+ return FALSE;
+ }
+ pDRIInfo->SAREASize = SAREA_MAX;
+#endif
+
+ if (!(pR128DRI = (R128DRIPtr)xcalloc(sizeof(R128DRIRec),1))) {
+ DRIDestroyInfoRec(info->pDRIInfo);
+ info->pDRIInfo = NULL;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pR128DRI;
+ pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
+ pDRIInfo->contextSize = sizeof(R128DRIContextRec);
+
+ pDRIInfo->CreateContext = R128CreateContext;
+ pDRIInfo->DestroyContext = R128DestroyContext;
+ pDRIInfo->SwapContext = R128DRISwapContext;
+ pDRIInfo->InitBuffers = R128DRIInitBuffers;
+ pDRIInfo->MoveBuffers = R128DRIMoveBuffers;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pDRIInfo);
+ pDRIInfo = NULL;
+ return FALSE;
+ }
+
+ /* Check the DRM lib version.
+ drmGetLibVersion was not supported in version 1.0, so check for
+ symbol first to avoid possible crash or hang.
+ */
+ if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
+ version = drmGetLibVersion(info->drmFD);
+ }
+ else {
+ /* drmlib version 1.0.0 didn't have the drmGetLibVersion
+ entry point. Fake it by allocating a version record
+ via drmGetVersion and changing it to version 1.0.0
+ */
+ version = drmGetVersion(info->drmFD);
+ version->version_major = 1;
+ version->version_minor = 0;
+ version->version_patchlevel = 0;
+ }
+
+ if (version) {
+ if (version->version_major != 1 ||
+ version->version_minor < 1) {
+ /* incompatible drm library version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Check the r128 DRM version */
+ version = drmGetVersion(info->drmFD);
+ if (version) {
+ if (version->version_major != 2 ||
+ version->version_minor < 2) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Initialize AGP */
+ if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) {
+ info->IsPCI = TRUE;
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[agp] Make sure you have the agpgart kernel module loaded.\n");
+ }
+
+ /* Initialize PCIGART */
+ if (info->IsPCI && !R128DRIPciInit(info, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* DRIScreenInit doesn't add all the
+ common mappings. Add additional
+ mappings here. */
+ if (!R128DRIMapInit(info, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* DRIScreenInit adds the frame buffer
+ map, but we need it as well */
+ {
+ void *scratch_ptr;
+ int scratch_int;
+
+ DRIGetDeviceInfo(pScreen, &info->fbHandle,
+ &scratch_int, &scratch_int,
+ &scratch_int, &scratch_int,
+ &scratch_ptr);
+ }
+
+ /* FIXME: When are these mappings unmapped? */
+
+ if (!R128InitVisualConfigs(pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
+
+ return TRUE;
+}
+
+/* Finish initializing the device-dependent DRI state, and call
+ DRIFinishScreenInit() to complete the device-independent DRI
+ initialization. */
+Bool R128DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ R128SAREAPrivPtr pSAREAPriv;
+ R128DRIPtr pR128DRI;
+
+ info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+ /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
+
+ /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
+ because *DRIKernelInit requires that the hardware lock is held by
+ the X server, and the first time the hardware lock is grabbed is
+ in DRIFinishScreenInit. */
+ if (!DRIFinishScreenInit(pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize the kernel data structures */
+ if (!R128DRIKernelInit(info, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize the vertex buffers list */
+ if (!R128DRIBufInit(info, pScreen)) {
+ R128DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize IRQ */
+ R128DRIIrqInit(info, pScreen);
+
+ /* Initialize and start the CCE if required */
+ R128DRICCEInit(pScrn);
+
+ pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+ pR128DRI = (R128DRIPtr)info->pDRIInfo->devPrivate;
+
+ pR128DRI->deviceID = info->Chipset;
+ pR128DRI->width = pScrn->virtualX;
+ pR128DRI->height = pScrn->virtualY;
+ pR128DRI->depth = pScrn->depth;
+ pR128DRI->bpp = pScrn->bitsPerPixel;
+
+ pR128DRI->IsPCI = info->IsPCI;
+ pR128DRI->AGPMode = info->agpMode;
+
+ pR128DRI->frontOffset = info->frontOffset;
+ pR128DRI->frontPitch = info->frontPitch;
+ pR128DRI->backOffset = info->backOffset;
+ pR128DRI->backPitch = info->backPitch;
+ pR128DRI->depthOffset = info->depthOffset;
+ pR128DRI->depthPitch = info->depthPitch;
+ pR128DRI->spanOffset = info->spanOffset;
+ pR128DRI->textureOffset = info->textureOffset;
+ pR128DRI->textureSize = info->textureSize;
+ pR128DRI->log2TexGran = info->log2TexGran;
+
+ pR128DRI->registerHandle = info->registerHandle;
+ pR128DRI->registerSize = info->registerSize;
+
+ pR128DRI->agpTexHandle = info->agpTexHandle;
+ pR128DRI->agpTexMapSize = info->agpTexMapSize;
+ pR128DRI->log2AGPTexGran = info->log2AGPTexGran;
+ pR128DRI->agpTexOffset = info->agpTexStart;
+ pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ return TRUE;
+}
+
+/* The screen is being closed, so clean up any state and free any
+ resources used by the DRI. */
+void R128DRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ drmR128Init drmInfo;
+
+ /* Stop the CCE if it is still in use */
+ if (info->directRenderingEnabled) {
+ R128CCE_STOP(pScrn, info);
+ }
+
+ if (info->irq) {
+ drmCtlUninstHandler(info->drmFD);
+ info->irq = 0;
+ }
+
+ /* De-allocate vertex buffers */
+ if (info->buffers) {
+ drmUnmapBufs(info->buffers);
+ info->buffers = NULL;
+ }
+
+ /* De-allocate all kernel resources */
+ memset(&drmInfo, 0, sizeof(drmR128Init));
+ drmInfo.func = DRM_R128_CLEANUP_CCE;
+ drmCommandWrite(info->drmFD, DRM_R128_INIT,
+ &drmInfo, sizeof(drmR128Init));
+
+ /* De-allocate all AGP resources */
+ if (info->agpTex) {
+ drmUnmap(info->agpTex, info->agpTexMapSize);
+ info->agpTex = NULL;
+ }
+ if (info->buf) {
+ drmUnmap(info->buf, info->bufMapSize);
+ info->buf = NULL;
+ }
+ if (info->ringReadPtr) {
+ drmUnmap(info->ringReadPtr, info->ringReadMapSize);
+ info->ringReadPtr = NULL;
+ }
+ if (info->ring) {
+ drmUnmap(info->ring, info->ringMapSize);
+ info->ring = NULL;
+ }
+ if (info->agpMemHandle) {
+ drmAgpUnbind(info->drmFD, info->agpMemHandle);
+ drmAgpFree(info->drmFD, info->agpMemHandle);
+ info->agpMemHandle = 0;
+ drmAgpRelease(info->drmFD);
+ }
+ if (info->pciMemHandle) {
+ drmScatterGatherFree(info->drmFD, info->pciMemHandle);
+ info->pciMemHandle = 0;
+ }
+
+ /* De-allocate all DRI resources */
+ DRICloseScreen(pScreen);
+
+ /* De-allocate all DRI data structures */
+ if (info->pDRIInfo) {
+ if (info->pDRIInfo->devPrivate) {
+ xfree(info->pDRIInfo->devPrivate);
+ info->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(info->pDRIInfo);
+ info->pDRIInfo = NULL;
+ }
+ if (info->pVisualConfigs) {
+ xfree(info->pVisualConfigs);
+ info->pVisualConfigs = NULL;
+ }
+ if (info->pVisualConfigsPriv) {
+ xfree(info->pVisualConfigsPriv);
+ info->pVisualConfigsPriv = NULL;
+ }
+}
diff --git a/src/r128_dri.h b/src/r128_dri.h
new file mode 100644
index 0000000..1339a45
--- /dev/null
+++ b/src/r128_dri.h
@@ -0,0 +1,102 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.h,v 1.7 2002/10/30 12:52:12 alanh Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Rickard E. Faith <faith@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_DRI_
+#define _R128_DRI_
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+/* DRI Driver defaults */
+#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM
+#define R128_DEFAULT_CCE_BM_MODE R128_PM4_64BM_64VCBM_64INDBM
+#define R128_DEFAULT_AGP_MODE 1
+#define R128_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */
+#define R128_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
+#define R128_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */
+#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
+
+#define R128_DEFAULT_CCE_TIMEOUT 10000 /* usecs */
+
+#define R128_AGP_MAX_MODE 4
+
+#define R128_CARD_TYPE_R128 1
+#define R128_CARD_TYPE_R128_PRO 2
+#define R128_CARD_TYPE_R128_MOBILITY 3
+
+#define R128CCE_USE_RING_BUFFER(m) \
+(((m) == R128_PM4_192BM) || \
+ ((m) == R128_PM4_128BM_64INDBM) || \
+ ((m) == R128_PM4_64BM_128INDBM) || \
+ ((m) == R128_PM4_64BM_64VCBM_64INDBM))
+
+typedef struct {
+ /* DRI screen private data */
+ int deviceID; /* PCI device ID */
+ int width; /* Width in pixels of display */
+ int height; /* Height in scanlines of display */
+ int depth; /* Depth of display (8, 15, 16, 24) */
+ int bpp; /* Bit depth of display (8, 16, 24, 32) */
+
+ int IsPCI; /* Current card is a PCI card */
+ int AGPMode;
+
+ int frontOffset; /* Start of front buffer */
+ int frontPitch;
+ int backOffset; /* Start of shared back buffer */
+ int backPitch;
+ int depthOffset; /* Start of shared depth buffer */
+ int depthPitch;
+ int spanOffset; /* Start of scratch spanline */
+ int textureOffset;/* Start of texture data in frame buffer */
+ int textureSize;
+ int log2TexGran;
+
+ /* MMIO register data */
+ drmHandle registerHandle;
+ drmSize registerSize;
+
+ /* CCE AGP Texture data */
+ drmHandle agpTexHandle;
+ drmSize agpTexMapSize;
+ int log2AGPTexGran;
+ int agpTexOffset;
+ unsigned int sarea_priv_offset;
+} R128DRIRec, *R128DRIPtr;
+
+#endif
diff --git a/src/r128_dripriv.h b/src/r128_dripriv.h
new file mode 100644
index 0000000..7f84987
--- /dev/null
+++ b/src/r128_dripriv.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dripriv.h,v 1.3 2000/11/18 19:37:11 tsi Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef _R128_DRIPRIV_H_
+#define _R128_DRIPRIV_H_
+
+#include "GL/glxint.h"
+
+#define R128_MAX_DRAWABLES 256
+
+extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
+ void **configprivs);
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} R128ConfigPrivRec, *R128ConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} R128DRIContextRec, *R128DRIContextPtr;
+
+#endif
diff --git a/src/r128_driver.c b/src/r128_driver.c
new file mode 100644
index 0000000..271c2fb
--- /dev/null
+++ b/src/r128_driver.c
@@ -0,0 +1,3724 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v 1.75 2003/02/19 01:19:41 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * Credits:
+ *
+ * Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for
+ * providing source code to their 3.3.x Rage 128 driver. Portions of
+ * this file are based on the initialization code for that driver.
+ *
+ * References:
+ *
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ * This server does not yet support these XFree86 4.0 features:
+ * DDC1 & DDC2
+ * shadowfb
+ * overlay planes
+ *
+ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
+ */
+
+
+ /* Driver data structures */
+#include "r128.h"
+#include "r128_probe.h"
+#include "r128_reg.h"
+#include "r128_version.h"
+
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "r128_dri.h"
+#include "r128_sarea.h"
+#endif
+
+#define USE_FB /* not until overlays */
+#ifdef USE_FB
+#include "fb.h"
+#else
+
+ /* CFB support */
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb24.h"
+#include "cfb32.h"
+#include "cfb24_32.h"
+#endif
+
+ /* colormap initialization */
+#include "micmap.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86PciInfo.h"
+#include "xf86RAC.h"
+#include "xf86Resources.h"
+#include "xf86cmap.h"
+#include "xf86xv.h"
+#include "vbe.h"
+
+ /* fbdevhw & vgahw */
+#include "fbdevhw.h"
+#include "vgaHW.h"
+#include "dixstruct.h"
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#define USE_CRT_ONLY 0
+
+ /* Forward definitions for driver functions */
+static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool R128SaveScreen(ScreenPtr pScreen, int mode);
+static void R128Save(ScrnInfoPtr pScrn);
+static void R128Restore(ScrnInfoPtr pScrn);
+static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags);
+static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags);
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_DAC_6BIT,
+ OPTION_DAC_8BIT,
+#ifdef XF86DRI
+ OPTION_XV_DMA,
+ OPTION_IS_PCI,
+ OPTION_CCE_PIO,
+ OPTION_NO_SECURITY,
+ OPTION_USEC_TIMEOUT,
+ OPTION_AGP_MODE,
+ OPTION_AGP_SIZE,
+ OPTION_RING_SIZE,
+ OPTION_BUFFER_SIZE,
+#endif
+#if USE_CRT_ONLY
+ /* FIXME: Disable CRTOnly until it is tested */
+ OPTION_CRT,
+#endif
+ OPTION_DISPLAY,
+ OPTION_PANEL_WIDTH,
+ OPTION_PANEL_HEIGHT,
+ OPTION_PROG_FP_REGS,
+ OPTION_FBDEV,
+ OPTION_VIDEO_KEY,
+ OPTION_SHOW_CACHE
+} R128Opts;
+
+const OptionInfoRec R128Options[] = {
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE },
+#ifdef XF86DRI
+ { OPTION_XV_DMA, "DMAForXv", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CCE_PIO, "CCEPIOMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NO_SECURITY, "CCENoSecurity", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_USEC_TIMEOUT, "CCEusecTimeout", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE },
+#endif
+ { OPTION_DISPLAY, "Display", OPTV_STRING, {0}, FALSE },
+ { OPTION_PANEL_WIDTH, "PanelWidth", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_PANEL_HEIGHT, "PanelHeight", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_PROG_FP_REGS, "ProgramFPRegs", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+R128RAMRec R128RAM[] = { /* Memory Specifications
+ From RAGE 128 Software Development
+ Manual (Technical Reference Manual P/N
+ SDK-G04000 Rev 0.01), page 3-21. */
+ { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
+ { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
+ { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
+ { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
+};
+
+static const char *vgahwSymbols[] = {
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIndex",
+ "vgaHWLock",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWUnlock",
+ NULL
+};
+
+static const char *fbdevHWSymbols[] = {
+ "fbdevHWInit",
+ "fbdevHWUseBuildinMode",
+ "fbdevHWGetLineLength",
+ "fbdevHWGetVidmem",
+
+ "fbdevHWDPMSSet",
+
+ /* colormap */
+ "fbdevHWLoadPalette",
+
+ /* ScrnInfo hooks */
+ "fbdevHWAdjustFrame",
+ "fbdevHWEnterVT",
+ "fbdevHWLeaveVT",
+ "fbdevHWModeInit",
+ "fbdevHWRestore",
+ "fbdevHWSave",
+ "fbdevHWSwitchMode",
+ "fbdevHWValidMode",
+
+ "fbdevHWMapMMIO",
+ "fbdevHWMapVidmem",
+ "fbdevHWUnmapMMIO",
+ "fbdevHWUnmapVidmem",
+
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+#ifdef USE_FB
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+#else
+static const char *cfbSymbols[] = {
+ "cfbScreenInit",
+ "cfb16ScreenInit",
+ "cfb24ScreenInit",
+ "cfb32ScreenInit",
+ "cfb24_32ScreenInit",
+ NULL
+};
+#endif
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAgpAcquire",
+ "drmAgpAlloc",
+ "drmAgpBind",
+ "drmAgpDeviceId",
+ "drmAgpEnable",
+ "drmAgpFree",
+ "drmAgpGetMode",
+ "drmAgpRelease",
+ "drmAgpUnbind",
+ "drmAgpVendorId",
+ "drmAvailable",
+ "drmCommandNone",
+ "drmCommandRead",
+ "drmCommandWrite",
+ "drmCommandWriteRead",
+ "drmFreeBufs",
+ "drmFreeVersion",
+ "drmGetLibVersion",
+ "drmGetVersion",
+ "drmMap",
+ "drmMapBufs",
+ "drmDMA",
+ "drmScatterGatherAlloc",
+ "drmScatterGatherFree",
+ "drmUnmap",
+ "drmUnmapBufs",
+ NULL
+};
+
+static const char *driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ NULL
+};
+#endif
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86InitInt10",
+ "xf86FreeInt10",
+ "xf86int10Addr",
+ NULL
+};
+
+void R128LoaderRefSymLists(void)
+{
+ /*
+ * Tell the loader about symbols from other modules that this module might
+ * refer to.
+ */
+ xf86LoaderRefSymLists(vgahwSymbols,
+#ifdef USE_FB
+ fbSymbols,
+#else
+ cfbSymbols,
+#endif
+ xaaSymbols,
+ ramdacSymbols,
+#ifdef XF86DRI
+ drmSymbols,
+ driSymbols,
+#endif
+ fbdevHWSymbols,
+ int10Symbols,
+ vbeSymbols,
+ /* ddcsymbols, */
+ i2cSymbols,
+ /* shadowSymbols, */
+ NULL);
+}
+
+/* Allocate our private R128InfoRec. */
+static Bool R128GetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate) return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
+ return TRUE;
+}
+
+/* Free our private R128InfoRec. */
+static void R128FreeRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn || !pScrn->driverPrivate) return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+/* Memory map the MMIO region. Used during pre-init and by R128MapMem,
+ below. */
+static Bool R128MapMMIO(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->FBDev) {
+ info->MMIO = fbdevHWMapMMIO(pScrn);
+ } else {
+ info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
+ info->PciTag,
+ info->MMIOAddr,
+ R128_MMIOSIZE);
+ }
+
+ if (!info->MMIO) return FALSE;
+ return TRUE;
+}
+
+/* Unmap the MMIO region. Used during pre-init and by R128UnmapMem,
+ below. */
+static Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->FBDev)
+ fbdevHWUnmapMMIO(pScrn);
+ else {
+ xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
+ }
+ info->MMIO = NULL;
+ return TRUE;
+}
+
+/* Memory map the frame buffer. Used by R128MapMem, below. */
+static Bool R128MapFB(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->FBDev) {
+ info->FB = fbdevHWMapVidmem(pScrn);
+ } else {
+ info->FB = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_FRAMEBUFFER,
+ info->PciTag,
+ info->LinearAddr,
+ info->FbMapSize);
+ }
+
+ if (!info->FB) return FALSE;
+ return TRUE;
+}
+
+/* Unmap the frame buffer. Used by R128UnmapMem, below. */
+static Bool R128UnmapFB(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (info->FBDev)
+ fbdevHWUnmapVidmem(pScrn);
+ else
+ xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
+ info->FB = NULL;
+ return TRUE;
+}
+
+/* Memory map the MMIO region and the frame buffer. */
+static Bool R128MapMem(ScrnInfoPtr pScrn)
+{
+ if (!R128MapMMIO(pScrn)) return FALSE;
+ if (!R128MapFB(pScrn)) {
+ R128UnmapMMIO(pScrn);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Unmap the MMIO region and the frame buffer. */
+static Bool R128UnmapMem(ScrnInfoPtr pScrn)
+{
+ if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
+ return TRUE;
+}
+
+/* Read PLL information */
+unsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return INREG(R128_CLOCK_CNTL_DATA);
+}
+
+#if 0
+/* Read PAL information (only used for debugging). */
+static int R128INPAL(int idx)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG(R128_PALETTE_INDEX, idx << 16);
+ return INREG(R128_PALETTE_DATA);
+}
+#endif
+
+/* Wait for vertical sync. */
+void R128WaitForVerticalSync(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
+ for (i = 0; i < R128_TIMEOUT; i++) {
+ if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
+ }
+}
+
+/* Blank screen. */
+static void R128Blank(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ if(info->isDFP)
+ OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS);
+ else
+ OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS);
+}
+
+/* Unblank screen. */
+static void R128Unblank(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ if(info->isDFP)
+ OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS);
+ else
+ OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS);
+}
+
+/* Compute log base 2 of val. */
+int R128MinBits(int val)
+{
+ int bits;
+
+ if (!val) return 1;
+ for (bits = 0; val; val >>= 1, ++bits);
+ return bits;
+}
+
+/* Compute n/d with rounding. */
+static int R128Div(int n, int d)
+{
+ return (n + (d / 2)) / d;
+}
+
+/* Read the Video BIOS block and the FP registers (if applicable). */
+static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int i;
+ int FPHeader = 0;
+
+#define R128_BIOS8(v) (info->VBIOS[v])
+#define R128_BIOS16(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8))
+#define R128_BIOS32(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8) | \
+ (info->VBIOS[(v) + 2] << 16) | \
+ (info->VBIOS[(v) + 3] << 24))
+
+ if (!(info->VBIOS = xalloc(R128_VBIOS_SIZE))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Cannot allocate space for hold Video BIOS!\n");
+ return FALSE;
+ }
+
+ if (pInt10) {
+ info->BIOSAddr = pInt10->BIOSseg << 4;
+ (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
+ R128_VBIOS_SIZE);
+ } else {
+ xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected in PCI space!\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Attempting to read Video BIOS from legacy ISA space!\n");
+ info->BIOSAddr = 0x000c0000;
+ xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
+ }
+ }
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ info->BIOSAddr = 0x00000000;
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not found!\n");
+ }
+
+ if (info->VBIOS && info->HasPanelRegs) {
+ info->FPBIOSstart = 0;
+
+ /* FIXME: There should be direct access to the start of the FP info
+ tables, but until we find out where that offset is stored, we
+ must search for the ATI signature string: "M3 ". */
+ for (i = 4; i < R128_VBIOS_SIZE-8; i++) {
+ if (R128_BIOS8(i) == 'M' &&
+ R128_BIOS8(i+1) == '3' &&
+ R128_BIOS8(i+2) == ' ' &&
+ R128_BIOS8(i+3) == ' ' &&
+ R128_BIOS8(i+4) == ' ' &&
+ R128_BIOS8(i+5) == ' ' &&
+ R128_BIOS8(i+6) == ' ' &&
+ R128_BIOS8(i+7) == ' ') {
+ FPHeader = i-2;
+ break;
+ }
+ }
+
+ if (!FPHeader) return TRUE;
+
+ /* Assume that only one panel is attached and supported */
+ for (i = FPHeader+20; i < FPHeader+84; i += 2) {
+ if (R128_BIOS16(i) != 0) {
+ info->FPBIOSstart = R128_BIOS16(i);
+ break;
+ }
+ }
+ if (!info->FPBIOSstart) return TRUE;
+
+ if (!info->PanelXRes)
+ info->PanelXRes = R128_BIOS16(info->FPBIOSstart+25);
+ if (!info->PanelYRes)
+ info->PanelYRes = R128_BIOS16(info->FPBIOSstart+27);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
+ info->PanelXRes, info->PanelYRes);
+
+ info->PanelPwrDly = R128_BIOS8(info->FPBIOSstart+56);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
+ for (i = 1; i <= 24; i++)
+ ErrorF("%c", R128_BIOS8(info->FPBIOSstart+i));
+ ErrorF("\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
+ i = R128_BIOS16(info->FPBIOSstart+29);
+ if (i & 1) ErrorF("Color, ");
+ else ErrorF("Monochrome, ");
+ if (i & 2) ErrorF("Dual(split), ");
+ else ErrorF("Single, ");
+ switch ((i >> 2) & 0x3f) {
+ case 0: ErrorF("STN"); break;
+ case 1: ErrorF("TFT"); break;
+ case 2: ErrorF("Active STN"); break;
+ case 3: ErrorF("EL"); break;
+ case 4: ErrorF("Plasma"); break;
+ default: ErrorF("UNKNOWN"); break;
+ }
+ ErrorF("\n");
+ if (R128_BIOS8(info->FPBIOSstart+61) & 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
+ } else {
+ /* FIXME: Add Non-LVDS flat pael support */
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Non-LVDS panel interface detected! "
+ "This support is untested and may not "
+ "function properly\n");
+ }
+ }
+
+ if (!info->PanelXRes || !info->PanelYRes) {
+ info->HasPanelRegs = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Can't determine panel dimensions, and none specified. \
+ Disabling programming of FP registers.\n");
+ }
+
+ return TRUE;
+}
+
+/* Read PLL parameters from BIOS block. Default to typical values if there
+ is no BIOS. */
+static Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ R128PLLPtr pll = &info->pll;
+
+#if defined(__powerpc__) || defined(__alpha__)
+ /* there is no bios under Linux PowerPC but Open Firmware
+ does set up the PLL registers properly and we can use
+ those to calculate xclk and find the reference divider */
+
+ unsigned x_mpll_ref_fb_div;
+ unsigned xclk_cntl;
+ unsigned Nx, M;
+ unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
+
+ /* Assume REF clock is 2950 (in units of 10khz) */
+ /* and that all pllclk must be between 125 Mhz and 250Mhz */
+ pll->reference_freq = 2950;
+ pll->min_pll_freq = 12500;
+ pll->max_pll_freq = 25000;
+
+ /* need to memory map the io to use INPLL since it
+ has not been done yet at this point in the startup */
+ R128MapMMIO(pScrn);
+ x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
+ xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
+ pll->reference_div =
+ INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
+ /* unmap it again */
+ R128UnmapMMIO(pScrn);
+
+ Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
+ M = (x_mpll_ref_fb_div & 0x0000FF);
+
+ pll->xclk = R128Div((2 * Nx * pll->reference_freq),
+ (M * PostDivSet[xclk_cntl]));
+
+#else /* !defined(__powerpc__) */
+
+ if (!info->VBIOS) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected, using default PLL parameters!\n");
+ /* These probably aren't going to work for
+ the card you are using. Specifically,
+ reference freq can be 29.50MHz,
+ 28.63MHz, or 14.32MHz. YMMV. */
+ pll->reference_freq = 2950;
+ pll->reference_div = 65;
+ pll->min_pll_freq = 12500;
+ pll->max_pll_freq = 25000;
+ pll->xclk = 10300;
+ } else {
+ CARD16 bios_header = R128_BIOS16(0x48);
+ CARD16 pll_info_block = R128_BIOS16(bios_header + 0x30);
+ R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
+ bios_header, pll_info_block));
+
+ pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
+ pll->reference_div = R128_BIOS16(pll_info_block + 0x10);
+ pll->min_pll_freq = R128_BIOS32(pll_info_block + 0x12);
+ pll->max_pll_freq = R128_BIOS32(pll_info_block + 0x16);
+ pll->xclk = R128_BIOS16(pll_info_block + 0x08);
+ }
+#endif /* __powerpc__ */
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
+ pll->reference_freq,
+ pll->reference_div,
+ pll->min_pll_freq,
+ pll->max_pll_freq,
+ pll->xclk);
+
+ return TRUE;
+}
+
+/* This is called by R128PreInit to set up the default visual. */
+static Bool R128PreInitVisual(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, (Support24bppFb
+ | Support32bppFb
+ | SupportConvert32to24
+ )))
+ return FALSE;
+
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by %s driver\n",
+ pScrn->depth, R128_DRIVER_NAME);
+ return FALSE;
+ }
+
+ xf86PrintDepthBpp(pScrn);
+
+ info->fifo_slots = 0;
+ info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth);
+ info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
+ info->CurrentLayout.depth = pScrn->depth;
+ info->CurrentLayout.pixel_bytes = pScrn->bitsPerPixel / 8;
+ info->CurrentLayout.pixel_code = (pScrn->bitsPerPixel != 16
+ ? pScrn->bitsPerPixel
+ : pScrn->depth);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
+ pScrn->depth,
+ info->CurrentLayout.pixel_bytes,
+ info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
+ info->pix24bpp);
+
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
+
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Default visual (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+/* This is called by R128PreInit to handle all color weight issues. */
+static Bool R128PreInitWeight(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ /* Save flag for 6 bit DAC to use for
+ setting CRTC registers. Otherwise use
+ an 8 bit DAC, even if xf86SetWeight sets
+ pScrn->rgbBits to some value other than
+ 8. */
+ info->dac6bits = FALSE;
+ if (pScrn->depth > 8) {
+ rgb defaultWeight = { 0, 0, 0 };
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
+ } else {
+ pScrn->rgbBits = 8;
+ if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) {
+ pScrn->rgbBits = 6;
+ info->dac6bits = TRUE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d bits per RGB (%d bit DAC)\n",
+ pScrn->rgbBits, info->dac6bits ? 6 : 8);
+
+ return TRUE;
+
+}
+
+/* This is called by R128PreInit to handle config file overrides for things
+ like chipset and memory regions. Also determine memory size and type.
+ If memory type ever needs an override, put it in this routine. */
+static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ EntityInfoPtr pEnt = info->pEnt;
+ GDevPtr dev = pEnt->device;
+ int offset = 0; /* RAM Type */
+ MessageType from;
+
+ /* Chipset */
+ from = X_PROBED;
+ if (dev->chipset && *dev->chipset) {
+ info->Chipset = xf86StringToToken(R128Chipsets, dev->chipset);
+ from = X_CONFIG;
+ } else if (dev->chipID >= 0) {
+ info->Chipset = dev->chipID;
+ from = X_CONFIG;
+ } else {
+ info->Chipset = info->PciInfo->chipType;
+ }
+ pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
+
+ if (!pScrn->chipset) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04x is not recognized\n", info->Chipset);
+ return FALSE;
+ }
+
+ if (info->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognized\n", pScrn->chipset);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Chipset: \"%s\" (ChipID = 0x%04x)\n",
+ pScrn->chipset,
+ info->Chipset);
+
+ /* Framebuffer */
+
+ from = X_PROBED;
+ info->LinearAddr = info->PciInfo->memBase[0] & 0xfc000000;
+ pScrn->memPhysBase = info->LinearAddr;
+ if (dev->MemBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Linear address override, using 0x%08x instead of 0x%08x\n",
+ dev->MemBase,
+ info->LinearAddr);
+ info->LinearAddr = dev->MemBase;
+ from = X_CONFIG;
+ } else if (!info->LinearAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid linear framebuffer address\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
+
+ /* MMIO registers */
+ from = X_PROBED;
+ info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00;
+ if (dev->IOBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MMIO address override, using 0x%08x instead of 0x%08x\n",
+ dev->IOBase,
+ info->MMIOAddr);
+ info->MMIOAddr = dev->IOBase;
+ from = X_CONFIG;
+ } else if (!info->MMIOAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "MMIO registers at 0x%08lx\n", info->MMIOAddr);
+
+ /* BIOS */
+ from = X_PROBED;
+ info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000;
+ if (dev->BiosBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS address override, using 0x%08x instead of 0x%08x\n",
+ dev->BiosBase,
+ info->BIOSAddr);
+ info->BIOSAddr = dev->BiosBase;
+ from = X_CONFIG;
+ }
+ if (info->BIOSAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "BIOS at 0x%08lx\n", info->BIOSAddr);
+ }
+
+ /* Flat panel (part 1) */
+ if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
+ &info->HasPanelRegs)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Turned flat panel register programming %s\n",
+ info->HasPanelRegs ? "on" : "off");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "\n\nWARNING: Forcing the driver to use/not use the flat panel registers\nmight damage your flat panel. Use at your *OWN* *RISK*.\n\n");
+ } else {
+ info->isDFP = FALSE;
+ info->isPro2 = FALSE;
+ switch (info->Chipset) {
+ /* R128 Pro and Pro2 can have DFP, we will deal with it.
+ No support for dual-head/xinerama yet.
+ M3 can also have DFP, no support for now */
+ case PCI_CHIP_RAGE128TF:
+ case PCI_CHIP_RAGE128TL:
+ case PCI_CHIP_RAGE128TR:
+ /* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
+ * out at the same time, so are of the same family likely.
+ * This requires confirmation however to be fully correct.
+ * Mike A. Harris <mharris@redhat.com>
+ */
+ case PCI_CHIP_RAGE128TS:
+ case PCI_CHIP_RAGE128TT:
+ case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
+ /* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
+ * capability, as the comment at the top suggests.
+ * This requires confirmation however to be fully correct.
+ * Mike A. Harris <mharris@redhat.com>
+ */
+ case PCI_CHIP_RAGE128PA:
+ case PCI_CHIP_RAGE128PB:
+ case PCI_CHIP_RAGE128PC:
+ case PCI_CHIP_RAGE128PE:
+ case PCI_CHIP_RAGE128PG:
+ case PCI_CHIP_RAGE128PH:
+ case PCI_CHIP_RAGE128PI:
+ case PCI_CHIP_RAGE128PJ:
+ case PCI_CHIP_RAGE128PK:
+ case PCI_CHIP_RAGE128PL:
+ case PCI_CHIP_RAGE128PM:
+ case PCI_CHIP_RAGE128PN:
+ case PCI_CHIP_RAGE128PO:
+ case PCI_CHIP_RAGE128PQ:
+ case PCI_CHIP_RAGE128PS:
+ case PCI_CHIP_RAGE128PT:
+ case PCI_CHIP_RAGE128PU:
+ case PCI_CHIP_RAGE128PV:
+ case PCI_CHIP_RAGE128PW:
+ case PCI_CHIP_RAGE128PX:
+
+ case PCI_CHIP_RAGE128PD:
+ case PCI_CHIP_RAGE128PF:
+ case PCI_CHIP_RAGE128PP:
+ case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
+
+ case PCI_CHIP_RAGE128LE:
+ case PCI_CHIP_RAGE128LF:
+ case PCI_CHIP_RAGE128MF:
+ case PCI_CHIP_RAGE128ML: info->HasPanelRegs = TRUE; break;
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RG:
+ case PCI_CHIP_RAGE128RK:
+ case PCI_CHIP_RAGE128RL:
+ case PCI_CHIP_RAGE128SM:
+ /* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
+ * all of them are listed as "Rage 128 4x" in ATI docs.
+ * This requires confirmation however to be fully correct.
+ * Mike A. Harris <mharris@redhat.com>
+ */
+ case PCI_CHIP_RAGE128SE:
+ case PCI_CHIP_RAGE128SF:
+ case PCI_CHIP_RAGE128SG:
+ case PCI_CHIP_RAGE128SH:
+ case PCI_CHIP_RAGE128SK:
+ case PCI_CHIP_RAGE128SL:
+ case PCI_CHIP_RAGE128SN:
+ default: info->HasPanelRegs = FALSE; break;
+ }
+ }
+
+ /* Read registers used to determine options */
+ from = X_PROBED;
+ R128MapMMIO(pScrn);
+ R128MMIO = info->MMIO;
+
+ if (info->FBDev)
+ pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024;
+ else
+ pScrn->videoRam = INREG(R128_CONFIG_MEMSIZE) / 1024;
+
+ info->MemCntl = INREG(R128_MEM_CNTL);
+ info->BusCntl = INREG(R128_BUS_CNTL);
+
+ /* On non-flat panel systems, the default is to display to the CRT,
+ and on flat panel systems, the default is to display to the flat
+ panel unless the user explicity chooses otherwise using the "Display"
+ config file setting. BIOS_5_SCRATCH holds the display device on flat
+ panel systems only. */
+ if (info->HasPanelRegs) {
+ char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY);
+
+ if (info->FBDev)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Option \"Display\" ignored "
+ "(framebuffer device determines display type)\n");
+ else if (!Display || !xf86NameCmp(Display, "FP"))
+ info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
+ else if (!xf86NameCmp(Display, "BIOS"))
+ info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH);
+ else if (!xf86NameCmp(Display, "Mirror"))
+ info->BIOSDisplay = R128_BIOS_DISPLAY_FP_CRT;
+ else if (!xf86NameCmp(Display, "CRT"))
+ info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unsupported type \"%s\" specified for Option \"Display\".\n"
+ "\tSupported types are: "
+ "\"BIOS\", \"Mirror\", \"CRT\" and \"FP\"\n", Display);
+ return FALSE;
+ }
+ } else {
+ info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
+ }
+
+ R128MMIO = NULL;
+ R128UnmapMMIO(pScrn);
+
+ /* RAM */
+ switch (info->MemCntl & 0x3) {
+ case 0: /* SDR SGRAM 1:1 */
+ switch (info->Chipset) {
+ case PCI_CHIP_RAGE128TF:
+ case PCI_CHIP_RAGE128TL:
+ case PCI_CHIP_RAGE128TR:
+ case PCI_CHIP_RAGE128LE:
+ case PCI_CHIP_RAGE128LF:
+ case PCI_CHIP_RAGE128MF:
+ case PCI_CHIP_RAGE128ML:
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
+ case PCI_CHIP_RAGE128RK:
+ case PCI_CHIP_RAGE128RL:
+ case PCI_CHIP_RAGE128SM:
+ default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */
+ }
+ break;
+ case 1: offset = 2; break; /* 64-bit SDR SGRAM 2:1 */
+ case 2: offset = 3; break; /* 64-bit DDR SGRAM */
+ default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */
+ }
+ info->ram = &R128RAM[offset];
+
+ if (dev->videoRam) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Video RAM override, using %d kB instead of %d kB\n",
+ dev->videoRam,
+ pScrn->videoRam);
+ from = X_CONFIG;
+ pScrn->videoRam = dev->videoRam;
+ }
+ pScrn->videoRam &= ~1023;
+ info->FbMapSize = pScrn->videoRam * 1024;
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
+
+ /* Flat panel (part 2) */
+ switch (info->BIOSDisplay) {
+ case R128_BIOS_DISPLAY_FP:
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using flat panel for display\n");
+ break;
+ case R128_BIOS_DISPLAY_CRT:
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using external CRT for display\n");
+ break;
+ case R128_BIOS_DISPLAY_FP_CRT:
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using both flat panel and external CRT "
+ "for display\n");
+ break;
+ }
+
+ if (info->HasPanelRegs) {
+ /* Panel width/height overrides */
+ info->PanelXRes = 0;
+ info->PanelYRes = 0;
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_PANEL_WIDTH, &(info->PanelXRes))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Flat panel width: %d\n", info->PanelXRes);
+ }
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_PANEL_HEIGHT, &(info->PanelYRes))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Flat panel height: %d\n", info->PanelYRes);
+ }
+ }
+
+#ifdef XF86DRI
+ /* DMA for Xv */
+ info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE);
+ if (info->DMAForXv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Will try to use DMA for Xv image transfers\n");
+ }
+
+ /* AGP/PCI */
+ if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
+ info->IsPCI = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
+ } else {
+ switch (info->Chipset) {
+ case PCI_CHIP_RAGE128LE:
+ case PCI_CHIP_RAGE128RE:
+ case PCI_CHIP_RAGE128RK:
+ case PCI_CHIP_RAGE128PD:
+ case PCI_CHIP_RAGE128PR:
+ case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE; break;
+ case PCI_CHIP_RAGE128LF:
+ case PCI_CHIP_RAGE128MF:
+ case PCI_CHIP_RAGE128ML:
+ case PCI_CHIP_RAGE128PF:
+ case PCI_CHIP_RAGE128RF:
+ case PCI_CHIP_RAGE128RG:
+ case PCI_CHIP_RAGE128RL:
+ case PCI_CHIP_RAGE128SM:
+ case PCI_CHIP_RAGE128TF:
+ case PCI_CHIP_RAGE128TL:
+ case PCI_CHIP_RAGE128TR:
+ /* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
+ * believed to be AGP, but need confirmation. <mharris@redhat.com>
+ */
+ case PCI_CHIP_RAGE128PA:
+ case PCI_CHIP_RAGE128PB:
+ case PCI_CHIP_RAGE128PC:
+ case PCI_CHIP_RAGE128PE:
+ case PCI_CHIP_RAGE128PG:
+ case PCI_CHIP_RAGE128PH:
+ case PCI_CHIP_RAGE128PI:
+ case PCI_CHIP_RAGE128PJ:
+ case PCI_CHIP_RAGE128PK:
+ case PCI_CHIP_RAGE128PL:
+ case PCI_CHIP_RAGE128PM:
+ case PCI_CHIP_RAGE128PN:
+ case PCI_CHIP_RAGE128PO:
+ case PCI_CHIP_RAGE128PQ:
+ case PCI_CHIP_RAGE128PS:
+ case PCI_CHIP_RAGE128PT:
+ case PCI_CHIP_RAGE128PU:
+ case PCI_CHIP_RAGE128PV:
+ case PCI_CHIP_RAGE128PW:
+ case PCI_CHIP_RAGE128PX:
+ case PCI_CHIP_RAGE128TS:
+ case PCI_CHIP_RAGE128TT:
+ case PCI_CHIP_RAGE128TU:
+ case PCI_CHIP_RAGE128SE:
+ case PCI_CHIP_RAGE128SF:
+ case PCI_CHIP_RAGE128SG:
+ case PCI_CHIP_RAGE128SH:
+ case PCI_CHIP_RAGE128SK:
+ case PCI_CHIP_RAGE128SL:
+ case PCI_CHIP_RAGE128SN:
+ default: info->IsPCI = FALSE; break;
+ }
+ }
+#endif
+
+ return TRUE;
+}
+
+static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ vbeInfoPtr pVbe;
+
+ if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+
+#if defined(__powerpc__) || defined(__alpha__)
+ /* Int10 is broken on PPC and some Alphas */
+ return TRUE;
+#else
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ xf86LoaderReqSymLists(vbeSymbols,NULL);
+ pVbe = VBEInit(pInt10,info->pEnt->index);
+ if (!pVbe) return FALSE;
+ xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
+ vbeFree(pVbe);
+ return TRUE;
+ } else
+ return FALSE;
+#endif
+}
+
+/* This is called by R128PreInit to initialize gamma correction. */
+static Bool R128PreInitGamma(ScrnInfoPtr pScrn)
+{
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros)) return FALSE;
+ return TRUE;
+}
+
+static void
+R128I2CGetBits(I2CBusPtr b, int *Clock, int *data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned long val;
+ unsigned char *R128MMIO = info->MMIO;
+
+ /* Get the result. */
+ val = INREG(info->DDCReg);
+ *Clock = (val & R128_GPIO_MONID_Y_3) != 0;
+ *data = (val & R128_GPIO_MONID_Y_0) != 0;
+
+}
+
+static void
+R128I2CPutBits(I2CBusPtr b, int Clock, int data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned long val;
+ unsigned char *R128MMIO = info->MMIO;
+
+ val = INREG(info->DDCReg)
+ & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3);
+ val |= (Clock ? 0:R128_GPIO_MONID_EN_3);
+ val |= (data ? 0:R128_GPIO_MONID_EN_0);
+ OUTREG(info->DDCReg, val);
+}
+
+
+static Bool
+R128I2cInit(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ if ( xf86LoadSubModule(pScrn, "i2c") )
+ xf86LoaderReqSymLists(i2cSymbols,NULL);
+ else{
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to load i2c module\n");
+ return FALSE;
+ }
+
+ info->pI2CBus = xf86CreateI2CBusRec();
+ if(!info->pI2CBus) return FALSE;
+
+ info->pI2CBus->BusName = "DDC";
+ info->pI2CBus->scrnIndex = pScrn->scrnIndex;
+ info->DDCReg = R128_GPIO_MONID;
+ info->pI2CBus->I2CPutBits = R128I2CPutBits;
+ info->pI2CBus->I2CGetBits = R128I2CGetBits;
+ info->pI2CBus->AcknTimeout = 5;
+
+ if (!xf86I2CBusInit(info->pI2CBus)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* return TRUE is a DFP is indeed connected to a DVI port */
+static Bool R128GetDFPInfo(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ int i;
+ xf86MonPtr MonInfo = NULL;
+ xf86MonPtr ddc;
+ unsigned char *R128MMIO = info->MMIO;
+
+ if(!R128I2cInit(pScrn)){
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I2C initialization failed!\n");
+ }
+
+ OUTREG(info->DDCReg, (INREG(info->DDCReg)
+ | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3));
+
+ OUTREG(info->DDCReg, INREG(info->DDCReg)
+ & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3));
+
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus);
+ if(!MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No DFP detected\n");
+ return FALSE;
+ }
+ xf86SetDDCproperties(pScrn, MonInfo);
+ ddc = pScrn->monitor->DDC;
+
+ for(i=0; i<4; i++)
+ {
+ if(ddc->det_mon[i].type == 0)
+ {
+ info->PanelXRes =
+ ddc->det_mon[i].section.d_timings.h_active;
+ info->PanelYRes =
+ ddc->det_mon[i].section.d_timings.v_active;
+
+ info->HOverPlus =
+ ddc->det_mon[i].section.d_timings.h_sync_off;
+ info->HSyncWidth =
+ ddc->det_mon[i].section.d_timings.h_sync_width;
+ info->HBlank =
+ ddc->det_mon[i].section.d_timings.h_blanking;
+ info->VOverPlus =
+ ddc->det_mon[i].section.d_timings.v_sync_off;
+ info->VSyncWidth =
+ ddc->det_mon[i].section.d_timings.v_sync_width;
+ info->VBlank =
+ ddc->det_mon[i].section.d_timings.v_blanking;
+ }
+ }
+ return TRUE;
+}
+
+
+static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
+{
+ int i;
+ xf86MonPtr ddc = pScrn->monitor->DDC;
+ if(flag) /*HSync*/
+ {
+ for(i=0; i<4; i++)
+ {
+ if(ddc->det_mon[i].type == DS_RANGES)
+ {
+ pScrn->monitor->nHsync = 1;
+ pScrn->monitor->hsync[0].lo =
+ ddc->det_mon[i].section.ranges.min_h;
+ pScrn->monitor->hsync[0].hi =
+ ddc->det_mon[i].section.ranges.max_h;
+ return;
+ }
+ }
+ /*if no sync ranges detected in detailed timing table,
+ let's try to derive them from supported VESA modes
+ Are we doing too much here!!!?
+ **/
+ i = 0;
+ if(ddc->timings1.t1 & 0x02) /*800x600@56*/
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 35.2;
+ i++;
+ }
+ if(ddc->timings1.t1 & 0x04) /*640x480@75*/
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 37.5;
+ i++;
+ }
+ if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01))
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 37.9;
+ i++;
+ }
+ if(ddc->timings1.t2 & 0x40)
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 46.9;
+ i++;
+ }
+ if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08))
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 48.1;
+ i++;
+ }
+ if(ddc->timings1.t2 & 0x04)
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 56.5;
+ i++;
+ }
+ if(ddc->timings1.t2 & 0x02)
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 60.0;
+ i++;
+ }
+ if(ddc->timings1.t2 & 0x01)
+ {
+ pScrn->monitor->hsync[i].lo =
+ pScrn->monitor->hsync[i].hi = 64.0;
+ i++;
+ }
+ pScrn->monitor->nHsync = i;
+ }
+ else /*Vrefresh*/
+ {
+ for(i=0; i<4; i++)
+ {
+ if(ddc->det_mon[i].type == DS_RANGES)
+ {
+ pScrn->monitor->nVrefresh = 1;
+ pScrn->monitor->vrefresh[0].lo =
+ ddc->det_mon[i].section.ranges.min_v;
+ pScrn->monitor->vrefresh[0].hi =
+ ddc->det_mon[i].section.ranges.max_v;
+ return;
+ }
+ }
+ i = 0;
+ if(ddc->timings1.t1 & 0x02) /*800x600@56*/
+ {
+ pScrn->monitor->vrefresh[i].lo =
+ pScrn->monitor->vrefresh[i].hi = 56;
+ i++;
+ }
+ if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08))
+ {
+ pScrn->monitor->vrefresh[i].lo =
+ pScrn->monitor->vrefresh[i].hi = 60;
+ i++;
+ }
+ if(ddc->timings1.t2 & 0x04)
+ {
+ pScrn->monitor->vrefresh[i].lo =
+ pScrn->monitor->vrefresh[i].hi = 70;
+ i++;
+ }
+ if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80))
+ {
+ pScrn->monitor->vrefresh[i].lo =
+ pScrn->monitor->vrefresh[i].hi = 72;
+ i++;
+ }
+ if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40)
+ || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01))
+ {
+ pScrn->monitor->vrefresh[i].lo =
+ pScrn->monitor->vrefresh[i].hi = 75;
+ i++;
+ }
+ pScrn->monitor->nVrefresh = i;
+ }
+}
+
+/***********
+ xfree's xf86ValidateModes routine deosn't work well with DFPs
+ here is our own validation routine. All modes between
+ 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted.
+ NOTE: RageProII doesn't support rmx, can only work with the
+ standard modes the monitor can support (scale).
+************/
+
+static int R128ValidateFPModes(ScrnInfoPtr pScrn)
+{
+ int i, j, count=0, width, height;
+ R128InfoPtr info = R128PTR(pScrn);
+ DisplayModePtr last = NULL, new = NULL, first = NULL;
+ xf86MonPtr ddc;
+
+ /* Free any allocated modes during configuration. We don't need them*/
+ while (pScrn->modes)
+ {
+ xf86DeleteMode(&pScrn->modes, pScrn->modes);
+ }
+ while (pScrn->modePool)
+ {
+ xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
+ }
+
+ pScrn->virtualX = pScrn->display->virtualX;
+ pScrn->virtualY = pScrn->display->virtualY;
+
+ /* If no mode specified in config, we use native resolution*/
+ if(!pScrn->display->modes[0])
+ {
+ pScrn->display->modes[0] = xnfalloc(16);
+ sprintf(pScrn->display->modes[0], "%dx%d",
+ info->PanelXRes, info->PanelYRes);
+ }
+
+ for(i=0; pScrn->display->modes[i] != NULL; i++)
+ {
+ if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2)
+ {
+
+ if(width < 640 || width > info->PanelXRes ||
+ height < 480 || height > info->PanelYRes)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode %s is out of range.\n"
+ "Valid mode should be between 640x480-%dx%d\n",
+ pScrn->display->modes[i], info->PanelXRes, info->PanelYRes);
+ continue;
+ }
+
+ new = xnfcalloc(1, sizeof(DisplayModeRec));
+ new->prev = last;
+ new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1);
+ strcpy(new->name, pScrn->display->modes[i]);
+ new->HDisplay = new->CrtcHDisplay = width;
+ new->VDisplay = new->CrtcVDisplay = height;
+
+ ddc = pScrn->monitor->DDC;
+ for(j=0; j<DET_TIMINGS; j++)
+ {
+ /*We use native mode clock only*/
+ if(ddc->det_mon[j].type == 0){
+ new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000;
+ break;
+ }
+ }
+
+ if(new->prev) new->prev->next = new;
+ last = new;
+ if(!first) first = new;
+ pScrn->display->virtualX =
+ pScrn->virtualX = MAX(pScrn->virtualX, width);
+ pScrn->display->virtualY =
+ pScrn->virtualY = MAX(pScrn->virtualY, height);
+ count++;
+ }
+ else
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode name %s is invalid\n", pScrn->display->modes[i]);
+ continue;
+ }
+ }
+
+ if(last)
+ {
+ last->next = first;
+ first->prev = last;
+ pScrn->modes = first;
+
+ /*FIXME: May need to validate line pitch here*/
+ {
+ int dummy = 0;
+ switch(pScrn->depth / 8)
+ {
+ case 1:
+ dummy = 128 - pScrn->virtualX % 128;
+ break;
+ case 2:
+ dummy = 32 - pScrn->virtualX % 32;
+ break;
+ case 3:
+ case 4:
+ dummy = 16 - pScrn->virtualX % 16;
+ }
+ pScrn->displayWidth = pScrn->virtualX + dummy;
+ }
+
+ }
+
+ return count;
+}
+
+
+/* This is called by R128PreInit to validate modes and compute parameters
+ for all of the valid modes. */
+static Bool R128PreInitModes(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ ClockRangePtr clockRanges;
+ int modesFound;
+ char *mod = NULL;
+#ifndef USE_FB
+ const char *Sym = NULL;
+#endif
+
+ if(info->isDFP) {
+ R128MapMem(pScrn);
+ info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
+ /* validate if DFP really connected. */
+ if(!R128GetDFPInfo(pScrn)) {
+ info->isDFP = FALSE;
+ info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
+ } else if(!info->isPro2) {
+ /* RageProII doesn't support rmx, we can't use native-mode
+ stretching for other non-native modes. It will rely on
+ whatever VESA modes monitor can support. */
+ modesFound = R128ValidateFPModes(pScrn);
+ if(modesFound < 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid mode found for this DFP/LCD\n");
+ R128UnmapMem(pScrn);
+ return FALSE;
+
+ }
+ }
+ R128UnmapMem(pScrn);
+ }
+
+ if(!info->isDFP || info->isPro2) {
+ /* Get mode information */
+ pScrn->progClock = TRUE;
+ clockRanges = xnfcalloc(sizeof(*clockRanges), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = info->pll.min_pll_freq;
+ clockRanges->maxClock = info->pll.max_pll_freq * 10;
+ clockRanges->clockIndex = -1;
+ if (info->HasPanelRegs || info->isDFP) {
+ clockRanges->interlaceAllowed = FALSE;
+ clockRanges->doubleScanAllowed = FALSE;
+ } else {
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = TRUE;
+ }
+
+ if(pScrn->monitor->DDC) {
+ /*if we still don't know sync range yet, let's try EDID.
+ Note that, since we can have dual heads, the Xconfigurator
+ may not be able to probe both monitors correctly through
+ vbe probe function (R128ProbeDDC). Here we provide an
+ additional way to auto-detect sync ranges if they haven't
+ been added to XF86Config manually.
+ **/
+ if(pScrn->monitor->nHsync <= 0)
+ R128SetSyncRangeFromEdid(pScrn, 1);
+ if(pScrn->monitor->nVrefresh <= 0)
+ R128SetSyncRangeFromEdid(pScrn, 0);
+ }
+
+
+ modesFound = xf86ValidateModes(pScrn,
+ pScrn->monitor->Modes,
+ pScrn->display->modes,
+ clockRanges,
+ NULL, /* linePitches */
+ 8 * 64, /* minPitch */
+ 8 * 1024, /* maxPitch */
+ 8 * 64, /* pitchInc */
+ 128, /* minHeight */
+ 2048, /* maxHeight */
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ info->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+
+ if (modesFound < 1 && info->FBDev) {
+ fbdevHWUseBuildinMode(pScrn);
+ pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8);
+ modesFound = 1;
+ }
+
+ if (modesFound == -1) return FALSE;
+ xf86PruneDriverModes(pScrn);
+ if (!modesFound || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ return FALSE;
+ }
+ xf86SetCrtcForModes(pScrn, 0);
+ }
+ /* Set DPI */
+ pScrn->currentMode = pScrn->modes;
+ xf86PrintModes(pScrn);
+
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Get ScreenInit function */
+#ifdef USE_FB
+ mod = "fb";
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8: mod = "cfb"; Sym = "cfbScreenInit"; break;
+ case 16: mod = "cfb16"; Sym = "cfb16ScreenInit"; break;
+ case 24:
+ if (info->pix24bpp == 24) {
+ mod = "cfb24"; Sym = "cfb24ScreenInit";
+ } else {
+ mod = "xf24_32bpp"; Sym = "cfb24_32ScreenInit";
+ }
+ break;
+ case 32: mod = "cfb32"; Sym = "cfb32ScreenInit"; break;
+ }
+#endif
+ if (mod && !xf86LoadSubModule(pScrn, mod)) return FALSE;
+#ifdef USE_FB
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+#else
+ xf86LoaderReqSymbols(Sym, NULL);
+#endif
+
+ info->CurrentLayout.displayWidth = pScrn->displayWidth;
+ info->CurrentLayout.mode = pScrn->currentMode;
+
+ return TRUE;
+}
+
+/* This is called by R128PreInit to initialize the hardware cursor. */
+static Bool R128PreInitCursor(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+ return TRUE;
+}
+
+/* This is called by R128PreInit to initialize hardware acceleration. */
+static Bool R128PreInitAccel(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE;
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+ return TRUE;
+}
+
+static Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+#if 1 && !defined(__alpha__)
+ /* int10 is broken on some Alphas */
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
+ *ppInt10 = xf86InitInt10(info->pEnt->index);
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef XF86DRI
+static Bool R128PreInitDRI(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n");
+ info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
+ } else {
+ info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
+ }
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "WARNING!!! CCE Security checks disabled!!! **********\n");
+ info->CCESecure = FALSE;
+ } else {
+ info->CCESecure = TRUE;
+ }
+
+ info->agpMode = R128_DEFAULT_AGP_MODE;
+ info->agpSize = R128_DEFAULT_AGP_SIZE;
+ info->ringSize = R128_DEFAULT_RING_SIZE;
+ info->bufSize = R128_DEFAULT_BUFFER_SIZE;
+ info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE;
+
+ info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
+
+ if (!info->IsPCI) {
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_AGP_MODE, &(info->agpMode))) {
+ if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP Mode: %d\n", info->agpMode);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using AGP %dx mode\n", info->agpMode);
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
+ switch (info->agpSize) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP size: %d MB\n", info->agpSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_RING_SIZE, &(info->ringSize))) {
+ if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal ring buffer size: %d MB\n",
+ info->ringSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_BUFFER_SIZE, &(info->bufSize))) {
+ if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal vertex/indirect buffers size: %d MB\n",
+ info->bufSize);
+ return FALSE;
+ }
+ if (info->bufSize > 2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal vertex/indirect buffers size: %d MB\n",
+ info->bufSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Clamping vertex/indirect buffers size to 2 MB\n");
+ info->bufSize = 2;
+ }
+ }
+
+ if (info->ringSize + info->bufSize + info->agpTexSize >
+ (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Buffers are too big for requested AGP space\n");
+ return FALSE;
+ }
+
+ info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
+ }
+
+ if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
+ &(info->CCEusecTimeout))) {
+ /* This option checked by the R128 DRM kernel module */
+ }
+
+ return TRUE;
+}
+#endif
+
+static void
+R128ProbeDDC(ScrnInfoPtr pScrn, int indx)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,indx);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+/* R128PreInit is called once at server startup. */
+Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
+{
+ R128InfoPtr info;
+ xf86Int10InfoPtr pInt10 = NULL;
+
+ R128TRACE(("R128PreInit\n"));
+
+ if (pScrn->numEntities != 1) return FALSE;
+
+ if (!R128GetRec(pScrn)) return FALSE;
+
+ info = R128PTR(pScrn);
+
+ info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (info->pEnt->location.type != BUS_PCI) goto fail;
+
+ if (flags & PROBE_DETECT) {
+ R128ProbeDDC(pScrn, info->pEnt->index);
+ return TRUE;
+ }
+
+ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+ if (!vgaHWGetHWRec(pScrn)) {
+ R128FreeRec(pScrn);
+ return FALSE;
+ }
+
+ info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
+ info->PciTag = pciTag(info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "PCI bus %d card %d func %d\n",
+ info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+
+ if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
+ if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
+
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ if (!R128PreInitVisual(pScrn)) goto fail;
+
+ /* We can't do this until we have a
+ pScrn->display. */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(info->Options = xalloc(sizeof(R128Options)))) goto fail;
+ memcpy(info->Options, R128Options, sizeof(R128Options));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
+
+ if (!R128PreInitWeight(pScrn)) goto fail;
+
+ if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
+ info->videoKey);
+ } else {
+ info->videoKey = 0x1E;
+ }
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) {
+ info->showCache = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
+ }
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) {
+ info->FBDev = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using framebuffer device\n");
+ }
+
+ if (info->FBDev) {
+ /* check for linux framebuffer device */
+ if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE;
+ xf86LoaderReqSymLists(fbdevHWSymbols, NULL);
+ if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE;
+ pScrn->SwitchMode = fbdevHWSwitchMode;
+ pScrn->AdjustFrame = fbdevHWAdjustFrame;
+ pScrn->ValidMode = fbdevHWValidMode;
+ }
+
+ if (!info->FBDev)
+ if (!R128PreInitInt10(pScrn, &pInt10)) goto fail;
+
+ if (!R128PreInitConfig(pScrn)) goto fail;
+
+ if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail;
+
+ if (!R128GetPLLParameters(pScrn)) goto fail;
+
+ /* Don't fail on this one */
+ R128PreInitDDC(pScrn, pInt10);
+
+ if (!R128PreInitGamma(pScrn)) goto fail;
+
+ if (!R128PreInitModes(pScrn)) goto fail;
+
+ if (!R128PreInitCursor(pScrn)) goto fail;
+
+ if (!R128PreInitAccel(pScrn)) goto fail;
+
+#ifdef XF86DRI
+ if (!R128PreInitDRI(pScrn)) goto fail;
+#endif
+
+ /* Free the video bios (if applicable) */
+ if (info->VBIOS) {
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ }
+
+ /* Free int10 info */
+ if (pInt10)
+ xf86FreeInt10(pInt10);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
+ "For information on using the multimedia capabilities\n of this"
+ " adapter, please see http://gatos.sf.net.\n");
+
+ return TRUE;
+
+ fail:
+ /* Pre-init failed. */
+
+ /* Free the video bios (if applicable) */
+ if (info->VBIOS) {
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ }
+
+ /* Free int10 info */
+ if (pInt10)
+ xf86FreeInt10(pInt10);
+
+ vgaHWFreeHWRec(pScrn);
+ R128FreeRec(pScrn);
+ return FALSE;
+}
+
+/* Load a palette. */
+static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
+ int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+ int idx;
+ unsigned char r, g, b;
+
+ /* Select palette 0 (main CRTC) if using FP-enabled chip */
+ if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);
+
+ if (info->CurrentLayout.depth == 15) {
+ /* 15bpp mode. This sends 32 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ g = colors[idx].green;
+ b = colors[idx].blue;
+ OUTPAL(idx * 8, r, g, b);
+ }
+ }
+ else if (info->CurrentLayout.depth == 16) {
+ /* 16bpp mode. This sends 64 values. */
+ /* There are twice as many green values as
+ there are values for red and blue. So,
+ we take each red and blue pair, and
+ combine it with each of the two green
+ values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx / 2].red;
+ g = colors[idx].green;
+ b = colors[idx / 2].blue;
+ OUTPAL(idx * 4, r, g, b);
+ }
+ }
+ else {
+ /* 8bpp mode. This sends 256 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ b = colors[idx].blue;
+ g = colors[idx].green;
+ OUTPAL(idx, r, g, b);
+ }
+ }
+}
+
+static void
+R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ R128InfoPtr info = R128PTR(pScrn);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled)
+ FLUSH_RING();
+#endif
+
+ pScreen->BlockHandler = info->BlockHandler;
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = R128BlockHandler;
+
+ if(info->VideoTimerCallback) {
+ (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+ }
+}
+
+/* Called at the start of each server generation. */
+Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ BoxRec MemBox;
+ int y2;
+
+ R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset));
+
+#ifdef XF86DRI
+ /* Turn off the CCE for now. */
+ info->CCEInUse = FALSE;
+ info->indirectBuffer = NULL;
+#endif
+
+ if (!R128MapMem(pScrn)) return FALSE;
+ pScrn->fbOffset = 0;
+#ifdef XF86DRI
+ info->fbX = 0;
+ info->fbY = 0;
+ info->frontOffset = 0;
+ info->frontPitch = pScrn->displayWidth;
+#endif
+
+ info->PaletteSavedOnVT = FALSE;
+
+ R128Save(pScrn);
+ if (info->FBDev) {
+ if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ } else {
+ if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ }
+
+ R128SaveScreen(pScreen, SCREEN_SAVER_ON);
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ /* Visual setup */
+ miClearVisualTypes();
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits,
+ pScrn->defaultVisual)) return FALSE;
+ miSetPixmapDepths ();
+
+#ifdef XF86DRI
+ /* Setup DRI after visuals have been
+ established, but before cfbScreenInit is
+ called. cfbScreenInit will eventually
+ call the driver's InitGLXVisuals call
+ back. */
+ {
+ /* FIXME: When we move to dynamic allocation of back and depth
+ buffers, we will want to revisit the following check for 3
+ times the virtual size of the screen below. */
+ int width_bytes = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ int maxy = info->FbMapSize / width_bytes;
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Acceleration disabled, not initializing the DRI\n");
+ info->directRenderingEnabled = FALSE;
+ } else if (maxy <= pScrn->virtualY * 3) {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Static buffer allocation failed -- "
+ "need at least %d kB video memory\n",
+ (pScrn->displayWidth * pScrn->virtualY *
+ info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
+ info->directRenderingEnabled = FALSE;
+ } else {
+ info->directRenderingEnabled = R128DRIScreenInit(pScreen);
+ }
+ }
+#endif
+
+#ifdef USE_FB
+ if (!fbScreenInit (pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+ pScrn->bitsPerPixel))
+ return FALSE;
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ if (!cfbScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 16:
+ if (!cfb16ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 24:
+ if (info->pix24bpp == 24) {
+ if (!cfb24ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ } else {
+ if (!cfb24_32ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ }
+ break;
+ case 32:
+ if (!cfb32ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Invalid bpp (%d)\n", pScrn->bitsPerPixel);
+ return FALSE;
+ }
+#endif
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+#ifdef USE_FB
+ /* must be after RGB order fixed */
+ fbPictureInit (pScreen, 0, 0);
+#endif
+ /* Memory manager setup */
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ FBAreaPtr fbarea;
+ int width_bytes = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ int cpp = info->CurrentLayout.pixel_bytes;
+ int bufferSize = pScrn->virtualY * width_bytes;
+ int l, total;
+ int scanlines;
+
+ switch (info->CCEMode) {
+ case R128_DEFAULT_CCE_PIO_MODE:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
+ break;
+ case R128_DEFAULT_CCE_BM_MODE:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
+ break;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB AGP aperture\n", info->agpSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for the ring buffer\n", info->ringSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for vertex/indirect buffers\n", info->bufSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for AGP textures\n", info->agpTexSize);
+
+ /* Try for front, back, depth, and two framebuffers worth of
+ * pixmap cache. Should be enough for a fullscreen background
+ * image plus some leftovers.
+ */
+ info->textureSize = info->FbMapSize - 5 * bufferSize;
+
+ /* If that gives us less than half the available memory, let's
+ * be greedy and grab some more. Sorry, I care more about 3D
+ * performance than playing nicely, and you'll get around a full
+ * framebuffer's worth of pixmap cache anyway.
+ */
+ if (info->textureSize < (int)info->FbMapSize / 2) {
+ info->textureSize = info->FbMapSize - 4 * bufferSize;
+ }
+
+ if (info->textureSize > 0) {
+ l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
+ if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+
+ /* Round the texture size up to the nearest whole number of
+ * texture regions. Again, be greedy about this, don't
+ * round down.
+ */
+ info->log2TexGran = l;
+ info->textureSize = (info->textureSize >> l) << l;
+ } else {
+ info->textureSize = 0;
+ }
+
+ /* Set a minimum usable local texture heap size. This will fit
+ * two 256x256x32bpp textures.
+ */
+ if (info->textureSize < 512 * 1024) {
+ info->textureOffset = 0;
+ info->textureSize = 0;
+ }
+
+ total = info->FbMapSize - info->textureSize;
+ scanlines = total / width_bytes;
+ if (scanlines > 8191) scanlines = 8191;
+
+ /* Recalculate the texture offset and size to accomodate any
+ * rounding to a whole number of scanlines.
+ */
+ info->textureOffset = scanlines * width_bytes;
+
+ MemBox.x1 = 0;
+ MemBox.y1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ MemBox.y2 = scanlines;
+
+ if (!xf86InitFBManager(pScreen, &MemBox)) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ return FALSE;
+ } else {
+ int width, height;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Memory manager initialized to (%d,%d) (%d,%d)\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth,
+ 2, 0, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved area from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+ }
+ if (xf86QueryLargestOffscreenArea(pScreen, &width,
+ &height, 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+ }
+ }
+
+ /* Allocate the shared back buffer */
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ 32, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved back buffer from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+
+ info->backX = fbarea->box.x1;
+ info->backY = fbarea->box.y1;
+ info->backOffset = (fbarea->box.y1 * width_bytes +
+ fbarea->box.x1 * cpp);
+ info->backPitch = pScrn->displayWidth;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
+ info->backX = -1;
+ info->backY = -1;
+ info->backOffset = -1;
+ info->backPitch = -1;
+ }
+
+ /* Allocate the shared depth buffer */
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->virtualX,
+ pScrn->virtualY + 1,
+ 32, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved depth buffer from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+
+ info->depthX = fbarea->box.x1;
+ info->depthY = fbarea->box.y1;
+ info->depthOffset = (fbarea->box.y1 * width_bytes +
+ fbarea->box.x1 * cpp);
+ info->depthPitch = pScrn->displayWidth;
+ info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes +
+ fbarea->box.x1 * cpp);
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved depth span from (%d,%d) offset 0x%x\n",
+ fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
+ info->depthX = -1;
+ info->depthY = -1;
+ info->depthOffset = -1;
+ info->depthPitch = -1;
+ info->spanOffset = -1;
+ }
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved %d kb for textures at offset 0x%x\n",
+ info->textureSize/1024, info->textureOffset);
+ }
+ else
+#endif
+ {
+ MemBox.x1 = 0;
+ MemBox.y1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ y2 = (info->FbMapSize
+ / (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes));
+ /* The acceleration engine uses 14 bit
+ signed coordinates, so we can't have any
+ drawable caches beyond this region. */
+ if (y2 > 8191) y2 = 8191;
+ MemBox.y2 = y2;
+
+ if (!xf86InitFBManager(pScreen, &MemBox)) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ return FALSE;
+ } else {
+ int width, height;
+ FBAreaPtr fbarea;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Memory manager initialized to (%d,%d) (%d,%d)\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ 2, 0, NULL, NULL, NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved area from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+ }
+ if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
+ 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+ }
+ }
+ }
+
+ /* Acceleration setup */
+ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ if (R128AccelInit(pScreen)) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
+ info->accelOn = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Acceleration initialization failed\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+
+ /* DGA setup */
+ R128DGAInit(pScreen);
+
+ /* Backing store setup */
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+
+ /* Set Silken Mouse */
+ xf86SetSilkenMouse(pScreen);
+
+ /* Cursor setup */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Hardware cursor setup */
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (R128CursorInit(pScreen)) {
+ int width, height;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using hardware cursor (scanline %d)\n",
+ info->cursor_start / pScrn->displayWidth);
+ if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
+ 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
+ }
+ } else {
+ info->cursor_start = 0;
+ xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
+ }
+
+ /* Colormap setup */
+ if (!miCreateDefColormap(pScreen)) return FALSE;
+ if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
+ (info->FBDev ? fbdevHWLoadPalette :
+ R128LoadPalette), NULL,
+ CMAP_PALETTED_TRUECOLOR
+ | CMAP_RELOAD_ON_MODE_SWITCH
+#if 0 /* This option messes up text mode! (eich@suse.de) */
+ | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+ )) return FALSE;
+
+ /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
+ if (info->FBDev)
+ xf86DPMSInit(pScreen, fbdevHWDPMSSet, 0);
+ else {
+ if (!info->HasPanelRegs || info->BIOSDisplay == R128_BIOS_DISPLAY_CRT)
+ xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0);
+ else if (info->HasPanelRegs || info->BIOSDisplay == R128_BIOS_DISPLAY_FP)
+ xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0);
+ }
+
+ R128InitVideo(pScreen);
+
+ /* Provide SaveScreen */
+ pScreen->SaveScreen = R128SaveScreen;
+
+ /* Wrap CloseScreen */
+ info->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = R128CloseScreen;
+
+ /* Note unused options */
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+#ifdef XF86DRI
+ /* DRI finalization */
+ if (info->directRenderingEnabled) {
+ /* Now that mi, cfb, drm and others have
+ done their thing, complete the DRI
+ setup. */
+ info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
+ }
+ if (info->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n");
+ }
+#endif
+
+ info->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = R128BlockHandler;
+
+ return TRUE;
+}
+
+/* Write common registers (initialized to 0). */
+static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
+
+ OUTREG(R128_OVR_CLR, restore->ovr_clr);
+ OUTREG(R128_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right);
+ OUTREG(R128_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
+ OUTREG(R128_OV0_SCALE_CNTL, restore->ov0_scale_cntl);
+ OUTREG(R128_MPP_TB_CONFIG, restore->mpp_tb_config );
+ OUTREG(R128_MPP_GP_CONFIG, restore->mpp_gp_config );
+ OUTREG(R128_SUBPIC_CNTL, restore->subpic_cntl);
+ OUTREG(R128_VIPH_CONTROL, restore->viph_control);
+ OUTREG(R128_I2C_CNTL_1, restore->i2c_cntl_1);
+ OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl);
+ OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl);
+ OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl);
+ OUTREG(R128_BUS_CNTL, restore->bus_cntl);
+ OUTREG(R128_CONFIG_CNTL, restore->config_cntl);
+}
+
+/* Write CRTC registers. */
+static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG(R128_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
+
+ OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl,
+ R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS);
+
+ OUTREGP(R128_DAC_CNTL, restore->dac_cntl,
+ R128_DAC_RANGE_CNTL | R128_DAC_BLANKING);
+
+ OUTREG(R128_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp);
+ OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
+ OUTREG(R128_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp);
+ OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
+ OUTREG(R128_CRTC_OFFSET, restore->crtc_offset);
+ OUTREG(R128_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl);
+ OUTREG(R128_CRTC_PITCH, restore->crtc_pitch);
+}
+
+/* Write flat panel registers */
+static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 tmp;
+
+
+ /*OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);*/
+ OUTREG(R128_FP_HORZ_STRETCH, restore->fp_horz_stretch);
+ OUTREG(R128_FP_VERT_STRETCH, restore->fp_vert_stretch);
+ OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
+ OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
+ OUTREG(R128_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid);
+ OUTREG(R128_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid);
+ OUTREG(R128_TMDS_CRC, restore->tmds_crc);
+ OUTREG(R128_FP_PANEL_CNTL, restore->fp_panel_cntl);
+ OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(CARD32)R128_FP_BLANK_DIS);
+
+ if(info->isDFP) return;
+
+ tmp = INREG(R128_LVDS_GEN_CNTL);
+ if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
+ (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
+ OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ } else {
+ if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
+ OUTREG(R128_LVDS_GEN_CNTL,
+ restore->lvds_gen_cntl & (CARD32)~R128_LVDS_BLON);
+ usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
+ OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ } else {
+ OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
+ usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
+ OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ }
+ }
+}
+
+static void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
+{
+ while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
+}
+
+static void R128PLLWriteUpdate(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, 0xffff);
+}
+
+/* Write PLL registers. */
+static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, 0xffff);
+
+ OUTPLLP(pScrn,
+ R128_PPLL_CNTL,
+ R128_PPLL_RESET
+ | R128_PPLL_ATOMIC_UPDATE_EN
+ | R128_PPLL_VGA_ATOMIC_UPDATE_EN,
+ 0xffff);
+
+ R128PLLWaitForReadUpdateComplete(pScrn);
+ OUTPLLP(pScrn, R128_PPLL_REF_DIV,
+ restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK);
+ R128PLLWriteUpdate(pScrn);
+
+ R128PLLWaitForReadUpdateComplete(pScrn);
+ OUTPLLP(pScrn, R128_PPLL_DIV_3,
+ restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK);
+ R128PLLWriteUpdate(pScrn);
+ OUTPLLP(pScrn, R128_PPLL_DIV_3,
+ restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK);
+ R128PLLWriteUpdate(pScrn);
+
+ R128PLLWaitForReadUpdateComplete(pScrn);
+ OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl);
+ R128PLLWriteUpdate(pScrn);
+
+ OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~R128_PPLL_RESET);
+
+ R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+ restore->ppll_ref_div,
+ restore->ppll_div_3,
+ restore->htotal_cntl,
+ INPLL(pScrn, R128_PPLL_CNTL)));
+ R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
+ restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
+ restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
+ (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
+}
+
+/* Write DDA registers. */
+static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ OUTREG(R128_DDA_CONFIG, restore->dda_config);
+ OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
+}
+
+/* Write palette data. */
+static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ if (!restore->palette_valid) return;
+
+ /* Select palette 0 (main CRTC) if using FP-enabled chip */
+ if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);
+
+ OUTPAL_START(0);
+ for (i = 0; i < 256; i++) OUTPAL_NEXT_CARD32(restore->palette[i]);
+}
+
+/* Write out state to define a new video mode. */
+static void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ R128TRACE(("R128RestoreMode(%p)\n", restore));
+ R128RestoreCommonRegisters(pScrn, restore);
+ R128RestoreCrtcRegisters(pScrn, restore);
+ if (!(info->HasPanelRegs) || info->BIOSDisplay == R128_BIOS_DISPLAY_CRT){
+ R128RestorePLLRegisters(pScrn, restore);
+ }
+ R128RestoreDDARegisters(pScrn, restore);
+ if (info->HasPanelRegs || info->isDFP)
+ R128RestoreFPRegisters(pScrn, restore);
+
+ R128RestorePalette(pScrn, restore);
+}
+
+/* Read common registers. */
+static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ save->ovr_clr = INREG(R128_OVR_CLR);
+ save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
+ save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
+ save->ov0_scale_cntl = INREG(R128_OV0_SCALE_CNTL);
+ save->mpp_tb_config = INREG(R128_MPP_TB_CONFIG);
+ save->mpp_gp_config = INREG(R128_MPP_GP_CONFIG);
+ save->subpic_cntl = INREG(R128_SUBPIC_CNTL);
+ save->viph_control = INREG(R128_VIPH_CONTROL);
+ save->i2c_cntl_1 = INREG(R128_I2C_CNTL_1);
+ save->gen_int_cntl = INREG(R128_GEN_INT_CNTL);
+ save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL);
+ save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL);
+ save->bus_cntl = INREG(R128_BUS_CNTL);
+ save->config_cntl = INREG(R128_CONFIG_CNTL);
+}
+
+/* Read CRTC registers. */
+static void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ save->crtc_gen_cntl = INREG(R128_CRTC_GEN_CNTL);
+ save->crtc_ext_cntl = INREG(R128_CRTC_EXT_CNTL);
+ save->dac_cntl = INREG(R128_DAC_CNTL);
+ save->crtc_h_total_disp = INREG(R128_CRTC_H_TOTAL_DISP);
+ save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
+ save->crtc_v_total_disp = INREG(R128_CRTC_V_TOTAL_DISP);
+ save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
+ save->crtc_offset = INREG(R128_CRTC_OFFSET);
+ save->crtc_offset_cntl = INREG(R128_CRTC_OFFSET_CNTL);
+ save->crtc_pitch = INREG(R128_CRTC_PITCH);
+}
+
+/* Read flat panel registers */
+static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL);
+ save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
+ save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
+ save->fp_gen_cntl = INREG(R128_FP_GEN_CNTL);
+ save->fp_h_sync_strt_wid = INREG(R128_FP_H_SYNC_STRT_WID);
+ save->fp_horz_stretch = INREG(R128_FP_HORZ_STRETCH);
+ save->fp_panel_cntl = INREG(R128_FP_PANEL_CNTL);
+ save->fp_v_sync_strt_wid = INREG(R128_FP_V_SYNC_STRT_WID);
+ save->fp_vert_stretch = INREG(R128_FP_VERT_STRETCH);
+ save->lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL);
+ save->tmds_crc = INREG(R128_TMDS_CRC);
+ save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
+}
+
+/* Read PLL registers. */
+static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ save->ppll_ref_div = INPLL(pScrn, R128_PPLL_REF_DIV);
+ save->ppll_div_3 = INPLL(pScrn, R128_PPLL_DIV_3);
+ save->htotal_cntl = INPLL(pScrn, R128_HTOTAL_CNTL);
+
+ R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
+ save->ppll_ref_div,
+ save->ppll_div_3,
+ save->htotal_cntl));
+ R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
+ save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
+ save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
+ (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
+}
+
+/* Read DDA registers. */
+static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+
+ save->dda_config = INREG(R128_DDA_CONFIG);
+ save->dda_on_off = INREG(R128_DDA_ON_OFF);
+}
+
+/* Read palette data. */
+static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int i;
+
+ /* Select palette 0 (main CRTC) if using FP-enabled chip */
+ if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);
+
+ INPAL_START(0);
+ for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
+ save->palette_valid = TRUE;
+}
+
+/* Save state that defines current video mode. */
+static void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
+{
+ R128TRACE(("R128SaveMode(%p)\n", save));
+
+ R128SaveCommonRegisters(pScrn, save);
+ R128SaveCrtcRegisters(pScrn, save);
+ if (R128PTR(pScrn)->HasPanelRegs || R128PTR(pScrn)->isDFP)
+ R128SaveFPRegisters(pScrn, save);
+ R128SavePLLRegisters(pScrn, save);
+ R128SaveDDARegisters(pScrn, save);
+ R128SavePalette(pScrn, save);
+
+ R128TRACE(("R128SaveMode returns %p\n", save));
+}
+
+/* Save everything needed to restore the original VC state. */
+static void R128Save(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128SavePtr save = &info->SavedReg;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ R128TRACE(("R128Save\n"));
+ if (info->FBDev) {
+ fbdevHWSave(pScrn);
+ return;
+ }
+ vgaHWUnlock(hwp);
+ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* save mode, fonts, cmap */
+ vgaHWLock(hwp);
+
+ R128SaveMode(pScrn, save);
+
+ save->dp_datatype = INREG(R128_DP_DATATYPE);
+ save->gen_reset_cntl = INREG(R128_GEN_RESET_CNTL);
+ save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
+ save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG);
+ save->amcgpio_mask = INREG(R128_AMCGPIO_MASK);
+}
+
+/* Restore the original (text) mode. */
+static void R128Restore(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128SavePtr restore = &info->SavedReg;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ R128TRACE(("R128Restore\n"));
+ if (info->FBDev) {
+ fbdevHWRestore(pScrn);
+ return;
+ }
+
+ R128Blank(pScrn);
+ OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask);
+ OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg);
+ OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
+ OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl);
+ OUTREG(R128_DP_DATATYPE, restore->dp_datatype);
+
+ R128RestoreMode(pScrn, restore);
+ vgaHWUnlock(hwp);
+ vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+ vgaHWLock(hwp);
+
+ R128WaitForVerticalSync(pScrn);
+ R128Unblank(pScrn);
+}
+
+/* Define common registers for requested video mode. */
+static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
+{
+ save->ovr_clr = 0;
+ save->ovr_wid_left_right = 0;
+ save->ovr_wid_top_bottom = 0;
+ save->ov0_scale_cntl = 0;
+ save->mpp_tb_config = 0;
+ save->mpp_gp_config = 0;
+ save->subpic_cntl = 0;
+ save->viph_control = 0;
+ save->i2c_cntl_1 = 0;
+ save->gen_int_cntl = 0;
+ save->cap0_trig_cntl = 0;
+ save->cap1_trig_cntl = 0;
+ save->bus_cntl = info->BusCntl;
+ /*
+ * If bursts are enabled, turn on discards and aborts
+ */
+ if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
+ save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
+}
+
+/* Define CRTC registers for requested video mode. */
+static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
+ DisplayModePtr mode, R128InfoPtr info)
+{
+ int format;
+ int hsync_start;
+ int hsync_wid;
+ int hsync_fudge;
+ int vsync_wid;
+ int bytpp;
+ int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
+ int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
+ int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 4: format = 1; bytpp = 0; break;
+ case 8: format = 2; bytpp = 1; break;
+ case 15: format = 3; bytpp = 2; break; /* 555 */
+ case 16: format = 4; bytpp = 2; break; /* 565 */
+ case 24: format = 5; bytpp = 3; break; /* RGB */
+ case 32: format = 6; bytpp = 4; break; /* xRGB */
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unsupported pixel depth (%d)\n",
+ info->CurrentLayout.bitsPerPixel);
+ return FALSE;
+ }
+ R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp));
+
+ switch (info->BIOSDisplay) {
+ case R128_BIOS_DISPLAY_FP:
+ hsync_fudge = hsync_fudge_fp[format-1];
+ break;
+ case R128_BIOS_DISPLAY_FP_CRT:
+ hsync_fudge = hsync_fudge_fp_crt[format-1];
+ break;
+ case R128_BIOS_DISPLAY_CRT:
+ default:
+ hsync_fudge = hsync_fudge_default[format-1];
+ break;
+ }
+
+ save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
+ | R128_CRTC_EN
+ | (format << 8)
+ | ((mode->Flags & V_DBLSCAN)
+ ? R128_CRTC_DBL_SCAN_EN
+ : 0)
+ | ((mode->Flags & V_INTERLACE)
+ ? R128_CRTC_INTERLACE_EN
+ : 0)
+ | ((mode->Flags & V_CSYNC)
+ ? R128_CRTC_CSYNC_EN
+ : 0));
+
+ save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN;
+ save->dac_cntl = (R128_DAC_MASK_ALL
+ | R128_DAC_VGA_ADR_EN
+ | (info->dac6bits ? 0 : R128_DAC_8BIT_EN));
+
+
+ if(info->isDFP && !info->isPro2)
+ {
+ if(info->PanelXRes < mode->CrtcHDisplay)
+ mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes;
+ if(info->PanelYRes < mode->CrtcVDisplay)
+ mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes;
+ mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank;
+ mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus;
+ mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth;
+ mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank;
+ mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus;
+ mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth;
+ }
+
+ save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
+ | (((mode->CrtcHDisplay / 8) - 1) << 16));
+
+ hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
+ if (!hsync_wid) hsync_wid = 1;
+ if (hsync_wid > 0x3f) hsync_wid = 0x3f;
+
+ hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
+
+ save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
+ | (hsync_wid << 16)
+ | ((mode->Flags & V_NHSYNC)
+ ? R128_CRTC_H_SYNC_POL
+ : 0));
+
+#if 1
+ /* This works for double scan mode. */
+ save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay - 1) << 16));
+#else
+ /* This is what cce/nbmode.c example code
+ does -- is this correct? */
+ save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay
+ * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
+ << 16));
+#endif
+
+ vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+ if (!vsync_wid) vsync_wid = 1;
+ if (vsync_wid > 0x1f) vsync_wid = 0x1f;
+
+ save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
+ | (vsync_wid << 16)
+ | ((mode->Flags & V_NVSYNC)
+ ? R128_CRTC_V_SYNC_POL
+ : 0));
+ save->crtc_offset = 0;
+ save->crtc_offset_cntl = 0;
+ save->crtc_pitch = info->CurrentLayout.displayWidth / 8;
+
+ R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
+ save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth));
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* Change the endianness of the aperture */
+ switch (info->CurrentLayout.pixel_code) {
+ case 15:
+ case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
+ case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
+ default: break;
+ }
+#endif
+
+ return TRUE;
+}
+
+/* Define CRTC registers for requested video mode. */
+static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save,
+ DisplayModePtr mode, R128InfoPtr info)
+{
+ int xres = mode->CrtcHDisplay;
+ int yres = mode->CrtcVDisplay;
+ float Hratio, Vratio;
+
+ if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) {
+ save->crtc_ext_cntl |= R128_CRTC_CRT_ON;
+ save->crtc2_gen_cntl = 0;
+ save->fp_gen_cntl = orig->fp_gen_cntl;
+ save->fp_gen_cntl &= ~(R128_FP_FPON |
+ R128_FP_CRTC_USE_SHADOW_VEND |
+ R128_FP_CRTC_HORZ_DIV2_EN |
+ R128_FP_CRTC_HOR_CRT_DIV2_DIS |
+ R128_FP_USE_SHADOW_EN);
+ save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 |
+ R128_FP_CRTC_DONT_SHADOW_VPAR);
+ save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON;
+ save->lvds_gen_cntl = orig->lvds_gen_cntl &
+ (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON);
+ return;
+ }
+
+ if (xres > info->PanelXRes) xres = info->PanelXRes;
+ if (yres > info->PanelYRes) yres = info->PanelYRes;
+
+ Hratio = (float)xres/(float)info->PanelXRes;
+ Vratio = (float)yres/(float)info->PanelYRes;
+
+ save->fp_horz_stretch =
+ (((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
+ & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
+ (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
+ R128_HORZ_FP_LOOP_STRETCH |
+ R128_HORZ_STRETCH_RESERVED)));
+ save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
+ save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
+ if (xres == info->PanelXRes)
+ save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
+ else
+ save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
+
+ save->fp_vert_stretch =
+ (((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
+ & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
+ (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
+ R128_VERT_STRETCH_RESERVED)));
+ save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
+ if (yres == info->PanelYRes)
+ save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
+ else
+ save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
+
+ save->fp_gen_cntl = (orig->fp_gen_cntl &
+ (CARD32)~(R128_FP_SEL_CRTC2 |
+ R128_FP_CRTC_USE_SHADOW_VEND |
+ R128_FP_CRTC_HORZ_DIV2_EN |
+ R128_FP_CRTC_HOR_CRT_DIV2_DIS |
+ R128_FP_USE_SHADOW_EN));
+
+ save->fp_panel_cntl = orig->fp_panel_cntl;
+ save->lvds_gen_cntl = orig->lvds_gen_cntl;
+ save->tmds_crc = orig->tmds_crc;
+
+ /* Disable CRT output by disabling CRT output and setting the CRT
+ DAC to use CRTC2, which we set to 0's. In the future, we will
+ want to use the dual CRTC capabilities of the R128 to allow both
+ the flat panel and external CRT to either simultaneously display
+ the same image or display two different images. */
+
+ if(!info->isDFP){
+ if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) {
+ save->crtc_ext_cntl |= R128_CRTC_CRT_ON;
+ } else {
+ save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON;
+ save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2;
+ save->crtc2_gen_cntl = 0;
+ }
+ }
+
+ /* WARNING: Be careful about turning on the flat panel */
+ if(info->isDFP){
+ save->fp_gen_cntl = orig->fp_gen_cntl;
+
+ save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
+ R128_FP_CRTC_USE_SHADOW_ROWCUR |
+ R128_FP_CRTC_HORZ_DIV2_EN |
+ R128_FP_CRTC_HOR_CRT_DIV2_DIS |
+ R128_FP_CRT_SYNC_SEL |
+ R128_FP_USE_SHADOW_EN);
+
+ save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON);
+ save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN |
+ R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND);
+ save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl
+ & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN;
+ }
+ else
+ save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON);
+
+ save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
+ save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
+ save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid;
+ save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid;
+}
+
+/* Define PLL registers for requested video mode. */
+static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
+ R128PLLPtr pll, double dot_clock)
+{
+ unsigned long freq = dot_clock * 100;
+ struct {
+ int divider;
+ int bitvalue;
+ } *post_div,
+ post_divs[] = {
+ /* From RAGE 128 VR/RAGE 128 GL Register
+ Reference Manual (Technical Reference
+ Manual P/N RRG-G04100-C Rev. 0.04), page
+ 3-17 (PLL_DIV_[3:0]). */
+ { 1, 0 }, /* VCLK_SRC */
+ { 2, 1 }, /* VCLK_SRC/2 */
+ { 4, 2 }, /* VCLK_SRC/4 */
+ { 8, 3 }, /* VCLK_SRC/8 */
+
+ { 3, 4 }, /* VCLK_SRC/3 */
+ /* bitvalue = 5 is reserved */
+ { 6, 6 }, /* VCLK_SRC/6 */
+ { 12, 7 }, /* VCLK_SRC/12 */
+ { 0, 0 }
+ };
+
+ if (freq > pll->max_pll_freq) freq = pll->max_pll_freq;
+ if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ save->pll_output_freq = post_div->divider * freq;
+ if (save->pll_output_freq >= pll->min_pll_freq
+ && save->pll_output_freq <= pll->max_pll_freq) break;
+ }
+
+ save->dot_clock_freq = freq;
+ save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq,
+ pll->reference_freq);
+ save->post_div = post_div->divider;
+
+ R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
+ save->dot_clock_freq,
+ save->pll_output_freq,
+ save->feedback_div,
+ save->post_div));
+
+ save->ppll_ref_div = pll->reference_div;
+ save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16));
+ save->htotal_cntl = 0;
+
+}
+
+/* Define DDA registers for requested video mode. */
+static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save,
+ R128PLLPtr pll, R128InfoPtr info,
+ DisplayModePtr mode)
+{
+ int DisplayFifoWidth = 128;
+ int DisplayFifoDepth = 32;
+ int XclkFreq;
+ int VclkFreq;
+ int XclksPerTransfer;
+ int XclksPerTransferPrecise;
+ int UseablePrecision;
+ int Roff;
+ int Ron;
+
+ XclkFreq = pll->xclk;
+
+ VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
+ pll->reference_div * save->post_div);
+
+ if(info->isDFP && !info->isPro2){
+ if(info->PanelXRes != mode->CrtcHDisplay)
+ VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes;
+ }
+
+ XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
+ VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
+
+ UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
+
+ XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
+ << (11 - UseablePrecision),
+ VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
+
+ Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
+
+ Ron = (4 * info->ram->MB
+ + 3 * MAX(info->ram->Trcd - 2, 0)
+ + 2 * info->ram->Trp
+ + info->ram->Twr
+ + info->ram->CL
+ + info->ram->Tr2w
+ + XclksPerTransfer) << (11 - UseablePrecision);
+
+ if (Ron + info->ram->Rloop >= Roff) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
+ Ron, info->ram->Rloop, Roff);
+ return FALSE;
+ }
+
+ save->dda_config = (XclksPerTransferPrecise
+ | (UseablePrecision << 16)
+ | (info->ram->Rloop << 20));
+
+ save->dda_on_off = (Ron << 16) | Roff;
+
+ R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
+ XclkFreq,
+ VclkFreq,
+ XclksPerTransfer,
+ XclksPerTransferPrecise,
+ UseablePrecision));
+ R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
+ Roff, Ron, info->ram->Rloop));
+
+ return TRUE;
+}
+
+
+#if 0
+/* Define initial palette for requested video mode. This doesn't do
+ anything for XFree86 4.0. */
+static void R128InitPalette(R128SavePtr save)
+{
+ save->palette_valid = FALSE;
+}
+#endif
+
+/* Define registers for a requested video mode. */
+static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ double dot_clock = mode->Clock/1000.0;
+
+#if R128_DEBUG
+ ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)",
+ mode->name,
+ dot_clock,
+
+ mode->HDisplay,
+ mode->HSyncStart,
+ mode->HSyncEnd,
+ mode->HTotal,
+
+ mode->VDisplay,
+ mode->VSyncStart,
+ mode->VSyncEnd,
+ mode->VTotal,
+ pScrn->depth,
+ pScrn->bitsPerPixel);
+ if (mode->Flags & V_DBLSCAN) ErrorF(" D");
+ if (mode->Flags & V_CSYNC) ErrorF(" C");
+ if (mode->Flags & V_INTERLACE) ErrorF(" I");
+ if (mode->Flags & V_PHSYNC) ErrorF(" +H");
+ if (mode->Flags & V_NHSYNC) ErrorF(" -H");
+ if (mode->Flags & V_PVSYNC) ErrorF(" +V");
+ if (mode->Flags & V_NVSYNC) ErrorF(" -V");
+ ErrorF("\n");
+ ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)",
+ mode->name,
+ dot_clock,
+
+ mode->CrtcHDisplay,
+ mode->CrtcHSyncStart,
+ mode->CrtcHSyncEnd,
+ mode->CrtcHTotal,
+
+ mode->CrtcVDisplay,
+ mode->CrtcVSyncStart,
+ mode->CrtcVSyncEnd,
+ mode->CrtcVTotal,
+ pScrn->depth,
+ pScrn->bitsPerPixel);
+ if (mode->Flags & V_DBLSCAN) ErrorF(" D");
+ if (mode->Flags & V_CSYNC) ErrorF(" C");
+ if (mode->Flags & V_INTERLACE) ErrorF(" I");
+ if (mode->Flags & V_PHSYNC) ErrorF(" +H");
+ if (mode->Flags & V_NHSYNC) ErrorF(" -H");
+ if (mode->Flags & V_PVSYNC) ErrorF(" +V");
+ if (mode->Flags & V_NVSYNC) ErrorF(" -V");
+ ErrorF("\n");
+#endif
+
+ info->Flags = mode->Flags;
+
+ R128InitCommonRegisters(save, info);
+ if (!R128InitCrtcRegisters(pScrn, save, mode, info)) return FALSE;
+ if (info->HasPanelRegs || info->isDFP)
+ R128InitFPRegisters(&info->SavedReg, save, mode, info);
+ if(dot_clock > 0){
+ R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock);
+ if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode))
+ return FALSE;
+ }
+ else{
+ save->ppll_ref_div = info->SavedReg.ppll_ref_div;
+ save->ppll_div_3 = info->SavedReg.ppll_div_3;
+ save->htotal_cntl = info->SavedReg.htotal_cntl;
+ save->dda_config = info->SavedReg.dda_config;
+ save->dda_on_off = info->SavedReg.dda_on_off;
+ }
+
+ R128TRACE(("R128Init returns %p\n", save));
+ return TRUE;
+}
+
+/* Initialize a new mode. */
+static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE;
+ /* FIXME? DRILock/DRIUnlock here? */
+ pScrn->vtSema = TRUE;
+ R128Blank(pScrn);
+ R128RestoreMode(pScrn, &info->ModeReg);
+ R128Unblank(pScrn);
+
+ info->CurrentLayout.mode = mode;
+
+ return TRUE;
+}
+
+static Bool R128SaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool unblank;
+
+ unblank = xf86IsUnblank(mode);
+ if (unblank)
+ SetTimeSinceLastInputEvent();
+
+ if ((pScrn != NULL) && pScrn->vtSema) {
+ if (unblank)
+ R128Unblank(pScrn);
+ else
+ R128Blank(pScrn);
+ }
+ return TRUE;
+}
+
+Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return R128ModeInit(xf86Screens[scrnIndex], mode);
+}
+
+/* Used to disallow modes that are not supported by the hardware. */
+int R128ValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flag)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ if(info->isDFP) {
+ if(info->PanelXRes < mode->CrtcHDisplay ||
+ info->PanelYRes < mode->CrtcVDisplay)
+ return MODE_NOMODE;
+ else
+ return MODE_OK;
+ }
+
+ if (info->HasPanelRegs) {
+ if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
+ if (mode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN;
+ }
+
+ if (info->HasPanelRegs &&
+ info->BIOSDisplay != R128_BIOS_DISPLAY_CRT &&
+ info->VBIOS) {
+ int i;
+ for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) {
+ int j = R128_BIOS16(i);
+
+ if (mode->CrtcHDisplay == R128_BIOS16(j) &&
+ mode->CrtcVDisplay == R128_BIOS16(j+2)) {
+ /* Assume we are using expanded mode */
+ if (R128_BIOS16(j+5)) j = R128_BIOS16(j+5);
+ else j += 9;
+
+ mode->Clock = (CARD32)R128_BIOS16(j) * 10;
+
+ mode->HDisplay = mode->CrtcHDisplay =
+ ((R128_BIOS16(j+10) & 0x01ff)+1)*8;
+ mode->HSyncStart = mode->CrtcHSyncStart =
+ ((R128_BIOS16(j+12) & 0x01ff)+1)*8;
+ mode->HSyncEnd = mode->CrtcHSyncEnd =
+ mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f);
+ mode->HTotal = mode->CrtcHTotal =
+ ((R128_BIOS16(j+8) & 0x01ff)+1)*8;
+
+ mode->VDisplay = mode->CrtcVDisplay =
+ (R128_BIOS16(j+17) & 0x07ff)+1;
+ mode->VSyncStart = mode->CrtcVSyncStart =
+ (R128_BIOS16(j+19) & 0x07ff)+1;
+ mode->VSyncEnd = mode->CrtcVSyncEnd =
+ mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f);
+ mode->VTotal = mode->CrtcVTotal =
+ (R128_BIOS16(j+15) & 0x07ff)+1;
+
+ return MODE_OK;
+ }
+ }
+ return MODE_NOMODE;
+ }
+
+ return MODE_OK;
+}
+
+/* Adjust viewport into virtual desktop such that (0,0) in viewport space
+ is (x,y) in virtual space. */
+void R128AdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int Base;
+
+ if(info->showCache && y && pScrn->vtSema)
+ y += pScrn->virtualY - 1;
+
+ Base = y * info->CurrentLayout.displayWidth + x;
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 15:
+ case 16: Base *= 2; break;
+ case 24: Base *= 3; break;
+ case 32: Base *= 4; break;
+ }
+
+ Base &= ~7; /* 3 lower bits are always 0 */
+
+ if (info->CurrentLayout.pixel_code == 24)
+ Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
+
+ OUTREG(R128_CRTC_OFFSET, Base);
+}
+
+/* Called when VT switching back to the X server. Reinitialize the video
+ mode. */
+Bool R128EnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ R128TRACE(("R128EnterVT\n"));
+ if (info->FBDev) {
+ if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
+ } else
+ if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ if (info->accelOn)
+ R128EngineInit(pScrn);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ if (info->irq) {
+ /* Need to make sure interrupts are enabled */
+ unsigned char *R128MMIO = info->MMIO;
+ OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
+ }
+ R128CCE_START(pScrn, info);
+ DRIUnlock(pScrn->pScreen);
+ }
+#endif
+
+ info->PaletteSavedOnVT = FALSE;
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return TRUE;
+}
+
+/* Called when VT switching away from the X server. Restore the original
+ text mode. */
+void R128LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+ R128SavePtr save = &info->ModeReg;
+
+ R128TRACE(("R128LeaveVT\n"));
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ DRILock(pScrn->pScreen, 0);
+ R128CCE_STOP(pScrn, info);
+ }
+#endif
+ R128SavePalette(pScrn, save);
+ info->PaletteSavedOnVT = TRUE;
+ if (info->FBDev)
+ fbdevHWLeaveVT(scrnIndex,flags);
+ else
+ R128Restore(pScrn);
+}
+
+
+/* Called at the end of each server generation. Restore the original text
+ mode, unmap video memory, and unwrap and call the saved CloseScreen
+ function. */
+static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ R128InfoPtr info = R128PTR(pScrn);
+
+ R128TRACE(("R128CloseScreen\n"));
+
+#ifdef XF86DRI
+ /* Disable direct rendering */
+ if (info->directRenderingEnabled) {
+ R128DRICloseScreen(pScreen);
+ info->directRenderingEnabled = FALSE;
+ }
+#endif
+
+ if (pScrn->vtSema) {
+ R128Restore(pScrn);
+ R128UnmapMem(pScrn);
+ }
+
+ if (info->accel) XAADestroyInfoRec(info->accel);
+ info->accel = NULL;
+
+ if (info->scratch_save) xfree(info->scratch_save);
+ info->scratch_save = NULL;
+
+ if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
+ info->cursor = NULL;
+
+ if (info->DGAModes) xfree(info->DGAModes);
+ info->DGAModes = NULL;
+
+ if (info->adaptor) {
+ xfree(info->adaptor->pPortPrivates[0].ptr);
+ xf86XVFreeVideoAdaptorRec(info->adaptor);
+ info->adaptor = NULL;
+ }
+
+ pScrn->vtSema = FALSE;
+
+ pScreen->BlockHandler = info->BlockHandler;
+ pScreen->CloseScreen = info->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+void R128FreeScreen(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ R128TRACE(("R128FreeScreen\n"));
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(pScrn);
+ R128FreeRec(pScrn);
+}
+
+/* Sets VESA Display Power Management Signaling (DPMS) Mode. */
+static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int mask = (R128_CRTC_DISPLAY_DIS
+ | R128_CRTC_HSYNC_DIS
+ | R128_CRTC_VSYNC_DIS);
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask);
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ OUTREGP(R128_CRTC_EXT_CNTL,
+ R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask);
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ OUTREGP(R128_CRTC_EXT_CNTL,
+ R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask);
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask);
+ break;
+ }
+}
+
+static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on);
+
+static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int mask = R128_LVDS_DISPLAY_DIS;
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask);
+ r128_set_backlight_enable(pScrn, 1);
+ break;
+ case DPMSModeStandby:
+ /* Fall through */
+ case DPMSModeSuspend:
+ /* Fall through */
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask);
+ r128_set_backlight_enable(pScrn, 0);
+ break;
+ }
+}
+
+static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL);
+
+ lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON);
+ if (on) {
+ lvds_gen_cntl |= R128_LVDS_DIGON;
+ if (!lvds_gen_cntl & R128_LVDS_ON) {
+ lvds_gen_cntl &= ~R128_LVDS_BLON;
+ OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
+ (void)INREG(R128_LVDS_GEN_CNTL);
+ usleep(10000);
+ lvds_gen_cntl |= R128_LVDS_BLON;
+ OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
+ }
+#if 0
+ lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
+ lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ <<
+ R128_LVDS_BL_MOD_LEVEL_SHIFT);
+#endif
+ lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN);
+ lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS;
+ } else {
+#if 0
+ lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
+ lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ <<
+ R128_LVDS_BL_MOD_LEVEL_SHIFT);
+#endif
+ lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS;
+ OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
+ usleep(10);
+ lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON
+ | R128_LVDS_DIGON);
+ }
+
+ OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
+
+ return 0;
+ }
diff --git a/src/r128_misc.c b/src/r128_misc.c
new file mode 100644
index 0000000..8841f34
--- /dev/null
+++ b/src/r128_misc.c
@@ -0,0 +1,87 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_misc.c,v 1.5 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef XFree86LOADER
+
+#include "ativersion.h"
+
+#include "r128_probe.h"
+#include "r128_version.h"
+
+#include "xf86.h"
+
+/* Module loader interface for subsidiary driver module */
+
+static XF86ModuleVersionInfo R128VersionRec =
+{
+ R128_DRIVER_NAME,
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ R128_VERSION_MAJOR, R128_VERSION_MINOR, R128_VERSION_PATCH,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * R128Setup --
+ *
+ * This function is called every time the module is loaded.
+ */
+static pointer
+R128Setup
+(
+ pointer Module,
+ pointer Options,
+ int *ErrorMajor,
+ int *ErrorMinor
+)
+{
+ static Bool Inited = FALSE;
+
+ if (!Inited)
+ {
+ /* Ensure main driver module is loaded, but not as a submodule */
+ if (!xf86ServerIsOnlyDetecting() && !LoaderSymbol(ATI_NAME))
+ xf86LoadOneModule(ATI_DRIVER_NAME, Options);
+
+ R128LoaderRefSymLists();
+
+ Inited = TRUE;
+ }
+
+ return (pointer)TRUE;
+}
+
+/* The following record must be called r128ModuleData */
+XF86ModuleData r128ModuleData =
+{
+ &R128VersionRec,
+ R128Setup,
+ NULL
+};
+
+#endif /* XFree86LOADER */
diff --git a/src/r128_probe.c b/src/r128_probe.c
new file mode 100644
index 0000000..a5cd42f
--- /dev/null
+++ b/src/r128_probe.c
@@ -0,0 +1,308 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c,v 1.18 2003/02/09 15:33:17 tsi Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
+ */
+
+#include "atimodule.h"
+#include "ativersion.h"
+
+#include "r128_probe.h"
+#include "r128_version.h"
+
+#include "xf86PciInfo.h"
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86Resources.h"
+
+#ifdef XFree86LOADER
+
+/*
+ * The following exists to prevent the compiler from considering entry points
+ * defined in a separate module from being constants.
+ */
+static xf86PreInitProc * const volatile PreInitProc = R128PreInit;
+static xf86ScreenInitProc * const volatile ScreenInitProc = R128ScreenInit;
+static xf86SwitchModeProc * const volatile SwitchModeProc = R128SwitchMode;
+static xf86AdjustFrameProc * const volatile AdjustFrameProc = R128AdjustFrame;
+static xf86EnterVTProc * const volatile EnterVTProc = R128EnterVT;
+static xf86LeaveVTProc * const volatile LeaveVTProc = R128LeaveVT;
+static xf86FreeScreenProc * const volatile FreeScreenProc = R128FreeScreen;
+static xf86ValidModeProc * const volatile ValidModeProc = R128ValidMode;
+
+#define R128PreInit PreInitProc
+#define R128ScreenInit ScreenInitProc
+#define R128SwitchMode SwitchModeProc
+#define R128AdjustFrame AdjustFrameProc
+#define R128EnterVT EnterVTProc
+#define R128LeaveVT LeaveVTProc
+#define R128FreeScreen FreeScreenProc
+#define R128ValidMode ValidModeProc
+
+#endif
+
+SymTabRec R128Chipsets[] = {
+ /* FIXME: The chipsets with (PCI/AGP) are not known wether they are AGP or
+ * PCI, so I've labeled them as such in hopes users will submit
+ * data if we're unable to gather it from official documentation
+ */
+ { PCI_CHIP_RAGE128LE, "ATI Rage 128 Mobility M3 LE (PCI)" },
+ { PCI_CHIP_RAGE128LF, "ATI Rage 128 Mobility M3 LF (AGP)" },
+ { PCI_CHIP_RAGE128MF, "ATI Rage 128 Mobility M4 MF (AGP)" },
+ { PCI_CHIP_RAGE128ML, "ATI Rage 128 Mobility M4 ML (AGP)" },
+ { PCI_CHIP_RAGE128PA, "ATI Rage 128 Pro GL PA (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PB, "ATI Rage 128 Pro GL PB (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PC, "ATI Rage 128 Pro GL PC (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PD, "ATI Rage 128 Pro GL PD (PCI)" },
+ { PCI_CHIP_RAGE128PE, "ATI Rage 128 Pro GL PE (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PF, "ATI Rage 128 Pro GL PF (AGP)" },
+ { PCI_CHIP_RAGE128PG, "ATI Rage 128 Pro VR PG (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PH, "ATI Rage 128 Pro VR PH (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PI, "ATI Rage 128 Pro VR PI (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PJ, "ATI Rage 128 Pro VR PJ (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PK, "ATI Rage 128 Pro VR PK (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PL, "ATI Rage 128 Pro VR PL (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PM, "ATI Rage 128 Pro VR PM (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PN, "ATI Rage 128 Pro VR PN (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PO, "ATI Rage 128 Pro VR PO (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PP, "ATI Rage 128 Pro VR PP (PCI)" },
+ { PCI_CHIP_RAGE128PQ, "ATI Rage 128 Pro VR PQ (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PR, "ATI Rage 128 Pro VR PR (PCI)" },
+ { PCI_CHIP_RAGE128PS, "ATI Rage 128 Pro VR PS (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PT, "ATI Rage 128 Pro VR PT (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PU, "ATI Rage 128 Pro VR PU (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PV, "ATI Rage 128 Pro VR PV (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PW, "ATI Rage 128 Pro VR PW (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PX, "ATI Rage 128 Pro VR PX (PCI/AGP)" },
+ { PCI_CHIP_RAGE128RE, "ATI Rage 128 GL RE (PCI)" },
+ { PCI_CHIP_RAGE128RF, "ATI Rage 128 GL RF (AGP)" },
+ { PCI_CHIP_RAGE128RG, "ATI Rage 128 RG (AGP)" },
+ { PCI_CHIP_RAGE128RK, "ATI Rage 128 VR RK (PCI)" },
+ { PCI_CHIP_RAGE128RL, "ATI Rage 128 VR RL (AGP)" },
+ { PCI_CHIP_RAGE128SE, "ATI Rage 128 4X SE (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SF, "ATI Rage 128 4X SF (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SG, "ATI Rage 128 4X SG (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SH, "ATI Rage 128 4X SH (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SK, "ATI Rage 128 4X SK (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SL, "ATI Rage 128 4X SL (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SM, "ATI Rage 128 4X SM (AGP)" },
+ { PCI_CHIP_RAGE128SN, "ATI Rage 128 4X SN (PCI/AGP)" },
+ { PCI_CHIP_RAGE128TF, "ATI Rage 128 Pro ULTRA TF (AGP)" },
+ { PCI_CHIP_RAGE128TL, "ATI Rage 128 Pro ULTRA TL (AGP)" },
+ { PCI_CHIP_RAGE128TR, "ATI Rage 128 Pro ULTRA TR (AGP)" },
+ { PCI_CHIP_RAGE128TS, "ATI Rage 128 Pro ULTRA TS (AGP?)" },
+ { PCI_CHIP_RAGE128TT, "ATI Rage 128 Pro ULTRA TT (AGP?)" },
+ { PCI_CHIP_RAGE128TU, "ATI Rage 128 Pro ULTRA TU (AGP?)" },
+ { -1, NULL }
+};
+
+PciChipsets R128PciChipsets[] = {
+ { PCI_CHIP_RAGE128LE, PCI_CHIP_RAGE128LE, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128LF, PCI_CHIP_RAGE128LF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128MF, PCI_CHIP_RAGE128MF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128ML, PCI_CHIP_RAGE128ML, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PA, PCI_CHIP_RAGE128PA, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PB, PCI_CHIP_RAGE128PB, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PC, PCI_CHIP_RAGE128PC, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PD, PCI_CHIP_RAGE128PD, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PE, PCI_CHIP_RAGE128PE, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PF, PCI_CHIP_RAGE128PF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PG, PCI_CHIP_RAGE128PG, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PH, PCI_CHIP_RAGE128PH, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PI, PCI_CHIP_RAGE128PI, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PJ, PCI_CHIP_RAGE128PJ, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PK, PCI_CHIP_RAGE128PK, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PL, PCI_CHIP_RAGE128PL, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PM, PCI_CHIP_RAGE128PM, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PN, PCI_CHIP_RAGE128PN, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PO, PCI_CHIP_RAGE128PO, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PP, PCI_CHIP_RAGE128PP, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PQ, PCI_CHIP_RAGE128PQ, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PR, PCI_CHIP_RAGE128PR, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PS, PCI_CHIP_RAGE128PS, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PT, PCI_CHIP_RAGE128PT, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PU, PCI_CHIP_RAGE128PU, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PV, PCI_CHIP_RAGE128PV, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PW, PCI_CHIP_RAGE128PW, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128PX, PCI_CHIP_RAGE128PX, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128RE, PCI_CHIP_RAGE128RE, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128RF, PCI_CHIP_RAGE128RF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128RG, PCI_CHIP_RAGE128RG, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128RK, PCI_CHIP_RAGE128RK, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128RL, PCI_CHIP_RAGE128RL, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SE, PCI_CHIP_RAGE128SE, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SF, PCI_CHIP_RAGE128SF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SG, PCI_CHIP_RAGE128SG, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SH, PCI_CHIP_RAGE128SH, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SK, PCI_CHIP_RAGE128SK, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SL, PCI_CHIP_RAGE128SL, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SM, PCI_CHIP_RAGE128SM, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128SN, PCI_CHIP_RAGE128SN, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TF, PCI_CHIP_RAGE128TF, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TL, PCI_CHIP_RAGE128TL, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TR, PCI_CHIP_RAGE128TR, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TS, PCI_CHIP_RAGE128TS, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TT, PCI_CHIP_RAGE128TT, RES_SHARED_VGA },
+ { PCI_CHIP_RAGE128TU, PCI_CHIP_RAGE128TU, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+/* Return the options for supported chipset 'n'; NULL otherwise */
+const OptionInfoRec *
+R128AvailableOptions(int chipid, int busid)
+{
+ int i;
+
+ /*
+ * Return options defined in the r128 submodule which will have been
+ * loaded by this point.
+ */
+ if ((chipid >> 16) == PCI_VENDOR_ATI)
+ chipid -= PCI_VENDOR_ATI << 16;
+ for (i = 0; R128PciChipsets[i].PCIid > 0; i++) {
+ if (chipid == R128PciChipsets[i].PCIid)
+ return R128Options;
+ }
+ return NULL;
+}
+
+/* Return the string name for supported chipset 'n'; NULL otherwise. */
+void
+R128Identify(int flags)
+{
+ xf86PrintChipsets(R128_NAME,
+ "Driver for ATI Rage 128 chipsets",
+ R128Chipsets);
+}
+
+/* Return TRUE if chipset is present; FALSE otherwise. */
+Bool
+R128Probe(DriverPtr drv, int flags)
+{
+ int numUsed;
+ int numDevSections, nATIGDev, nR128GDev;
+ int *usedChips;
+ GDevPtr *devSections, *ATIGDevs, *R128GDevs;
+ EntityInfoPtr pEnt;
+ Bool foundScreen = FALSE;
+ int i;
+
+ if (!xf86GetPciVideoInfo()) return FALSE;
+
+ /* Collect unclaimed device sections for both driver names */
+ nATIGDev = xf86MatchDevice(ATI_NAME, &ATIGDevs);
+ nR128GDev = xf86MatchDevice(R128_NAME, &R128GDevs);
+
+ if (!(numDevSections = nATIGDev + nR128GDev)) return FALSE;
+
+ if (!ATIGDevs) {
+ if (!(devSections = R128GDevs))
+ numDevSections = 1;
+ else
+ numDevSections = nR128GDev;
+ } if (!R128GDevs) {
+ devSections = ATIGDevs;
+ numDevSections = nATIGDev;
+ } else {
+ /* Combine into one list */
+ devSections = xnfalloc((numDevSections + 1) * sizeof(GDevPtr));
+ (void)memcpy(devSections,
+ ATIGDevs, nATIGDev * sizeof(GDevPtr));
+ (void)memcpy(devSections + nATIGDev,
+ R128GDevs, nR128GDev * sizeof(GDevPtr));
+ devSections[numDevSections] = NULL;
+ xfree(ATIGDevs);
+ xfree(R128GDevs);
+ }
+
+ numUsed = xf86MatchPciInstances(R128_NAME,
+ PCI_VENDOR_ATI,
+ R128Chipsets,
+ R128PciChipsets,
+ devSections,
+ numDevSections,
+ drv,
+ &usedChips);
+
+ if (numUsed<=0) return FALSE;
+
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ pEnt = xf86GetEntityInfo(usedChips[i]);
+
+ if (pEnt->active) {
+ ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0);
+
+#ifdef XFree86LOADER
+
+ if (!xf86LoadSubModule(pScrn, "r128")) {
+ xf86Msg(X_ERROR,
+ R128_NAME ": Failed to load \"r128\" module.\n");
+ xf86DeleteScreen(pScrn->scrnIndex, 0);
+ continue;
+ }
+
+ xf86LoaderReqSymLists(R128Symbols, NULL);
+
+#endif
+
+ pScrn->driverVersion = R128_VERSION_CURRENT;
+ pScrn->driverName = R128_DRIVER_NAME;
+ pScrn->name = R128_NAME;
+ pScrn->Probe = R128Probe;
+ pScrn->PreInit = R128PreInit;
+ pScrn->ScreenInit = R128ScreenInit;
+ pScrn->SwitchMode = R128SwitchMode;
+ pScrn->AdjustFrame = R128AdjustFrame;
+ pScrn->EnterVT = R128EnterVT;
+ pScrn->LeaveVT = R128LeaveVT;
+ pScrn->FreeScreen = R128FreeScreen;
+ pScrn->ValidMode = R128ValidMode;
+
+ foundScreen = TRUE;
+
+ xf86ConfigActivePciEntity(pScrn, usedChips[i], R128PciChipsets,
+ 0, 0, 0, 0, 0);
+ }
+ xfree(pEnt);
+ }
+
+ xfree(usedChips);
+ xfree(devSections);
+
+ return foundScreen;
+}
diff --git a/src/r128_probe.h b/src/r128_probe.h
new file mode 100644
index 0000000..094a9b6
--- /dev/null
+++ b/src/r128_probe.h
@@ -0,0 +1,78 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v 1.6 2002/04/06 19:06:06 tsi Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
+ */
+
+#ifndef _R128_PROBE_H_
+#define _R128_PROBE_H_ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+/* r128_probe.c */
+extern const OptionInfoRec * R128AvailableOptions
+ FunctionPrototype((int, int));
+extern void R128Identify
+ FunctionPrototype((int));
+extern Bool R128Probe
+ FunctionPrototype((DriverPtr, int));
+
+extern SymTabRec R128Chipsets[];
+extern PciChipsets R128PciChipsets[];
+
+/* r128_driver.c */
+extern void R128LoaderRefSymLists
+ FunctionPrototype((void));
+extern Bool R128PreInit
+ FunctionPrototype((ScrnInfoPtr, int));
+extern Bool R128ScreenInit
+ FunctionPrototype((int, ScreenPtr, int, char **));
+extern Bool R128SwitchMode
+ FunctionPrototype((int, DisplayModePtr, int));
+extern void R128AdjustFrame
+ FunctionPrototype((int, int, int, int));
+extern Bool R128EnterVT
+ FunctionPrototype((int, int));
+extern void R128LeaveVT
+ FunctionPrototype((int, int));
+extern void R128FreeScreen
+ FunctionPrototype((int, int));
+extern int R128ValidMode
+ FunctionPrototype((int, DisplayModePtr, Bool,
+ int));
+
+extern const OptionInfoRec R128Options[];
+
+#endif /* _R128_PROBE_H_ */
diff --git a/src/r128_reg.h b/src/r128_reg.h
new file mode 100644
index 0000000..3968bd5
--- /dev/null
+++ b/src/r128_reg.h
@@ -0,0 +1,1510 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.15 2002/12/16 16:19:11 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * References:
+ *
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+#ifndef _R128_REG_H_
+#define _R128_REG_H_
+
+#ifdef XFree86Module
+#include "xf86_ansic.h"
+#endif
+#include "compiler.h"
+
+ /* Memory mapped register access macros */
+#define INREG8(addr) MMIO_IN8(R128MMIO, addr)
+#define INREG16(addr) MMIO_IN16(R128MMIO, addr)
+#define INREG(addr) MMIO_IN32(R128MMIO, addr)
+#define OUTREG8(addr, val) MMIO_OUT8(R128MMIO, addr, val)
+#define OUTREG16(addr, val) MMIO_OUT16(R128MMIO, addr, val)
+#define OUTREG(addr, val) MMIO_OUT32(R128MMIO, addr, val)
+
+#define ADDRREG(addr) ((volatile CARD32 *)(pointer)(R128MMIO + (addr)))
+
+
+#define OUTREGP(addr, val, mask) \
+ do { \
+ CARD32 tmp = INREG(addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTREG(addr, tmp); \
+ } while (0)
+
+#define INPLL(pScrn, addr) R128INPLL(pScrn, addr)
+
+#define OUTPLL(addr, val) \
+ do { \
+ OUTREG8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \
+ OUTREG(R128_CLOCK_CNTL_DATA, val); \
+ } while (0)
+
+#define OUTPLLP(pScrn, addr, val, mask) \
+ do { \
+ CARD32 tmp = INPLL(pScrn, addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTPLL(addr, tmp); \
+ } while (0)
+
+#define OUTPAL_START(idx) \
+ do { \
+ OUTREG8(R128_PALETTE_INDEX, (idx)); \
+ } while (0)
+
+#define OUTPAL_NEXT(r, g, b) \
+ do { \
+ OUTREG(R128_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
+ } while (0)
+
+#define OUTPAL_NEXT_CARD32(v) \
+ do { \
+ OUTREG(R128_PALETTE_DATA, (v & 0x00ffffff)); \
+ } while (0)
+
+#define OUTPAL(idx, r, g, b) \
+ do { \
+ OUTPAL_START((idx)); \
+ OUTPAL_NEXT((r), (g), (b)); \
+ } while (0)
+
+#define INPAL_START(idx) \
+ do { \
+ OUTREG(R128_PALETTE_INDEX, (idx) << 16); \
+ } while (0)
+
+#define INPAL_NEXT() INREG(R128_PALETTE_DATA)
+
+#define PAL_SELECT(idx) \
+ do { \
+ CARD32 tmp = INREG(R128_DAC_CNTL); \
+ if (idx) { \
+ OUTREG(R128_DAC_CNTL, tmp | R128_DAC_PALETTE_ACC_CTL); \
+ } else { \
+ OUTREG(R128_DAC_CNTL, tmp & \
+ (CARD32)~R128_DAC_PALETTE_ACC_CTL); \
+ } \
+ } while (0)
+
+#define R128_ADAPTER_ID 0x0f2c /* PCI */
+#define R128_AGP_APER_OFFSET 0x0178
+#define R128_AGP_BASE 0x0170
+#define R128_AGP_CNTL 0x0174
+# define R128_AGP_APER_SIZE_256MB (0x00 << 0)
+# define R128_AGP_APER_SIZE_128MB (0x20 << 0)
+# define R128_AGP_APER_SIZE_64MB (0x30 << 0)
+# define R128_AGP_APER_SIZE_32MB (0x38 << 0)
+# define R128_AGP_APER_SIZE_16MB (0x3c << 0)
+# define R128_AGP_APER_SIZE_8MB (0x3e << 0)
+# define R128_AGP_APER_SIZE_4MB (0x3f << 0)
+# define R128_AGP_APER_SIZE_MASK (0x3f << 0)
+#define R128_AGP_CNTL_B 0x0b44
+#define R128_AGP_COMMAND 0x0f58 /* PCI */
+#define R128_AGP_PLL_CNTL 0x0010 /* PLL */
+#define R128_AGP_STATUS 0x0f54 /* PCI */
+# define R128_AGP_1X_MODE 0x01
+# define R128_AGP_2X_MODE 0x02
+# define R128_AGP_4X_MODE 0x04
+# define R128_AGP_MODE_MASK 0x07
+#define R128_AMCGPIO_A_REG 0x01a0
+#define R128_AMCGPIO_EN_REG 0x01a8
+#define R128_AMCGPIO_MASK 0x0194
+#define R128_AMCGPIO_Y_REG 0x01a4
+#define R128_ATTRDR 0x03c1 /* VGA */
+#define R128_ATTRDW 0x03c0 /* VGA */
+#define R128_ATTRX 0x03c0 /* VGA */
+#define R128_AUX_SC_CNTL 0x1660
+# define R128_AUX1_SC_EN (1 << 0)
+# define R128_AUX1_SC_MODE_OR (0 << 1)
+# define R128_AUX1_SC_MODE_NAND (1 << 1)
+# define R128_AUX2_SC_EN (1 << 2)
+# define R128_AUX2_SC_MODE_OR (0 << 3)
+# define R128_AUX2_SC_MODE_NAND (1 << 3)
+# define R128_AUX3_SC_EN (1 << 4)
+# define R128_AUX3_SC_MODE_OR (0 << 5)
+# define R128_AUX3_SC_MODE_NAND (1 << 5)
+#define R128_AUX1_SC_BOTTOM 0x1670
+#define R128_AUX1_SC_LEFT 0x1664
+#define R128_AUX1_SC_RIGHT 0x1668
+#define R128_AUX1_SC_TOP 0x166c
+#define R128_AUX2_SC_BOTTOM 0x1680
+#define R128_AUX2_SC_LEFT 0x1674
+#define R128_AUX2_SC_RIGHT 0x1678
+#define R128_AUX2_SC_TOP 0x167c
+#define R128_AUX3_SC_BOTTOM 0x1690
+#define R128_AUX3_SC_LEFT 0x1684
+#define R128_AUX3_SC_RIGHT 0x1688
+#define R128_AUX3_SC_TOP 0x168c
+#define R128_AUX_WINDOW_HORZ_CNTL 0x02d8
+#define R128_AUX_WINDOW_VERT_CNTL 0x02dc
+
+#define R128_BASE_CODE 0x0f0b
+#define R128_BIOS_0_SCRATCH 0x0010
+#define R128_BIOS_1_SCRATCH 0x0014
+#define R128_BIOS_2_SCRATCH 0x0018
+#define R128_BIOS_3_SCRATCH 0x001c
+#define R128_BIOS_4_SCRATCH 0x0020
+#define R128_BIOS_5_SCRATCH 0x0024
+# define R128_BIOS_DISPLAY_FP (1 << 0)
+# define R128_BIOS_DISPLAY_CRT (2 << 0)
+# define R128_BIOS_DISPLAY_FP_CRT (3 << 0)
+#define R128_BIOS_6_SCRATCH 0x0028
+#define R128_BIOS_7_SCRATCH 0x002c
+#define R128_BIOS_ROM 0x0f30 /* PCI */
+#define R128_BIST 0x0f0f /* PCI */
+#define R128_BM_CHUNK_0_VAL 0x0a18
+# define R128_BM_PTR_FORCE_TO_PCI (1 << 21)
+# define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22)
+# define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23)
+#define R128_BRUSH_DATA0 0x1480
+#define R128_BRUSH_DATA1 0x1484
+#define R128_BRUSH_DATA10 0x14a8
+#define R128_BRUSH_DATA11 0x14ac
+#define R128_BRUSH_DATA12 0x14b0
+#define R128_BRUSH_DATA13 0x14b4
+#define R128_BRUSH_DATA14 0x14b8
+#define R128_BRUSH_DATA15 0x14bc
+#define R128_BRUSH_DATA16 0x14c0
+#define R128_BRUSH_DATA17 0x14c4
+#define R128_BRUSH_DATA18 0x14c8
+#define R128_BRUSH_DATA19 0x14cc
+#define R128_BRUSH_DATA2 0x1488
+#define R128_BRUSH_DATA20 0x14d0
+#define R128_BRUSH_DATA21 0x14d4
+#define R128_BRUSH_DATA22 0x14d8
+#define R128_BRUSH_DATA23 0x14dc
+#define R128_BRUSH_DATA24 0x14e0
+#define R128_BRUSH_DATA25 0x14e4
+#define R128_BRUSH_DATA26 0x14e8
+#define R128_BRUSH_DATA27 0x14ec
+#define R128_BRUSH_DATA28 0x14f0
+#define R128_BRUSH_DATA29 0x14f4
+#define R128_BRUSH_DATA3 0x148c
+#define R128_BRUSH_DATA30 0x14f8
+#define R128_BRUSH_DATA31 0x14fc
+#define R128_BRUSH_DATA32 0x1500
+#define R128_BRUSH_DATA33 0x1504
+#define R128_BRUSH_DATA34 0x1508
+#define R128_BRUSH_DATA35 0x150c
+#define R128_BRUSH_DATA36 0x1510
+#define R128_BRUSH_DATA37 0x1514
+#define R128_BRUSH_DATA38 0x1518
+#define R128_BRUSH_DATA39 0x151c
+#define R128_BRUSH_DATA4 0x1490
+#define R128_BRUSH_DATA40 0x1520
+#define R128_BRUSH_DATA41 0x1524
+#define R128_BRUSH_DATA42 0x1528
+#define R128_BRUSH_DATA43 0x152c
+#define R128_BRUSH_DATA44 0x1530
+#define R128_BRUSH_DATA45 0x1534
+#define R128_BRUSH_DATA46 0x1538
+#define R128_BRUSH_DATA47 0x153c
+#define R128_BRUSH_DATA48 0x1540
+#define R128_BRUSH_DATA49 0x1544
+#define R128_BRUSH_DATA5 0x1494
+#define R128_BRUSH_DATA50 0x1548
+#define R128_BRUSH_DATA51 0x154c
+#define R128_BRUSH_DATA52 0x1550
+#define R128_BRUSH_DATA53 0x1554
+#define R128_BRUSH_DATA54 0x1558
+#define R128_BRUSH_DATA55 0x155c
+#define R128_BRUSH_DATA56 0x1560
+#define R128_BRUSH_DATA57 0x1564
+#define R128_BRUSH_DATA58 0x1568
+#define R128_BRUSH_DATA59 0x156c
+#define R128_BRUSH_DATA6 0x1498
+#define R128_BRUSH_DATA60 0x1570
+#define R128_BRUSH_DATA61 0x1574
+#define R128_BRUSH_DATA62 0x1578
+#define R128_BRUSH_DATA63 0x157c
+#define R128_BRUSH_DATA7 0x149c
+#define R128_BRUSH_DATA8 0x14a0
+#define R128_BRUSH_DATA9 0x14a4
+#define R128_BRUSH_SCALE 0x1470
+#define R128_BRUSH_Y_X 0x1474
+#define R128_BUS_CNTL 0x0030
+# define R128_BUS_MASTER_DIS (1 << 6)
+# define R128_BUS_RD_DISCARD_EN (1 << 24)
+# define R128_BUS_RD_ABORT_EN (1 << 25)
+# define R128_BUS_MSTR_DISCONNECT_EN (1 << 28)
+# define R128_BUS_WRT_BURST (1 << 29)
+# define R128_BUS_READ_BURST (1 << 30)
+#define R128_BUS_CNTL1 0x0034
+# define R128_BUS_WAIT_ON_LOCK_EN (1 << 4)
+
+#define R128_CACHE_CNTL 0x1724
+#define R128_CACHE_LINE 0x0f0c /* PCI */
+#define R128_CAP0_TRIG_CNTL 0x0950 /* ? */
+#define R128_CAP1_TRIG_CNTL 0x09c0 /* ? */
+#define R128_CAPABILITIES_ID 0x0f50 /* PCI */
+#define R128_CAPABILITIES_PTR 0x0f34 /* PCI */
+#define R128_CLK_PIN_CNTL 0x0001 /* PLL */
+#define R128_CLOCK_CNTL_DATA 0x000c
+#define R128_CLOCK_CNTL_INDEX 0x0008
+# define R128_PLL_WR_EN (1 << 7)
+# define R128_PLL_DIV_SEL (3 << 8)
+#define R128_CLR_CMP_CLR_3D 0x1a24
+#define R128_CLR_CMP_CLR_DST 0x15c8
+#define R128_CLR_CMP_CLR_SRC 0x15c4
+#define R128_CLR_CMP_CNTL 0x15c0
+# define R128_SRC_CMP_EQ_COLOR (4 << 0)
+# define R128_SRC_CMP_NEQ_COLOR (5 << 0)
+# define R128_CLR_CMP_SRC_SOURCE (1 << 24)
+#define R128_CLR_CMP_MASK 0x15cc
+# define R128_CLR_CMP_MSK 0xffffffff
+#define R128_CLR_CMP_MASK_3D 0x1A28
+#define R128_COMMAND 0x0f04 /* PCI */
+#define R128_COMPOSITE_SHADOW_ID 0x1a0c
+#define R128_CONFIG_APER_0_BASE 0x0100
+#define R128_CONFIG_APER_1_BASE 0x0104
+#define R128_CONFIG_APER_SIZE 0x0108
+#define R128_CONFIG_BONDS 0x00e8
+#define R128_CONFIG_CNTL 0x00e0
+# define APER_0_BIG_ENDIAN_16BPP_SWAP (1 << 0)
+# define APER_0_BIG_ENDIAN_32BPP_SWAP (2 << 0)
+#define R128_CONFIG_MEMSIZE 0x00f8
+#define R128_CONFIG_MEMSIZE_EMBEDDED 0x0114
+#define R128_CONFIG_REG_1_BASE 0x010c
+#define R128_CONFIG_REG_APER_SIZE 0x0110
+#define R128_CONFIG_XSTRAP 0x00e4
+#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_COLOR_MASK 0x00ffffff
+# define R128_CONSTANT_COLOR_ONE 0x00ffffff
+# define R128_CONSTANT_COLOR_ZERO 0x00000000
+#define R128_CRC_CMDFIFO_ADDR 0x0740
+#define R128_CRC_CMDFIFO_DOUT 0x0744
+#define R128_CRTC_CRNT_FRAME 0x0214
+#define R128_CRTC_DEBUG 0x021c
+#define R128_CRTC_EXT_CNTL 0x0054
+# define R128_CRTC_VGA_XOVERSCAN (1 << 0)
+# define R128_VGA_ATI_LINEAR (1 << 3)
+# define R128_XCRT_CNT_EN (1 << 6)
+# define R128_CRTC_HSYNC_DIS (1 << 8)
+# define R128_CRTC_VSYNC_DIS (1 << 9)
+# define R128_CRTC_DISPLAY_DIS (1 << 10)
+# define R128_CRTC_CRT_ON (1 << 15)
+# define R128_FP_OUT_EN (1 << 22)
+# define R128_FP_ACTIVE (1 << 23)
+#define R128_CRTC_EXT_CNTL_DPMS_BYTE 0x0055
+# define R128_CRTC_HSYNC_DIS_BYTE (1 << 0)
+# define R128_CRTC_VSYNC_DIS_BYTE (1 << 1)
+# define R128_CRTC_DISPLAY_DIS_BYTE (1 << 2)
+#define R128_CRTC_GEN_CNTL 0x0050
+# define R128_CRTC_DBL_SCAN_EN (1 << 0)
+# define R128_CRTC_INTERLACE_EN (1 << 1)
+# define R128_CRTC_CSYNC_EN (1 << 4)
+# define R128_CRTC_CUR_EN (1 << 16)
+# define R128_CRTC_CUR_MODE_MASK (7 << 17)
+# define R128_CRTC_ICON_EN (1 << 20)
+# define R128_CRTC_EXT_DISP_EN (1 << 24)
+# define R128_CRTC_EN (1 << 25)
+# define R128_CRTC_DISP_REQ_EN_B (1 << 26)
+#define R128_CRTC_GUI_TRIG_VLINE 0x0218
+#define R128_CRTC_H_SYNC_STRT_WID 0x0204
+# define R128_CRTC_H_SYNC_STRT_PIX (0x07 << 0)
+# define R128_CRTC_H_SYNC_STRT_CHAR (0x1ff << 3)
+# define R128_CRTC_H_SYNC_STRT_CHAR_SHIFT 3
+# define R128_CRTC_H_SYNC_WID (0x3f << 16)
+# define R128_CRTC_H_SYNC_WID_SHIFT 16
+# define R128_CRTC_H_SYNC_POL (1 << 23)
+#define R128_CRTC_H_TOTAL_DISP 0x0200
+# define R128_CRTC_H_TOTAL (0x01ff << 0)
+# define R128_CRTC_H_TOTAL_SHIFT 0
+# define R128_CRTC_H_DISP (0x00ff << 16)
+# define R128_CRTC_H_DISP_SHIFT 16
+#define R128_CRTC_OFFSET 0x0224
+#define R128_CRTC_OFFSET_CNTL 0x0228
+#define R128_CRTC_PITCH 0x022c
+#define R128_CRTC_STATUS 0x005c
+# define R128_CRTC_VBLANK_SAVE (1 << 1)
+#define R128_CRTC_V_SYNC_STRT_WID 0x020c
+# define R128_CRTC_V_SYNC_STRT (0x7ff << 0)
+# define R128_CRTC_V_SYNC_STRT_SHIFT 0
+# define R128_CRTC_V_SYNC_WID (0x1f << 16)
+# define R128_CRTC_V_SYNC_WID_SHIFT 16
+# define R128_CRTC_V_SYNC_POL (1 << 23)
+#define R128_CRTC_V_TOTAL_DISP 0x0208
+# define R128_CRTC_V_TOTAL (0x07ff << 0)
+# define R128_CRTC_V_TOTAL_SHIFT 0
+# define R128_CRTC_V_DISP (0x07ff << 16)
+# define R128_CRTC_V_DISP_SHIFT 16
+#define R128_CRTC_VLINE_CRNT_VLINE 0x0210
+# define R128_CRTC_CRNT_VLINE_MASK (0x7ff << 16)
+#define R128_CRTC2_CRNT_FRAME 0x0314
+#define R128_CRTC2_DEBUG 0x031c
+#define R128_CRTC2_GEN_CNTL 0x03f8
+#define R128_CRTC2_GUI_TRIG_VLINE 0x0318
+#define R128_CRTC2_H_SYNC_STRT_WID 0x0304
+#define R128_CRTC2_H_TOTAL_DISP 0x0300
+#define R128_CRTC2_OFFSET 0x0324
+#define R128_CRTC2_OFFSET_CNTL 0x0328
+#define R128_CRTC2_PITCH 0x032c
+#define R128_CRTC2_STATUS 0x03fc
+#define R128_CRTC2_V_SYNC_STRT_WID 0x030c
+#define R128_CRTC2_V_TOTAL_DISP 0x0308
+#define R128_CRTC2_VLINE_CRNT_VLINE 0x0310
+#define R128_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */
+#define R128_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */
+#define R128_CUR_CLR0 0x026c
+#define R128_CUR_CLR1 0x0270
+#define R128_CUR_HORZ_VERT_OFF 0x0268
+#define R128_CUR_HORZ_VERT_POSN 0x0264
+#define R128_CUR_OFFSET 0x0260
+# define R128_CUR_LOCK (1 << 31)
+
+#define R128_DAC_CNTL 0x0058
+# define R128_DAC_RANGE_CNTL (3 << 0)
+# define R128_DAC_BLANKING (1 << 2)
+# define R128_DAC_CRT_SEL_CRTC2 (1 << 4)
+# define R128_DAC_PALETTE_ACC_CTL (1 << 5)
+# define R128_DAC_8BIT_EN (1 << 8)
+# define R128_DAC_VGA_ADR_EN (1 << 13)
+# define R128_DAC_MASK_ALL (0xff << 24)
+#define R128_DAC_CRC_SIG 0x02cc
+#define R128_DAC_DATA 0x03c9 /* VGA */
+#define R128_DAC_MASK 0x03c6 /* VGA */
+#define R128_DAC_R_INDEX 0x03c7 /* VGA */
+#define R128_DAC_W_INDEX 0x03c8 /* VGA */
+#define R128_DDA_CONFIG 0x02e0
+#define R128_DDA_ON_OFF 0x02e4
+#define R128_DEFAULT_OFFSET 0x16e0
+#define R128_DEFAULT_PITCH 0x16e4
+#define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
+# define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0)
+# define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
+#define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820
+#define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824
+#define R128_DEVICE_ID 0x0f02 /* PCI */
+#define R128_DP_BRUSH_BKGD_CLR 0x1478
+#define R128_DP_BRUSH_FRGD_CLR 0x147c
+#define R128_DP_CNTL 0x16c0
+# define R128_DST_X_LEFT_TO_RIGHT (1 << 0)
+# define R128_DST_Y_TOP_TO_BOTTOM (1 << 1)
+#define R128_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0
+# define R128_DST_Y_MAJOR (1 << 2)
+# define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
+# define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
+#define R128_DP_DATATYPE 0x16c4
+# define R128_HOST_BIG_ENDIAN_EN (1 << 29)
+#define R128_DP_GUI_MASTER_CNTL 0x146c
+# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define R128_GMC_SRC_CLIPPING (1 << 2)
+# define R128_GMC_DST_CLIPPING (1 << 3)
+# define R128_GMC_BRUSH_DATATYPE_MASK (0x0f << 4)
+# define R128_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4)
+# define R128_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4)
+# define R128_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4)
+# define R128_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4)
+# define R128_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4)
+# define R128_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4)
+# define R128_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4)
+# define R128_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4)
+# define R128_GMC_BRUSH_8x8_COLOR (10 << 4)
+# define R128_GMC_BRUSH_1X8_COLOR (12 << 4)
+# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define R128_GMC_BRUSH_NONE (15 << 4)
+# define R128_GMC_DST_8BPP_CI (2 << 8)
+# define R128_GMC_DST_15BPP (3 << 8)
+# define R128_GMC_DST_16BPP (4 << 8)
+# define R128_GMC_DST_24BPP (5 << 8)
+# define R128_GMC_DST_32BPP (6 << 8)
+# define R128_GMC_DST_8BPP_RGB (7 << 8)
+# define R128_GMC_DST_Y8 (8 << 8)
+# define R128_GMC_DST_RGB8 (9 << 8)
+# define R128_GMC_DST_VYUY (11 << 8)
+# define R128_GMC_DST_YVYU (12 << 8)
+# define R128_GMC_DST_AYUV444 (14 << 8)
+# define R128_GMC_DST_ARGB4444 (15 << 8)
+# define R128_GMC_DST_DATATYPE_MASK (0x0f << 8)
+# define R128_GMC_DST_DATATYPE_SHIFT 8
+# define R128_GMC_SRC_DATATYPE_MASK (3 << 12)
+# define R128_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12)
+# define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12)
+# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define R128_GMC_BYTE_PIX_ORDER (1 << 14)
+# define R128_GMC_BYTE_MSB_TO_LSB (0 << 14)
+# define R128_GMC_BYTE_LSB_TO_MSB (1 << 14)
+# define R128_GMC_CONVERSION_TEMP (1 << 15)
+# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15)
+# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15)
+# define R128_GMC_ROP3_MASK (0xff << 16)
+# define R128_DP_SRC_SOURCE_MASK (7 << 24)
+# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
+# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24)
+# define R128_GMC_3D_FCN_EN (1 << 27)
+# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define R128_GMC_AUX_CLIP_DIS (1 << 29)
+# define R128_GMC_WR_MSK_DIS (1 << 30)
+# define R128_GMC_LD_BRUSH_Y_X (1 << 31)
+# define R128_ROP3_ZERO 0x00000000
+# define R128_ROP3_DSa 0x00880000
+# define R128_ROP3_SDna 0x00440000
+# define R128_ROP3_S 0x00cc0000
+# define R128_ROP3_DSna 0x00220000
+# define R128_ROP3_D 0x00aa0000
+# define R128_ROP3_DSx 0x00660000
+# define R128_ROP3_DSo 0x00ee0000
+# define R128_ROP3_DSon 0x00110000
+# define R128_ROP3_DSxn 0x00990000
+# define R128_ROP3_Dn 0x00550000
+# define R128_ROP3_SDno 0x00dd0000
+# define R128_ROP3_Sn 0x00330000
+# define R128_ROP3_DSno 0x00bb0000
+# define R128_ROP3_DSan 0x00770000
+# define R128_ROP3_ONE 0x00ff0000
+# define R128_ROP3_DPa 0x00a00000
+# define R128_ROP3_PDna 0x00500000
+# define R128_ROP3_P 0x00f00000
+# define R128_ROP3_DPna 0x000a0000
+# define R128_ROP3_D 0x00aa0000
+# define R128_ROP3_DPx 0x005a0000
+# define R128_ROP3_DPo 0x00fa0000
+# define R128_ROP3_DPon 0x00050000
+# define R128_ROP3_PDxn 0x00a50000
+# define R128_ROP3_PDno 0x00f50000
+# define R128_ROP3_Pn 0x000f0000
+# define R128_ROP3_DPno 0x00af0000
+# define R128_ROP3_DPan 0x005f0000
+
+
+#define R128_DP_GUI_MASTER_CNTL_C 0x1c84
+#define R128_DP_MIX 0x16c8
+#define R128_DP_SRC_BKGD_CLR 0x15dc
+#define R128_DP_SRC_FRGD_CLR 0x15d8
+#define R128_DP_WRITE_MASK 0x16cc
+#define R128_DST_BRES_DEC 0x1630
+#define R128_DST_BRES_ERR 0x1628
+#define R128_DST_BRES_INC 0x162c
+#define R128_DST_BRES_LNTH 0x1634
+#define R128_DST_BRES_LNTH_SUB 0x1638
+#define R128_DST_HEIGHT 0x1410
+#define R128_DST_HEIGHT_WIDTH 0x143c
+#define R128_DST_HEIGHT_WIDTH_8 0x158c
+#define R128_DST_HEIGHT_WIDTH_BW 0x15b4
+#define R128_DST_HEIGHT_Y 0x15a0
+#define R128_DST_OFFSET 0x1404
+#define R128_DST_PITCH 0x1408
+#define R128_DST_PITCH_OFFSET 0x142c
+#define R128_DST_PITCH_OFFSET_C 0x1c80
+# define R128_PITCH_SHIFT 21
+# define R128_DST_TILE (1 << 31)
+#define R128_DST_WIDTH 0x140c
+#define R128_DST_WIDTH_HEIGHT 0x1598
+#define R128_DST_WIDTH_X 0x1588
+#define R128_DST_WIDTH_X_INCY 0x159c
+#define R128_DST_X 0x141c
+#define R128_DST_X_SUB 0x15a4
+#define R128_DST_X_Y 0x1594
+#define R128_DST_Y 0x1420
+#define R128_DST_Y_SUB 0x15a8
+#define R128_DST_Y_X 0x1438
+
+#define R128_EXT_MEM_CNTL 0x0144
+
+#define R128_FCP_CNTL 0x0012 /* PLL */
+#define R128_FLUSH_1 0x1704
+#define R128_FLUSH_2 0x1708
+#define R128_FLUSH_3 0x170c
+#define R128_FLUSH_4 0x1710
+#define R128_FLUSH_5 0x1714
+#define R128_FLUSH_6 0x1718
+#define R128_FLUSH_7 0x171c
+#define R128_FOG_3D_TABLE_START 0x1810
+#define R128_FOG_3D_TABLE_END 0x1814
+#define R128_FOG_3D_TABLE_DENSITY 0x181c
+#define R128_FOG_TABLE_INDEX 0x1a14
+#define R128_FOG_TABLE_DATA 0x1a18
+#define R128_FP_CRTC_H_TOTAL_DISP 0x0250
+#define R128_FP_CRTC_V_TOTAL_DISP 0x0254
+#define R128_FP_GEN_CNTL 0x0284
+# define R128_FP_FPON (1 << 0)
+# define R128_FP_BLANK_DIS (1 << 1)
+# define R128_FP_TDMS_EN (1 << 2)
+# define R128_FP_DETECT_SENSE (1 << 8)
+# define R128_FP_SEL_CRTC2 (1 << 13)
+# define R128_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
+# define R128_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
+# define R128_FP_CRTC_USE_SHADOW_VEND (1 << 18)
+# define R128_FP_CRTC_USE_SHADOW_ROWCUR (1 << 19)
+# define R128_FP_CRTC_HORZ_DIV2_EN (1 << 20)
+# define R128_FP_CRTC_HOR_CRT_DIV2_DIS (1 << 21)
+# define R128_FP_CRT_SYNC_SEL (1 << 23)
+# define R128_FP_USE_SHADOW_EN (1 << 24)
+#define R128_FP_H_SYNC_STRT_WID 0x02c4
+#define R128_FP_HORZ_STRETCH 0x028c
+# define R128_HORZ_STRETCH_RATIO_MASK 0xffff
+# define R128_HORZ_STRETCH_RATIO_SHIFT 0
+# define R128_HORZ_STRETCH_RATIO_MAX 4096
+# define R128_HORZ_PANEL_SIZE (0xff << 16)
+# define R128_HORZ_PANEL_SHIFT 16
+# define R128_AUTO_HORZ_RATIO (0 << 24)
+# define R128_HORZ_STRETCH_PIXREP (0 << 25)
+# define R128_HORZ_STRETCH_BLEND (1 << 25)
+# define R128_HORZ_STRETCH_ENABLE (1 << 26)
+# define R128_HORZ_FP_LOOP_STRETCH (0x7 << 27)
+# define R128_HORZ_STRETCH_RESERVED (1 << 30)
+# define R128_HORZ_AUTO_RATIO_FIX_EN (1 << 31)
+
+#define R128_FP_PANEL_CNTL 0x0288
+# define R128_FP_DIGON (1 << 0)
+# define R128_FP_BLON (1 << 1)
+#define R128_FP_V_SYNC_STRT_WID 0x02c8
+#define R128_FP_VERT_STRETCH 0x0290
+# define R128_VERT_PANEL_SIZE (0x7ff << 0)
+# define R128_VERT_PANEL_SHIFT 0
+# define R128_VERT_STRETCH_RATIO_MASK 0x3ff
+# define R128_VERT_STRETCH_RATIO_SHIFT 11
+# define R128_VERT_STRETCH_RATIO_MAX 1024
+# define R128_VERT_STRETCH_ENABLE (1 << 24)
+# define R128_VERT_STRETCH_LINEREP (0 << 25)
+# define R128_VERT_STRETCH_BLEND (1 << 25)
+# define R128_VERT_AUTO_RATIO_EN (1 << 26)
+# define R128_VERT_STRETCH_RESERVED 0xf8e00000
+
+#define R128_GEN_INT_CNTL 0x0040
+#define R128_GEN_INT_STATUS 0x0044
+# define R128_VSYNC_INT_AK (1 << 2)
+# define R128_VSYNC_INT (1 << 2)
+#define R128_GEN_RESET_CNTL 0x00f0
+# define R128_SOFT_RESET_GUI (1 << 0)
+# define R128_SOFT_RESET_VCLK (1 << 8)
+# define R128_SOFT_RESET_PCLK (1 << 9)
+# define R128_SOFT_RESET_DISPENG_XCLK (1 << 11)
+# define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12)
+#define R128_GENENB 0x03c3 /* VGA */
+#define R128_GENFC_RD 0x03ca /* VGA */
+#define R128_GENFC_WT 0x03da /* VGA, 0x03ba */
+#define R128_GENMO_RD 0x03cc /* VGA */
+#define R128_GENMO_WT 0x03c2 /* VGA */
+#define R128_GENS0 0x03c2 /* VGA */
+#define R128_GENS1 0x03da /* VGA, 0x03ba */
+#define R128_GPIO_MONID 0x0068
+# define R128_GPIO_MONID_A_0 (1 << 0)
+# define R128_GPIO_MONID_A_1 (1 << 1)
+# define R128_GPIO_MONID_A_2 (1 << 2)
+# define R128_GPIO_MONID_A_3 (1 << 3)
+# define R128_GPIO_MONID_Y_0 (1 << 8)
+# define R128_GPIO_MONID_Y_1 (1 << 9)
+# define R128_GPIO_MONID_Y_2 (1 << 10)
+# define R128_GPIO_MONID_Y_3 (1 << 11)
+# define R128_GPIO_MONID_EN_0 (1 << 16)
+# define R128_GPIO_MONID_EN_1 (1 << 17)
+# define R128_GPIO_MONID_EN_2 (1 << 18)
+# define R128_GPIO_MONID_EN_3 (1 << 19)
+# define R128_GPIO_MONID_MASK_0 (1 << 24)
+# define R128_GPIO_MONID_MASK_1 (1 << 25)
+# define R128_GPIO_MONID_MASK_2 (1 << 26)
+# define R128_GPIO_MONID_MASK_3 (1 << 27)
+#define R128_GPIO_MONIDB 0x006c
+#define R128_GRPH8_DATA 0x03cf /* VGA */
+#define R128_GRPH8_IDX 0x03ce /* VGA */
+#define R128_GUI_DEBUG0 0x16a0
+#define R128_GUI_DEBUG1 0x16a4
+#define R128_GUI_DEBUG2 0x16a8
+#define R128_GUI_DEBUG3 0x16ac
+#define R128_GUI_DEBUG4 0x16b0
+#define R128_GUI_DEBUG5 0x16b4
+#define R128_GUI_DEBUG6 0x16b8
+#define R128_GUI_PROBE 0x16bc
+#define R128_GUI_SCRATCH_REG0 0x15e0
+#define R128_GUI_SCRATCH_REG1 0x15e4
+#define R128_GUI_SCRATCH_REG2 0x15e8
+#define R128_GUI_SCRATCH_REG3 0x15ec
+#define R128_GUI_SCRATCH_REG4 0x15f0
+#define R128_GUI_SCRATCH_REG5 0x15f4
+#define R128_GUI_STAT 0x1740
+# define R128_GUI_FIFOCNT_MASK 0x0fff
+# define R128_GUI_ACTIVE (1 << 31)
+
+#define R128_HEADER 0x0f0e /* PCI */
+#define R128_HOST_DATA0 0x17c0
+#define R128_HOST_DATA1 0x17c4
+#define R128_HOST_DATA2 0x17c8
+#define R128_HOST_DATA3 0x17cc
+#define R128_HOST_DATA4 0x17d0
+#define R128_HOST_DATA5 0x17d4
+#define R128_HOST_DATA6 0x17d8
+#define R128_HOST_DATA7 0x17dc
+#define R128_HOST_DATA_LAST 0x17e0
+#define R128_HOST_PATH_CNTL 0x0130
+#define R128_HTOTAL_CNTL 0x0009 /* PLL */
+#define R128_HW_DEBUG 0x0128
+#define R128_HW_DEBUG2 0x011c
+
+#define R128_I2C_CNTL_1 0x0094 /* ? */
+#define R128_INTERRUPT_LINE 0x0f3c /* PCI */
+#define R128_INTERRUPT_PIN 0x0f3d /* PCI */
+#define R128_IO_BASE 0x0f14 /* PCI */
+
+#define R128_LATENCY 0x0f0d /* PCI */
+#define R128_LEAD_BRES_DEC 0x1608
+#define R128_LEAD_BRES_ERR 0x1600
+#define R128_LEAD_BRES_INC 0x1604
+#define R128_LEAD_BRES_LNTH 0x161c
+#define R128_LEAD_BRES_LNTH_SUB 0x1624
+#define R128_LVDS_GEN_CNTL 0x02d0
+# define R128_LVDS_ON (1 << 0)
+# define R128_LVDS_DISPLAY_DIS (1 << 1)
+# define R128_LVDS_EN (1 << 7)
+# define R128_LVDS_DIGON (1 << 18)
+# define R128_LVDS_BLON (1 << 19)
+# define R128_LVDS_SEL_CRTC2 (1 << 23)
+# define R128_HSYNC_DELAY_SHIFT 28
+# define R128_HSYNC_DELAY_MASK (0xf << 28)
+
+#define R128_MAX_LATENCY 0x0f3f /* PCI */
+#define R128_MCLK_CNTL 0x000f /* PLL */
+# define R128_FORCE_GCP (1 << 16)
+# define R128_FORCE_PIPE3D_CP (1 << 17)
+# define R128_FORCE_RCP (1 << 18)
+#define R128_MDGPIO_A_REG 0x01ac
+#define R128_MDGPIO_EN_REG 0x01b0
+#define R128_MDGPIO_MASK 0x0198
+#define R128_MDGPIO_Y_REG 0x01b4
+#define R128_MEM_ADDR_CONFIG 0x0148
+#define R128_MEM_BASE 0x0f10 /* PCI */
+#define R128_MEM_CNTL 0x0140
+#define R128_MEM_INIT_LAT_TIMER 0x0154
+#define R128_MEM_INTF_CNTL 0x014c
+#define R128_MEM_SDRAM_MODE_REG 0x0158
+#define R128_MEM_STR_CNTL 0x0150
+#define R128_MEM_VGA_RP_SEL 0x003c
+#define R128_MEM_VGA_WP_SEL 0x0038
+#define R128_MIN_GRANT 0x0f3e /* PCI */
+#define R128_MM_DATA 0x0004
+#define R128_MM_INDEX 0x0000
+#define R128_MPLL_CNTL 0x000e /* PLL */
+#define R128_MPP_TB_CONFIG 0x01c0 /* ? */
+#define R128_MPP_GP_CONFIG 0x01c8 /* ? */
+
+#define R128_N_VIF_COUNT 0x0248
+
+#define R128_OVR_CLR 0x0230
+#define R128_OVR_WID_LEFT_RIGHT 0x0234
+#define R128_OVR_WID_TOP_BOTTOM 0x0238
+
+/* first overlay unit (there is only one) */
+
+#define R128_OV0_Y_X_START 0x0400
+#define R128_OV0_Y_X_END 0x0404
+#define R128_OV0_EXCLUSIVE_HORZ 0x0408
+# define R128_EXCL_HORZ_START_MASK 0x000000ff
+# define R128_EXCL_HORZ_END_MASK 0x0000ff00
+# define R128_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000
+# define R128_EXCL_HORZ_EXCLUSIVE_EN 0x80000000
+#define R128_OV0_EXCLUSIVE_VERT 0x040C
+# define R128_EXCL_VERT_START_MASK 0x000003ff
+# define R128_EXCL_VERT_END_MASK 0x03ff0000
+#define R128_OV0_REG_LOAD_CNTL 0x0410
+# define R128_REG_LD_CTL_LOCK 0x00000001L
+# define R128_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L
+# define R128_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L
+# define R128_REG_LD_CTL_LOCK_READBACK 0x00000008L
+#define R128_OV0_SCALE_CNTL 0x0420
+# define R128_SCALER_PIX_EXPAND 0x00000001L
+# define R128_SCALER_Y2R_TEMP 0x00000002L
+# define R128_SCALER_HORZ_PICK_NEAREST 0x00000003L
+# define R128_SCALER_VERT_PICK_NEAREST 0x00000004L
+# define R128_SCALER_SIGNED_UV 0x00000010L
+# define R128_SCALER_GAMMA_SEL_MASK 0x00000060L
+# define R128_SCALER_GAMMA_SEL_BRIGHT 0x00000000L
+# define R128_SCALER_GAMMA_SEL_G22 0x00000020L
+# define R128_SCALER_GAMMA_SEL_G18 0x00000040L
+# define R128_SCALER_GAMMA_SEL_G14 0x00000060L
+# define R128_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L
+# define R128_SCALER_SURFAC_FORMAT 0x00000f00L
+# define R128_SCALER_SOURCE_15BPP 0x00000300L
+# define R128_SCALER_SOURCE_16BPP 0x00000400L
+# define R128_SCALER_SOURCE_32BPP 0x00000600L
+# define R128_SCALER_SOURCE_YUV9 0x00000900L
+# define R128_SCALER_SOURCE_YUV12 0x00000A00L
+# define R128_SCALER_SOURCE_VYUY422 0x00000B00L
+# define R128_SCALER_SOURCE_YVYU422 0x00000C00L
+# define R128_SCALER_SMART_SWITCH 0x00008000L
+# define R128_SCALER_BURST_PER_PLANE 0x00ff0000L
+# define R128_SCALER_DOUBLE_BUFFER 0x01000000L
+# define R128_SCALER_DIS_LIMIT 0x08000000L
+# define R128_SCALER_PRG_LOAD_START 0x10000000L
+# define R128_SCALER_INT_EMU 0x20000000L
+# define R128_SCALER_ENABLE 0x40000000L
+# define R128_SCALER_SOFT_RESET 0x80000000L
+#define R128_OV0_V_INC 0x0424
+#define R128_OV0_P1_V_ACCUM_INIT 0x0428
+# define R128_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L
+# define R128_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L
+#define R128_OV0_P23_V_ACCUM_INIT 0x042C
+#define R128_OV0_P1_BLANK_LINES_AT_TOP 0x0430
+# define R128_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL
+# define R128_P1_ACTIVE_LINES_M1 0x0fff0000L
+#define R128_OV0_P23_BLANK_LINES_AT_TOP 0x0434
+# define R128_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL
+# define R128_P23_ACTIVE_LINES_M1 0x07ff0000L
+#define R128_OV0_VID_BUF0_BASE_ADRS 0x0440
+# define R128_VIF_BUF0_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF0_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF1_BASE_ADRS 0x0444
+# define R128_VIF_BUF1_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF1_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF2_BASE_ADRS 0x0448
+# define R128_VIF_BUF2_PITCH_SEL 0x00000001L
+# define R128_VIF_BUF2_TILE_ADRS 0x00000002L
+# define R128_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L
+# define R128_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF3_BASE_ADRS 0x044C
+#define R128_OV0_VID_BUF4_BASE_ADRS 0x0450
+#define R128_OV0_VID_BUF5_BASE_ADRS 0x0454
+#define R128_OV0_VID_BUF_PITCH0_VALUE 0x0460
+#define R128_OV0_VID_BUF_PITCH1_VALUE 0x0464
+#define R128_OV0_AUTO_FLIP_CNTL 0x0470
+#define R128_OV0_DEINTERLACE_PATTERN 0x0474
+#define R128_OV0_H_INC 0x0480
+#define R128_OV0_STEP_BY 0x0484
+#define R128_OV0_P1_H_ACCUM_INIT 0x0488
+#define R128_OV0_P23_H_ACCUM_INIT 0x048C
+#define R128_OV0_P1_X_START_END 0x0494
+#define R128_OV0_P2_X_START_END 0x0498
+#define R128_OV0_P3_X_START_END 0x049C
+#define R128_OV0_FILTER_CNTL 0x04A0
+#define R128_OV0_FOUR_TAP_COEF_0 0x04B0
+#define R128_OV0_FOUR_TAP_COEF_1 0x04B4
+#define R128_OV0_FOUR_TAP_COEF_2 0x04B8
+#define R128_OV0_FOUR_TAP_COEF_3 0x04BC
+#define R128_OV0_FOUR_TAP_COEF_4 0x04C0
+#define R128_OV0_COLOUR_CNTL 0x04E0
+#define R128_OV0_VIDEO_KEY_CLR 0x04E4
+#define R128_OV0_VIDEO_KEY_MSK 0x04E8
+#define R128_OV0_GRAPHICS_KEY_CLR 0x04EC
+#define R128_OV0_GRAPHICS_KEY_MSK 0x04F0
+#define R128_OV0_KEY_CNTL 0x04F4
+# define R128_VIDEO_KEY_FN_MASK 0x00000007L
+# define R128_VIDEO_KEY_FN_FALSE 0x00000000L
+# define R128_VIDEO_KEY_FN_TRUE 0x00000001L
+# define R128_VIDEO_KEY_FN_EQ 0x00000004L
+# define R128_VIDEO_KEY_FN_NE 0x00000005L
+# define R128_GRAPHIC_KEY_FN_MASK 0x00000070L
+# define R128_GRAPHIC_KEY_FN_FALSE 0x00000000L
+# define R128_GRAPHIC_KEY_FN_TRUE 0x00000010L
+# define R128_GRAPHIC_KEY_FN_EQ 0x00000040L
+# define R128_GRAPHIC_KEY_FN_NE 0x00000050L
+# define R128_CMP_MIX_MASK 0x00000100L
+# define R128_CMP_MIX_OR 0x00000000L
+# define R128_CMP_MIX_AND 0x00000100L
+#define R128_OV0_TEST 0x04F8
+
+
+#define R128_PALETTE_DATA 0x00b4
+#define R128_PALETTE_INDEX 0x00b0
+#define R128_PC_DEBUG_MODE 0x1760
+#define R128_PC_GUI_CTLSTAT 0x1748
+#define R128_PC_GUI_MODE 0x1744
+# define R128_PC_IGNORE_UNIFY (1 << 5)
+#define R128_PC_MISC_CNTL 0x0188
+#define R128_PC_NGUI_CTLSTAT 0x0184
+# define R128_PC_FLUSH_GUI (3 << 0)
+# define R128_PC_RI_GUI (1 << 2)
+# define R128_PC_FLUSH_ALL 0x00ff
+# define R128_PC_BUSY (1 << 31)
+#define R128_PC_NGUI_MODE 0x0180
+#define R128_PCI_GART_PAGE 0x017c
+#define R128_PLANE_3D_MASK_C 0x1d44
+#define R128_PLL_TEST_CNTL 0x0013 /* PLL */
+#define R128_PMI_CAP_ID 0x0f5c /* PCI */
+#define R128_PMI_DATA 0x0f63 /* PCI */
+#define R128_PMI_NXT_CAP_PTR 0x0f5d /* PCI */
+#define R128_PMI_PMC_REG 0x0f5e /* PCI */
+#define R128_PMI_PMCSR_REG 0x0f60 /* PCI */
+#define R128_PMI_REGISTER 0x0f5c /* PCI */
+#define R128_PPLL_CNTL 0x0002 /* PLL */
+# define R128_PPLL_RESET (1 << 0)
+# define R128_PPLL_SLEEP (1 << 1)
+# define R128_PPLL_ATOMIC_UPDATE_EN (1 << 16)
+# define R128_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+#define R128_PPLL_DIV_0 0x0004 /* PLL */
+#define R128_PPLL_DIV_1 0x0005 /* PLL */
+#define R128_PPLL_DIV_2 0x0006 /* PLL */
+#define R128_PPLL_DIV_3 0x0007 /* PLL */
+# define R128_PPLL_FB3_DIV_MASK 0x07ff
+# define R128_PPLL_POST3_DIV_MASK 0x00070000
+#define R128_PPLL_REF_DIV 0x0003 /* PLL */
+# define R128_PPLL_REF_DIV_MASK 0x03ff
+# define R128_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
+# define R128_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+#define R128_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */
+#define R128_REG_BASE 0x0f18 /* PCI */
+#define R128_REGPROG_INF 0x0f09 /* PCI */
+#define R128_REVISION_ID 0x0f08 /* PCI */
+
+#define R128_SC_BOTTOM 0x164c
+#define R128_SC_BOTTOM_RIGHT 0x16f0
+#define R128_SC_BOTTOM_RIGHT_C 0x1c8c
+#define R128_SC_LEFT 0x1640
+#define R128_SC_RIGHT 0x1644
+#define R128_SC_TOP 0x1648
+#define R128_SC_TOP_LEFT 0x16ec
+#define R128_SC_TOP_LEFT_C 0x1c88
+#define R128_SEQ8_DATA 0x03c5 /* VGA */
+#define R128_SEQ8_IDX 0x03c4 /* VGA */
+#define R128_SNAPSHOT_F_COUNT 0x0244
+#define R128_SNAPSHOT_VH_COUNTS 0x0240
+#define R128_SNAPSHOT_VIF_COUNT 0x024c
+#define R128_SRC_OFFSET 0x15ac
+#define R128_SRC_PITCH 0x15b0
+#define R128_SRC_PITCH_OFFSET 0x1428
+#define R128_SRC_SC_BOTTOM 0x165c
+#define R128_SRC_SC_BOTTOM_RIGHT 0x16f4
+#define R128_SRC_SC_RIGHT 0x1654
+#define R128_SRC_X 0x1414
+#define R128_SRC_X_Y 0x1590
+#define R128_SRC_Y 0x1418
+#define R128_SRC_Y_X 0x1434
+#define R128_STATUS 0x0f06 /* PCI */
+#define R128_SUBPIC_CNTL 0x0540 /* ? */
+#define R128_SUB_CLASS 0x0f0a /* PCI */
+#define R128_SURFACE_DELAY 0x0b00
+#define R128_SURFACE0_INFO 0x0b0c
+#define R128_SURFACE0_LOWER_BOUND 0x0b04
+#define R128_SURFACE0_UPPER_BOUND 0x0b08
+#define R128_SURFACE1_INFO 0x0b1c
+#define R128_SURFACE1_LOWER_BOUND 0x0b14
+#define R128_SURFACE1_UPPER_BOUND 0x0b18
+#define R128_SURFACE2_INFO 0x0b2c
+#define R128_SURFACE2_LOWER_BOUND 0x0b24
+#define R128_SURFACE2_UPPER_BOUND 0x0b28
+#define R128_SURFACE3_INFO 0x0b3c
+#define R128_SURFACE3_LOWER_BOUND 0x0b34
+#define R128_SURFACE3_UPPER_BOUND 0x0b38
+#define R128_SW_SEMAPHORE 0x013c
+
+#define R128_TEST_DEBUG_CNTL 0x0120
+#define R128_TEST_DEBUG_MUX 0x0124
+#define R128_TEST_DEBUG_OUT 0x012c
+#define R128_TMDS_CRC 0x02a0
+#define R128_TMDS_TRANSMITTER_CNTL 0x02a4
+# define R128_TMDS_PLLEN (1 << 0)
+# define R128_TMDS_PLLRST (1 << 1)
+#define R128_TRAIL_BRES_DEC 0x1614
+#define R128_TRAIL_BRES_ERR 0x160c
+#define R128_TRAIL_BRES_INC 0x1610
+#define R128_TRAIL_X 0x1618
+#define R128_TRAIL_X_SUB 0x1620
+
+#define R128_VCLK_ECP_CNTL 0x0008 /* PLL */
+#define R128_VENDOR_ID 0x0f00 /* PCI */
+#define R128_VGA_DDA_CONFIG 0x02e8
+#define R128_VGA_DDA_ON_OFF 0x02ec
+#define R128_VID_BUFFER_CONTROL 0x0900
+#define R128_VIDEOMUX_CNTL 0x0190
+#define R128_VIPH_CONTROL 0x01D0 /* ? */
+
+#define R128_WAIT_UNTIL 0x1720
+
+#define R128_X_MPLL_REF_FB_DIV 0x000a /* PLL */
+#define R128_XCLK_CNTL 0x000d /* PLL */
+#define R128_XDLL_CNTL 0x000c /* PLL */
+#define R128_XPLL_CNTL 0x000b /* PLL */
+
+ /* Registers for CCE and Microcode Engine */
+#define R128_PM4_MICROCODE_ADDR 0x07d4
+#define R128_PM4_MICROCODE_RADDR 0x07d8
+#define R128_PM4_MICROCODE_DATAH 0x07dc
+#define R128_PM4_MICROCODE_DATAL 0x07e0
+
+#define R128_PM4_BUFFER_OFFSET 0x0700
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192PIO (1 << 28)
+# define R128_PM4_192BM (2 << 28)
+# define R128_PM4_128PIO_64INDBM (3 << 28)
+# define R128_PM4_128BM_64INDBM (4 << 28)
+# define R128_PM4_64PIO_128INDBM (5 << 28)
+# define R128_PM4_64BM_128INDBM (6 << 28)
+# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
+# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
+# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+#define R128_PM4_BUFFER_WM_CNTL 0x0708
+# define R128_WMA_SHIFT 0
+# define R128_WMB_SHIFT 8
+# define R128_WMC_SHIFT 16
+# define R128_WB_WM_SHIFT 24
+#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
+#define R128_PM4_BUFFER_DL_RPTR 0x0710
+#define R128_PM4_BUFFER_DL_WPTR 0x0714
+# define R128_PM4_BUFFER_DL_DONE (1 << 31)
+#define R128_PM4_BUFFER_DL_WPTR_DELAY 0x0718
+# define R128_PRE_WRITE_TIMER_SHIFT 0
+# define R128_PRE_WRITE_LIMIT_SHIFT 23
+#define R128_PM4_VC_FPU_SETUP 0x071c
+# define R128_FRONT_DIR_CW (0 << 0)
+# define R128_FRONT_DIR_CCW (1 << 0)
+# define R128_FRONT_DIR_MASK (1 << 0)
+# define R128_BACKFACE_CULL (0 << 1)
+# define R128_BACKFACE_POINTS (1 << 1)
+# define R128_BACKFACE_LINES (2 << 1)
+# define R128_BACKFACE_SOLID (3 << 1)
+# define R128_BACKFACE_MASK (3 << 1)
+# define R128_FRONTFACE_CULL (0 << 3)
+# define R128_FRONTFACE_POINTS (1 << 3)
+# define R128_FRONTFACE_LINES (2 << 3)
+# define R128_FRONTFACE_SOLID (3 << 3)
+# define R128_FRONTFACE_MASK (3 << 3)
+# define R128_FPU_COLOR_SOLID (0 << 5)
+# define R128_FPU_COLOR_FLAT (1 << 5)
+# define R128_FPU_COLOR_GOURAUD (2 << 5)
+# define R128_FPU_COLOR_GOURAUD2 (3 << 5)
+# define R128_FPU_COLOR_MASK (3 << 5)
+# define R128_FPU_SUB_PIX_2BITS (0 << 7)
+# define R128_FPU_SUB_PIX_4BITS (1 << 7)
+# define R128_FPU_MODE_2D (0 << 8)
+# define R128_FPU_MODE_3D (1 << 8)
+# define R128_TRAP_BITS_DISABLE (1 << 9)
+# define R128_EDGE_ANTIALIAS (1 << 10)
+# define R128_SUPERSAMPLE (1 << 11)
+# define R128_XFACTOR_2 (0 << 12)
+# define R128_XFACTOR_4 (1 << 12)
+# define R128_YFACTOR_2 (0 << 13)
+# define R128_YFACTOR_4 (1 << 13)
+# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14)
+# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14)
+# define R128_FPU_ROUND_TRUNCATE (0 << 15)
+# define R128_FPU_ROUND_NEAREST (1 << 15)
+# define R128_WM_SEL_8DW (0 << 16)
+# define R128_WM_SEL_16DW (1 << 16)
+# define R128_WM_SEL_32DW (2 << 16)
+#define R128_PM4_VC_DEBUG_CONFIG 0x07a4
+#define R128_PM4_VC_STAT 0x07a8
+#define R128_PM4_VC_TIMESTAMP0 0x07b0
+#define R128_PM4_VC_TIMESTAMP1 0x07b4
+#define R128_PM4_STAT 0x07b8
+# define R128_PM4_FIFOCNT_MASK 0x0fff
+# define R128_PM4_BUSY (1 << 16)
+# define R128_PM4_GUI_ACTIVE (1 << 31)
+#define R128_PM4_BUFFER_ADDR 0x07f0
+#define R128_PM4_MICRO_CNTL 0x07fc
+# define R128_PM4_MICRO_FREERUN (1 << 30)
+#define R128_PM4_FIFO_DATA_EVEN 0x1000
+#define R128_PM4_FIFO_DATA_ODD 0x1004
+
+#define R128_SCALE_3D_CNTL 0x1a00
+# define R128_SCALE_DITHER_ERR_DIFF (0 << 1)
+# define R128_SCALE_DITHER_TABLE (1 << 1)
+# define R128_TEX_CACHE_SIZE_FULL (0 << 2)
+# define R128_TEX_CACHE_SIZE_HALF (1 << 2)
+# define R128_DITHER_INIT_CURR (0 << 3)
+# define R128_DITHER_INIT_RESET (1 << 3)
+# define R128_ROUND_24BIT (1 << 4)
+# define R128_TEX_CACHE_DISABLE (1 << 5)
+# define R128_SCALE_3D_NOOP (0 << 6)
+# define R128_SCALE_3D_SCALE (1 << 6)
+# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6)
+# define R128_SCALE_PIX_BLEND (0 << 8)
+# define R128_SCALE_PIX_REPLICATE (1 << 8)
+# define R128_TEX_CACHE_SPLIT (1 << 9)
+# define R128_APPLE_YUV_MODE (1 << 10)
+# define R128_TEX_CACHE_PALLETE_MODE (1 << 11)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_SIGNED_DST_CLAMP (1 << 15)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16)
+# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28)
+# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28)
+# define R128_COMPOSITE_SHADOW (1 << 29)
+# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30)
+# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31)
+# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31)
+#define R128_SCALE_3D_DATATYPE 0x1a20
+
+#define R128_SETUP_CNTL 0x1bc4
+# define R128_DONT_START_TRIANGLE (1 << 0)
+# define R128_Z_BIAS (0 << 1)
+# define R128_DONT_START_ANY_ON (1 << 2)
+# define R128_COLOR_SOLID_COLOR (0 << 3)
+# define R128_COLOR_FLAT_VERT_1 (1 << 3)
+# define R128_COLOR_FLAT_VERT_2 (2 << 3)
+# define R128_COLOR_FLAT_VERT_3 (3 << 3)
+# define R128_COLOR_GOURAUD (4 << 3)
+# define R128_PRIM_TYPE_TRI (0 << 7)
+# define R128_PRIM_TYPE_LINE (1 << 7)
+# define R128_PRIM_TYPE_POINT (2 << 7)
+# define R128_PRIM_TYPE_POLY_EDGE (3 << 7)
+# define R128_TEXTURE_ST_MULT_W (0 << 9)
+# define R128_TEXTURE_ST_DIRECT (1 << 9)
+# define R128_STARTING_VERTEX_1 (1 << 14)
+# define R128_STARTING_VERTEX_2 (2 << 14)
+# define R128_STARTING_VERTEX_3 (3 << 14)
+# define R128_ENDING_VERTEX_1 (1 << 16)
+# define R128_ENDING_VERTEX_2 (2 << 16)
+# define R128_ENDING_VERTEX_3 (3 << 16)
+# define R128_SU_POLY_LINE_LAST (0 << 18)
+# define R128_SU_POLY_LINE_NOT_LAST (1 << 18)
+# define R128_SUB_PIX_2BITS (0 << 19)
+# define R128_SUB_PIX_4BITS (1 << 19)
+# define R128_SET_UP_CONTINUE (1 << 31)
+
+#define R128_WINDOW_XY_OFFSET 0x1bcc
+# define R128_WINDOW_Y_SHIFT 4
+# define R128_WINDOW_X_SHIFT 20
+
+#define R128_Z_OFFSET_C 0x1c90
+#define R128_Z_PITCH_C 0x1c94
+# define R128_Z_TILE (1 << 16)
+#define R128_Z_STEN_CNTL_C 0x1c98
+# define R128_Z_PIX_WIDTH_16 (0 << 1)
+# define R128_Z_PIX_WIDTH_24 (1 << 1)
+# define R128_Z_PIX_WIDTH_32 (2 << 1)
+# define R128_Z_PIX_WIDTH_MASK (3 << 1)
+# define R128_Z_TEST_NEVER (0 << 4)
+# define R128_Z_TEST_LESS (1 << 4)
+# define R128_Z_TEST_LESSEQUAL (2 << 4)
+# define R128_Z_TEST_EQUAL (3 << 4)
+# define R128_Z_TEST_GREATEREQUAL (4 << 4)
+# define R128_Z_TEST_GREATER (5 << 4)
+# define R128_Z_TEST_NEQUAL (6 << 4)
+# define R128_Z_TEST_ALWAYS (7 << 4)
+# define R128_Z_TEST_MASK (7 << 4)
+# define R128_STENCIL_TEST_NEVER (0 << 12)
+# define R128_STENCIL_TEST_LESS (1 << 12)
+# define R128_STENCIL_TEST_LESSEQUAL (2 << 12)
+# define R128_STENCIL_TEST_EQUAL (3 << 12)
+# define R128_STENCIL_TEST_GREATEREQUAL (4 << 12)
+# define R128_STENCIL_TEST_GREATER (5 << 12)
+# define R128_STENCIL_TEST_NEQUAL (6 << 12)
+# define R128_STENCIL_TEST_ALWAYS (7 << 12)
+# define R128_STENCIL_S_FAIL_KEEP (0 << 16)
+# define R128_STENCIL_S_FAIL_ZERO (1 << 16)
+# define R128_STENCIL_S_FAIL_REPLACE (2 << 16)
+# define R128_STENCIL_S_FAIL_INC (3 << 16)
+# define R128_STENCIL_S_FAIL_DEC (4 << 16)
+# define R128_STENCIL_S_FAIL_INV (5 << 16)
+# define R128_STENCIL_ZPASS_KEEP (0 << 20)
+# define R128_STENCIL_ZPASS_ZERO (1 << 20)
+# define R128_STENCIL_ZPASS_REPLACE (2 << 20)
+# define R128_STENCIL_ZPASS_INC (3 << 20)
+# define R128_STENCIL_ZPASS_DEC (4 << 20)
+# define R128_STENCIL_ZPASS_INV (5 << 20)
+# define R128_STENCIL_ZFAIL_KEEP (0 << 24)
+# define R128_STENCIL_ZFAIL_ZERO (1 << 24)
+# define R128_STENCIL_ZFAIL_REPLACE (2 << 24)
+# define R128_STENCIL_ZFAIL_INC (3 << 24)
+# define R128_STENCIL_ZFAIL_DEC (4 << 24)
+# define R128_STENCIL_ZFAIL_INV (5 << 24)
+#define R128_TEX_CNTL_C 0x1c9c
+# define R128_Z_ENABLE (1 << 0)
+# define R128_Z_WRITE_ENABLE (1 << 1)
+# define R128_STENCIL_ENABLE (1 << 3)
+# define R128_SHADE_ENABLE (0 << 4)
+# define R128_TEXMAP_ENABLE (1 << 4)
+# define R128_SEC_TEXMAP_ENABLE (1 << 5)
+# define R128_FOG_ENABLE (1 << 7)
+# define R128_DITHER_ENABLE (1 << 8)
+# define R128_ALPHA_ENABLE (1 << 9)
+# define R128_ALPHA_TEST_ENABLE (1 << 10)
+# define R128_SPEC_LIGHT_ENABLE (1 << 11)
+# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12)
+# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13)
+# define R128_ALPHA_IN_TEX_LSB_A (1 << 13)
+# define R128_LIGHT_DIS (0 << 14)
+# define R128_LIGHT_COPY (1 << 14)
+# define R128_LIGHT_MODULATE (2 << 14)
+# define R128_LIGHT_ADD (3 << 14)
+# define R128_LIGHT_BLEND_CONSTANT (4 << 14)
+# define R128_LIGHT_BLEND_TEXTURE (5 << 14)
+# define R128_LIGHT_BLEND_VERTEX (6 << 14)
+# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14)
+# define R128_ALPHA_LIGHT_DIS (0 << 18)
+# define R128_ALPHA_LIGHT_COPY (1 << 18)
+# define R128_ALPHA_LIGHT_MODULATE (2 << 18)
+# define R128_ALPHA_LIGHT_ADD (3 << 18)
+# define R128_ANTI_ALIAS (1 << 21)
+# define R128_TEX_CACHE_FLUSH (1 << 23)
+# define R128_LOD_BIAS_SHIFT 24
+# define R128_LOD_BIAS_MASK (0xff << 24)
+#define R128_MISC_3D_STATE_CNTL_REG 0x1ca0
+# define R128_REF_ALPHA_MASK 0xff
+# define R128_MISC_SCALE_3D_NOOP (0 << 8)
+# define R128_MISC_SCALE_3D_SCALE (1 << 8)
+# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8)
+# define R128_MISC_SCALE_PIX_BLEND (0 << 10)
+# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10)
+# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
+# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12)
+# define R128_FOG_VERTEX (0 << 14)
+# define R128_FOG_TABLE (1 << 14)
+# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
+# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
+# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16)
+# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16)
+# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16)
+# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16)
+# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16)
+# define R128_ALPHA_BLEND_SRC_MASK (15 << 16)
+# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
+# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
+# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
+# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
+# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20)
+# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20)
+# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20)
+# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20)
+# define R128_ALPHA_BLEND_DST_MASK (15 << 20)
+# define R128_ALPHA_TEST_NEVER (0 << 24)
+# define R128_ALPHA_TEST_LESS (1 << 24)
+# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
+# define R128_ALPHA_TEST_EQUAL (3 << 24)
+# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
+# define R128_ALPHA_TEST_GREATER (5 << 24)
+# define R128_ALPHA_TEST_NEQUAL (6 << 24)
+# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_ALPHA_TEST_MASK (7 << 24)
+#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4
+#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8
+#define R128_FOG_COLOR_C 0x1cac
+# define R128_FOG_BLUE_SHIFT 0
+# define R128_FOG_GREEN_SHIFT 8
+# define R128_FOG_RED_SHIFT 16
+#define R128_PRIM_TEX_CNTL_C 0x1cb0
+# define R128_MIN_BLEND_NEAREST (0 << 1)
+# define R128_MIN_BLEND_LINEAR (1 << 1)
+# define R128_MIN_BLEND_MIPNEAREST (2 << 1)
+# define R128_MIN_BLEND_MIPLINEAR (3 << 1)
+# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1)
+# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1)
+# define R128_MIN_BLEND_MASK (7 << 1)
+# define R128_MAG_BLEND_NEAREST (0 << 4)
+# define R128_MAG_BLEND_LINEAR (1 << 4)
+# define R128_MAG_BLEND_MASK (7 << 4)
+# define R128_MIP_MAP_DISABLE (1 << 7)
+# define R128_TEX_CLAMP_S_WRAP (0 << 8)
+# define R128_TEX_CLAMP_S_MIRROR (1 << 8)
+# define R128_TEX_CLAMP_S_CLAMP (2 << 8)
+# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8)
+# define R128_TEX_CLAMP_S_MASK (3 << 8)
+# define R128_TEX_WRAP_S (1 << 10)
+# define R128_TEX_CLAMP_T_WRAP (0 << 11)
+# define R128_TEX_CLAMP_T_MIRROR (1 << 11)
+# define R128_TEX_CLAMP_T_CLAMP (2 << 11)
+# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11)
+# define R128_TEX_CLAMP_T_MASK (3 << 11)
+# define R128_TEX_WRAP_T (1 << 13)
+# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14)
+# define R128_DATATYPE_VQ (0 << 16)
+# define R128_DATATYPE_CI4 (1 << 16)
+# define R128_DATATYPE_CI8 (2 << 16)
+# define R128_DATATYPE_ARGB1555 (3 << 16)
+# define R128_DATATYPE_RGB565 (4 << 16)
+# define R128_DATATYPE_RGB888 (5 << 16)
+# define R128_DATATYPE_ARGB8888 (6 << 16)
+# define R128_DATATYPE_RGB332 (7 << 16)
+# define R128_DATATYPE_Y8 (8 << 16)
+# define R128_DATATYPE_RGB8 (9 << 16)
+# define R128_DATATYPE_CI16 (10 << 16)
+# define R128_DATATYPE_YUV422 (11 << 16)
+# define R128_DATATYPE_YUV422_2 (12 << 16)
+# define R128_DATATYPE_AYUV444 (14 << 16)
+# define R128_DATATYPE_ARGB4444 (15 << 16)
+# define R128_PALLETE_EITHER (0 << 20)
+# define R128_PALLETE_1 (1 << 20)
+# define R128_PALLETE_2 (2 << 20)
+# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24)
+# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24)
+#define R128_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4
+# define R128_COMB_DIS (0 << 0)
+# define R128_COMB_COPY (1 << 0)
+# define R128_COMB_COPY_INP (2 << 0)
+# define R128_COMB_MODULATE (3 << 0)
+# define R128_COMB_MODULATE2X (4 << 0)
+# define R128_COMB_MODULATE4X (5 << 0)
+# define R128_COMB_ADD (6 << 0)
+# define R128_COMB_ADD_SIGNED (7 << 0)
+# define R128_COMB_BLEND_VERTEX (8 << 0)
+# define R128_COMB_BLEND_TEXTURE (9 << 0)
+# define R128_COMB_BLEND_CONST (10 << 0)
+# define R128_COMB_BLEND_PREMULT (11 << 0)
+# define R128_COMB_BLEND_PREV (12 << 0)
+# define R128_COMB_BLEND_PREMULT_INV (13 << 0)
+# define R128_COMB_ADD_SIGNED2X (14 << 0)
+# define R128_COMB_BLEND_CONST_COLOR (15 << 0)
+# define R128_COMB_MASK (15 << 0)
+# define R128_COLOR_FACTOR_CONST_COLOR (0 << 4)
+# define R128_COLOR_FACTOR_NCONST_COLOR (1 << 4)
+# define R128_COLOR_FACTOR_TEX (4 << 4)
+# define R128_COLOR_FACTOR_NTEX (5 << 4)
+# define R128_COLOR_FACTOR_ALPHA (6 << 4)
+# define R128_COLOR_FACTOR_NALPHA (7 << 4)
+# define R128_COLOR_FACTOR_PREV_COLOR (8 << 4)
+# define R128_COLOR_FACTOR_MASK (15 << 4)
+# define R128_COMB_FCN_MSB (1 << 8)
+# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10)
+# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10)
+# define R128_INPUT_FACTOR_INT_COLOR (4 << 10)
+# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10)
+# define R128_INPUT_FACTOR_MASK (15 << 10)
+# define R128_COMB_ALPHA_DIS (0 << 14)
+# define R128_COMB_ALPHA_COPY (1 << 14)
+# define R128_COMB_ALPHA_COPY_INP (2 << 14)
+# define R128_COMB_ALPHA_MODULATE (3 << 14)
+# define R128_COMB_ALPHA_MODULATE2X (4 << 14)
+# define R128_COMB_ALPHA_MODULATE4X (5 << 14)
+# define R128_COMB_ALPHA_ADD (6 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14)
+# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14)
+# define R128_COMB_ALPHA_MASK (15 << 14)
+# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18)
+# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18)
+# define R128_ALPHA_FACTOR_MASK (15 << 18)
+# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25)
+# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25)
+# define R128_INP_FACTOR_A_MASK (7 << 25)
+#define R128_TEX_SIZE_PITCH_C 0x1cb8
+# define R128_TEX_PITCH_SHIFT 0
+# define R128_TEX_SIZE_SHIFT 4
+# define R128_TEX_HEIGHT_SHIFT 8
+# define R128_TEX_MIN_SIZE_SHIFT 12
+# define R128_SEC_TEX_PITCH_SHIFT 16
+# define R128_SEC_TEX_SIZE_SHIFT 20
+# define R128_SEC_TEX_HEIGHT_SHIFT 24
+# define R128_SEC_TEX_MIN_SIZE_SHIFT 28
+# define R128_TEX_PITCH_MASK (0x0f << 0)
+# define R128_TEX_SIZE_MASK (0x0f << 4)
+# define R128_TEX_HEIGHT_MASK (0x0f << 8)
+# define R128_TEX_MIN_SIZE_MASK (0x0f << 12)
+# define R128_SEC_TEX_PITCH_MASK (0x0f << 16)
+# define R128_SEC_TEX_SIZE_MASK (0x0f << 20)
+# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24)
+# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28)
+# define R128_TEX_SIZE_PITCH_SHIFT 0
+# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16
+# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0)
+# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16)
+#define R128_PRIM_TEX_0_OFFSET_C 0x1cbc
+#define R128_PRIM_TEX_1_OFFSET_C 0x1cc0
+#define R128_PRIM_TEX_2_OFFSET_C 0x1cc4
+#define R128_PRIM_TEX_3_OFFSET_C 0x1cc8
+#define R128_PRIM_TEX_4_OFFSET_C 0x1ccc
+#define R128_PRIM_TEX_5_OFFSET_C 0x1cd0
+#define R128_PRIM_TEX_6_OFFSET_C 0x1cd4
+#define R128_PRIM_TEX_7_OFFSET_C 0x1cd8
+#define R128_PRIM_TEX_8_OFFSET_C 0x1cdc
+#define R128_PRIM_TEX_9_OFFSET_C 0x1ce0
+#define R128_PRIM_TEX_10_OFFSET_C 0x1ce4
+# define R128_TEX_NO_TILE (0 << 30)
+# define R128_TEX_TILED_BY_HOST (1 << 30)
+# define R128_TEX_TILED_BY_STORAGE (2 << 30)
+# define R128_TEX_TILED_BY_STORAGE2 (3 << 30)
+
+#define R128_SEC_TEX_CNTL_C 0x1d00
+# define R128_SEC_SELECT_PRIM_ST (0 << 0)
+# define R128_SEC_SELECT_SEC_ST (1 << 0)
+#define R128_SEC_TEX_COMBINE_CNTL_C 0x1d04
+# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10)
+# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10)
+# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25)
+#define R128_SEC_TEX_0_OFFSET_C 0x1d08
+#define R128_SEC_TEX_1_OFFSET_C 0x1d0c
+#define R128_SEC_TEX_2_OFFSET_C 0x1d10
+#define R128_SEC_TEX_3_OFFSET_C 0x1d14
+#define R128_SEC_TEX_4_OFFSET_C 0x1d18
+#define R128_SEC_TEX_5_OFFSET_C 0x1d1c
+#define R128_SEC_TEX_6_OFFSET_C 0x1d20
+#define R128_SEC_TEX_7_OFFSET_C 0x1d24
+#define R128_SEC_TEX_8_OFFSET_C 0x1d28
+#define R128_SEC_TEX_9_OFFSET_C 0x1d2c
+#define R128_SEC_TEX_10_OFFSET_C 0x1d30
+#define R128_CONSTANT_COLOR_C 0x1d34
+# define R128_CONSTANT_BLUE_SHIFT 0
+# define R128_CONSTANT_GREEN_SHIFT 8
+# define R128_CONSTANT_RED_SHIFT 16
+# define R128_CONSTANT_ALPHA_SHIFT 24
+#define R128_PRIM_TEXTURE_BORDER_COLOR_C 0x1d38
+# define R128_PRIM_TEX_BORDER_BLUE_SHIFT 0
+# define R128_PRIM_TEX_BORDER_GREEN_SHIFT 8
+# define R128_PRIM_TEX_BORDER_RED_SHIFT 16
+# define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
+# define R128_SEC_TEX_BORDER_BLUE_SHIFT 0
+# define R128_SEC_TEX_BORDER_GREEN_SHIFT 8
+# define R128_SEC_TEX_BORDER_RED_SHIFT 16
+# define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_STEN_REF_MASK_C 0x1d40
+# define R128_STEN_REFERENCE_SHIFT 0
+# define R128_STEN_MASK_SHIFT 16
+# define R128_STEN_WRITE_MASK_SHIFT 24
+#define R128_PLANE_3D_MASK_C 0x1d44
+#define R128_TEX_CACHE_STAT_COUNT 0x1974
+
+
+ /* Constants */
+#define R128_AGP_TEX_OFFSET 0x02000000
+
+#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
+
+ /* CCE packet types */
+#define R128_CCE_PACKET0 0x00000000
+#define R128_CCE_PACKET0_ONE_REG_WR 0x00008000
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+#define R128_CCE_PACKET3 0xC0000000
+#define R128_CCE_PACKET3_NOP 0xC0001000
+#define R128_CCE_PACKET3_PAINT 0xC0001100
+#define R128_CCE_PACKET3_BITBLT 0xC0001200
+#define R128_CCE_PACKET3_SMALLTEXT 0xC0001300
+#define R128_CCE_PACKET3_HOSTDATA_BLT 0xC0001400
+#define R128_CCE_PACKET3_POLYLINE 0xC0001500
+#define R128_CCE_PACKET3_SCALING 0xC0001600
+#define R128_CCE_PACKET3_TRANS_SCALING 0xC0001700
+#define R128_CCE_PACKET3_POLYSCANLINES 0xC0001800
+#define R128_CCE_PACKET3_NEXT_CHAR 0xC0001900
+#define R128_CCE_PACKET3_PAINT_MULTI 0xC0001A00
+#define R128_CCE_PACKET3_BITBLT_MULTI 0xC0001B00
+#define R128_CCE_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define R128_CCE_PACKET3_SET_SCISSORS 0xC0001E00
+#define R128_CCE_PACKET3_SET_MODE24BPP 0xC0001F00
+#define R128_CCE_PACKET3_CNTL_PAINT 0xC0009100
+#define R128_CCE_PACKET3_CNTL_BITBLT 0xC0009200
+#define R128_CCE_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define R128_CCE_PACKET3_CNTL_POLYLINE 0xC0009500
+#define R128_CCE_PACKET3_CNTL_SCALING 0xC0009600
+#define R128_CCE_PACKET3_CNTL_TRANS_SCALING 0xC0009700
+#define R128_CCE_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define R128_CCE_PACKET3_CNTL_NEXT_CHAR 0xC0009900
+#define R128_CCE_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xC0002000
+#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xC0002100
+#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xC0002500
+#define R128_CCE_PACKET3_LOAD_PALETTE 0xC0002C00
+#define R128_CCE_PACKET3_PURGE 0xC0002D00
+#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xC0002E00
+# define R128_CCE_PACKET_MASK 0xC0000000
+# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
+# define R128_CCE_PACKET_MAX_DWORDS (1 << 12)
+# define R128_CCE_PACKET0_REG_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
+# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+
+#define R128_CCE_VC_FRMT_RHW 0x00000001
+#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002
+#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004
+#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008
+#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010
+#define R128_CCE_VC_FRMT_SPEC_F 0x00000020
+#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040
+#define R128_CCE_VC_FRMT_S_T 0x00000080
+#define R128_CCE_VC_FRMT_S2_T2 0x00000100
+#define R128_CCE_VC_FRMT_RHW2 0x00000200
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT 16
+
+/* hmm copyed blindly (no specs) from radeon.h ... */
+#define R128_RE_TOP_LEFT 0x26c0
+# define R128_RE_LEFT_SHIFT 0
+# define R128_RE_TOP_SHIFT 16
+#define R128_RE_WIDTH_HEIGHT 0x1c44
+# define R128_RE_WIDTH_SHIFT 0
+# define R128_RE_HEIGHT_SHIFT 16
+
+#endif
diff --git a/src/r128_sarea.h b/src/r128_sarea.h
new file mode 100644
index 0000000..2ac863f
--- /dev/null
+++ b/src/r128_sarea.h
@@ -0,0 +1,201 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.7 2002/02/16 21:26:35 herrb Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_SAREA_H_
+#define _R128_SAREA_H_
+
+#include "Xmd.h"
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the kernel file (r128_drm.h)
+ */
+#ifndef __R128_SAREA_DEFINES__
+#define __R128_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define R128_UPLOAD_CONTEXT 0x001
+#define R128_UPLOAD_SETUP 0x002
+#define R128_UPLOAD_TEX0 0x004
+#define R128_UPLOAD_TEX1 0x008
+#define R128_UPLOAD_TEX0IMAGES 0x010
+#define R128_UPLOAD_TEX1IMAGES 0x020
+#define R128_UPLOAD_CORE 0x040
+#define R128_UPLOAD_MASKS 0x080
+#define R128_UPLOAD_WINDOW 0x100
+#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
+#define R128_REQUIRE_QUIESCENCE 0x400
+#define R128_UPLOAD_ALL 0x7ff
+
+#define R128_FRONT 0x1
+#define R128_BACK 0x2
+#define R128_DEPTH 0x4
+
+/* Primitive types
+ */
+#define R128_POINTS 0x1
+#define R128_LINES 0x2
+#define R128_LINE_STRIP 0x3
+#define R128_TRIANGLES 0x4
+#define R128_TRIANGLE_FAN 0x5
+#define R128_TRIANGLE_STRIP 0x6
+
+/* Vertex/indirect buffer size
+ */
+#define R128_BUFFER_SIZE 16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define R128_INDEX_PRIM_OFFSET 20
+#define R128_HOSTDATA_BLIT_OFFSET 32
+
+/* Keep these small for testing
+ */
+#define R128_NR_SAREA_CLIPRECTS 12
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define R128_CARD_HEAP 0
+#define R128_AGP_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 64
+#define R128_LOG_TEX_GRANULARITY 16
+
+#define R128_NR_CONTEXT_REGS 12
+
+#define R128_MAX_TEXTURE_LEVELS 11
+#define R128_MAX_TEXTURE_UNITS 2
+
+#endif /* __R128_SAREA_DEFINES__ */
+
+typedef struct {
+ /* Context state - can be written in one large chunk */
+ unsigned int dst_pitch_offset_c;
+ unsigned int dp_gui_master_cntl_c;
+ unsigned int sc_top_left_c;
+ unsigned int sc_bottom_right_c;
+ unsigned int z_offset_c;
+ unsigned int z_pitch_c;
+ unsigned int z_sten_cntl_c;
+ unsigned int tex_cntl_c;
+ unsigned int misc_3d_state_cntl_reg;
+ unsigned int texture_clr_cmp_clr_c;
+ unsigned int texture_clr_cmp_msk_c;
+ unsigned int fog_color_c;
+
+ /* Texture state */
+ unsigned int tex_size_pitch_c;
+ unsigned int constant_color_c;
+
+ /* Setup state */
+ unsigned int pm4_vc_fpu_setup;
+ unsigned int setup_cntl;
+
+ /* Mask state */
+ unsigned int dp_write_mask;
+ unsigned int sten_ref_mask_c;
+ unsigned int plane_3d_mask_c;
+
+ /* Window state */
+ unsigned int window_xy_offset;
+
+ /* Core state */
+ unsigned int scale_3d_cntl;
+} r128_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+ unsigned int tex_cntl;
+ unsigned int tex_combine_cntl;
+ unsigned int tex_size_pitch;
+ unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
+ unsigned int tex_border_color;
+} r128_texture_regs_t;
+
+typedef struct {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} r128_tex_region_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ r128_context_regs_t ContextState;
+ r128_texture_regs_t TexState[R128_MAX_TEXTURE_UNITS];
+ unsigned int dirty;
+ unsigned int vertsize;
+ unsigned int vc_format;
+
+#ifdef XF86DRI
+ /* The current cliprects, or a subset thereof.
+ */
+ XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+#endif
+
+ /* Counters for throttling of rendering clients.
+ */
+ unsigned int last_frame;
+ unsigned int last_dispatch;
+
+ /* Maintain an LRU of contiguous regions of texture space. If you
+ * think you own a region of texture memory, and it has an age
+ * different to the one you set, then you are mistaken and it has
+ * been stolen by another client. If global texAge hasn't changed,
+ * there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained texture
+ * information of other clients - by maintaining them in the same
+ * lru which is used to age their own textures, clients have an
+ * approximate lru for the whole of global texture space, and can
+ * make informed decisions as to which areas to kick out. There is
+ * no need to choose whether to kick out your own texture or someone
+ * else's - simply eject them all in LRU order.
+ */
+ /* Last elt is sentinal */
+ r128_tex_region_t texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ /* last time texture was uploaded */
+ int texAge[R128_NR_TEX_HEAPS];
+
+ int ctxOwner; /* last context to upload state */
+} R128SAREAPriv, *R128SAREAPrivPtr;
+
+#endif
diff --git a/src/r128_version.h b/src/r128_version.h
new file mode 100644
index 0000000..589d8d4
--- /dev/null
+++ b/src/r128_version.h
@@ -0,0 +1,60 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h,v 1.6 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _R128_VERSION_H_
+#define _R128_VERSION_H_ 1
+
+#undef R128_NAME
+#undef R128_DRIVER_NAME
+#undef R128_VERSION_MAJOR
+#undef R128_VERSION_MINOR
+#undef R128_VERSION_PATCH
+#undef R128_VERSION_CURRENT
+#undef R128_VERSION_EVALUATE
+#undef R128_VERSION_STRINGIFY
+#undef R128_VERSION_NAME
+
+#define R128_NAME "R128"
+#define R128_DRIVER_NAME "r128"
+
+#define R128_VERSION_MAJOR 4
+#define R128_VERSION_MINOR 0
+#define R128_VERSION_PATCH 1
+
+#ifndef R128_VERSION_EXTRA
+#define R128_VERSION_EXTRA ""
+#endif
+
+#define R128_VERSION_CURRENT \
+ ((R128_VERSION_MAJOR << 20) | \
+ (R128_VERSION_MINOR << 10) | \
+ (R128_VERSION_PATCH))
+
+#define R128_VERSION_EVALUATE(__x) #__x
+#define R128_VERSION_STRINGIFY(_x) R128_VERSION_EVALUATE(_x)
+#define R128_VERSION_NAME \
+ R128_VERSION_STRINGIFY(R128_VERSION_MAJOR) "." \
+ R128_VERSION_STRINGIFY(R128_VERSION_MINOR) "." \
+ R128_VERSION_STRINGIFY(R128_VERSION_MINOR) R128_VERSION_EXTRA
+
+#endif /* _R128_VERSION_H_ */
diff --git a/src/r128_video.c b/src/r128_video.c
new file mode 100644
index 0000000..119971f
--- /dev/null
+++ b/src/r128_video.c
@@ -0,0 +1,1143 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.26 2003/02/19 01:19:41 dawes Exp $ */
+
+#include "r128.h"
+#include "r128_reg.h"
+
+#ifdef XF86DRI
+#include "r128_common.h"
+#include "r128_sarea.h"
+#endif
+
+#include "xf86.h"
+#include "dixstruct.h"
+
+#include "Xv.h"
+#include "fourcc.h"
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+#ifndef XvExtension
+void R128InitVideo(ScreenPtr pScreen) {}
+#else
+
+static XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr);
+static int R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static void R128StopVideo(ScrnInfoPtr, pointer, Bool);
+static void R128QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
+ unsigned int *, unsigned int *, pointer);
+static int R128PutImage(ScrnInfoPtr, short, short, short, short, short,
+ short, short, short, int, unsigned char*, short,
+ short, Bool, RegionPtr, pointer);
+static int R128QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
+ unsigned short *, int *, int *);
+
+
+static void R128ResetVideo(ScrnInfoPtr);
+
+static void R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now);
+
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
+
+
+typedef struct {
+ int brightness;
+ int saturation;
+ Bool doubleBuffer;
+ unsigned char currentBuffer;
+ FBLinearPtr linear;
+ RegionRec clip;
+ CARD32 colorKey;
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+} R128PortPrivRec, *R128PortPrivPtr;
+
+
+void R128InitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+ if(info->accel && info->accel->FillSolidRects)
+ newAdaptor = R128SetupImageVideo(pScreen);
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if(newAdaptor) {
+ if(!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ xfree(newAdaptors);
+}
+
+#define MAXWIDTH 2048
+#define MAXHEIGHT 2048
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding =
+{
+ 0,
+ "XV_IMAGE",
+ MAXWIDTH, MAXHEIGHT,
+ {1, 1}
+};
+
+#define NUM_FORMATS 12
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+ {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
+ {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
+ {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
+};
+
+
+#define NUM_ATTRIBUTES 4
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -64, 63, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 31, "XV_SATURATION"},
+ {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
+};
+
+#define NUM_IMAGES 4
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_UYVY,
+ XVIMAGE_YV12,
+ XVIMAGE_I420
+};
+
+static void
+R128ResetVideo(ScrnInfoPtr pScrn)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+
+
+ OUTREG(R128_OV0_SCALE_CNTL, 0x80000000);
+ OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0);
+ OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0); /* maybe */
+ OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f);
+ OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
+ (pPriv->saturation << 8) |
+ (pPriv->saturation << 16));
+ OUTREG(R128_OV0_GRAPHICS_KEY_MSK, (1 << pScrn->depth) - 1);
+ OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey);
+ OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE);
+ OUTREG(R128_OV0_TEST, 0);
+}
+
+
+static XF86VideoAdaptorPtr
+R128AllocAdaptor(ScrnInfoPtr pScrn)
+{
+ XF86VideoAdaptorPtr adapt;
+ R128InfoPtr info = R128PTR(pScrn);
+ R128PortPrivPtr pPriv;
+
+ if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
+ return NULL;
+
+ if(!(pPriv = xcalloc(1, sizeof(R128PortPrivRec) + sizeof(DevUnion))))
+ {
+ xfree(adapt);
+ return NULL;
+ }
+
+ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
+ adapt->pPortPrivates[0].ptr = (pointer)pPriv;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvSaturation = MAKE_ATOM("XV_SATURATION");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+ xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
+
+ pPriv->colorKey = info->videoKey;
+ pPriv->doubleBuffer = TRUE;
+ pPriv->videoStatus = 0;
+ pPriv->brightness = 0;
+ pPriv->saturation = 16;
+ pPriv->currentBuffer = 0;
+
+ return adapt;
+}
+
+static XF86VideoAdaptorPtr
+R128SetupImageVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ R128InfoPtr info = R128PTR(pScrn);
+ R128PortPrivPtr pPriv;
+ XF86VideoAdaptorPtr adapt;
+
+ if(!(adapt = R128AllocAdaptor(pScrn)))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "ATI Rage128 Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = &DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = R128StopVideo;
+ adapt->SetPortAttribute = R128SetPortAttribute;
+ adapt->GetPortAttribute = R128GetPortAttribute;
+ adapt->QueryBestSize = R128QueryBestSize;
+ adapt->PutImage = R128PutImage;
+ adapt->QueryImageAttributes = R128QueryImageAttributes;
+
+ info->adaptor = adapt;
+
+ pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr);
+ REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0);
+
+ R128ResetVideo(pScrn);
+
+ return adapt;
+}
+
+/* I really should stick this in miregion */
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (pointer)REGION_RECTS(A);
+ dataB = (pointer)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* R128ClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (xa, ya
+ inclusive, xb, yb exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+#define DummyScreen screenInfo.screens[0]
+
+static Bool
+R128ClipVideo(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+ int diff;
+
+ hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+ *xa <<= 16; *xb <<= 16;
+ *ya <<= 16; *yb <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *xa += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *xb -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *ya += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *yb -= diff * vscale;
+ }
+
+ if(*xa < 0) {
+ diff = (- *xa + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *xa += diff * hscale;
+ }
+ delta = *xb - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *xb -= diff * hscale;
+ }
+ if(*xa >= *xb) return FALSE;
+
+ if(*ya < 0) {
+ diff = (- *ya + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *ya += diff * vscale;
+ }
+ delta = *yb - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *yb -= diff * vscale;
+ }
+ if(*ya >= *yb) return FALSE;
+
+ if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+ (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+ {
+ RegionRec clipReg;
+ REGION_INIT(DummyScreen, &clipReg, dst, 1);
+ REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+ REGION_UNINIT(DummyScreen, &clipReg);
+ }
+ return TRUE;
+}
+
+static void
+R128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(cleanup) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ OUTREG(R128_OV0_SCALE_CNTL, 0);
+ if (info->cursor_start)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ }
+ if(pPriv->linear) {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+}
+
+static int
+R128SetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ if((value < -64) || (value > 63))
+ return BadValue;
+ pPriv->brightness = value;
+
+ OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
+ (pPriv->saturation << 8) |
+ (pPriv->saturation << 16));
+ } else
+ if(attribute == xvSaturation) {
+ if((value < 0) || (value > 31))
+ return BadValue;
+ pPriv->saturation = value;
+
+ OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
+ (pPriv->saturation << 8) |
+ (pPriv->saturation << 16));
+ } else
+ if(attribute == xvDoubleBuffer) {
+ if((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->doubleBuffer = value;
+ } else
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey);
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+R128GetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvSaturation) {
+ *value = pPriv->saturation;
+ } else
+ if(attribute == xvDoubleBuffer) {
+ *value = pPriv->doubleBuffer ? 1 : 0;
+ } else
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else return BadMatch;
+
+ return Success;
+}
+
+
+static void
+R128QueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > (drw_w << 4))
+ drw_w = vid_w >> 4;
+ if(vid_h > (drw_h << 4))
+ drw_h = vid_h >> 4;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+
+/*
+ *
+ * R128DMA - abuse the texture blit ioctl to transfer rectangular blocks
+ *
+ * The block is split into 'passes' pieces of 'hpass' lines which fit entirely
+ * into an indirect buffer
+ *
+ */
+
+static Bool
+R128DMA(
+ R128InfoPtr info,
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int h,
+ int w
+){
+
+#ifdef XF86DRI
+
+#define BUFSIZE (R128_BUFFER_SIZE - R128_HOSTDATA_BLIT_OFFSET)
+#define MAXPASSES (MAXHEIGHT/(BUFSIZE/(MAXWIDTH*2))+1)
+
+ unsigned char *buf;
+ int err=-1, i, idx, offset, hpass, passes, srcpassbytes, dstpassbytes;
+ int sizes[MAXPASSES], list[MAXPASSES];
+ drmDMAReq req;
+ drmR128Blit blit;
+
+ /* Verify conditions and bail out as early as possible */
+ if (!info->directRenderingEnabled || !info->DMAForXv)
+ return FALSE;
+
+ if ((hpass = min(h,(BUFSIZE/w))) == 0)
+ return FALSE;
+
+ if ((passes = (h+hpass-1)/hpass) > MAXPASSES)
+ return FALSE;
+
+ /* Request indirect buffers */
+ srcpassbytes = w*hpass;
+
+ req.context = info->drmCtx;
+ req.send_count = 0;
+ req.send_list = NULL;
+ req.send_sizes = NULL;
+ req.flags = DRM_DMA_LARGER_OK;
+ req.request_count = passes;
+ req.request_size = srcpassbytes + R128_HOSTDATA_BLIT_OFFSET;
+ req.request_list = &list[0];
+ req.request_sizes = &sizes[0];
+ req.granted_count = 0;
+
+ if (drmDMA(info->drmFD, &req))
+ return FALSE;
+
+ if (req.granted_count < passes) {
+ drmFreeBufs(info->drmFD, req.granted_count, req.request_list);
+ return FALSE;
+ }
+
+ /* Copy parts of the block into buffers and fire them */
+ dstpassbytes = hpass*dstPitch;
+ dstPitch /= 8;
+
+ for (i=0, offset=dst-info->FB; i<passes; i++, offset+=dstpassbytes) {
+ if (i == (passes-1) && (h % hpass) != 0) {
+ hpass = h % hpass;
+ srcpassbytes = w*hpass;
+ }
+
+ idx = req.request_list[i];
+ buf = (unsigned char *) info->buffers->list[idx].address + R128_HOSTDATA_BLIT_OFFSET;
+
+ if (srcPitch == w) {
+ memcpy(buf, src, srcpassbytes);
+ src += srcpassbytes;
+ } else {
+ int count = hpass;
+ while(count--) {
+ memcpy(buf, src, w);
+ src += srcPitch;
+ buf += w;
+ }
+ }
+
+ blit.idx = idx;
+ blit.offset = offset;
+ blit.pitch = dstPitch;
+ blit.format = (R128_DATATYPE_CI8 >> 16);
+ blit.x = (offset % 32);
+ blit.y = 0;
+ blit.width = w;
+ blit.height = hpass;
+
+ if ((err = drmCommandWrite(info->drmFD, DRM_R128_BLIT,
+ &blit, sizeof(drmR128Blit))) < 0)
+ break;
+ }
+
+ drmFreeBufs(info->drmFD, req.granted_count, req.request_list);
+
+ return (err==0) ? TRUE : FALSE;
+
+#else
+
+ /* This is to avoid cluttering the rest of the code with '#ifdef XF86DRI' */
+ return FALSE;
+
+#endif /* XF86DRI */
+
+}
+
+
+static void
+R128CopyData422(
+ R128InfoPtr info,
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int h,
+ int w
+){
+ w <<= 1;
+
+ /* Attempt data transfer with DMA and fall back to memcpy */
+
+ if (!R128DMA(info, src, dst, srcPitch, dstPitch, h, w)) {
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+ }
+}
+
+static void
+R128CopyData420(
+ R128InfoPtr info,
+ unsigned char *src1,
+ unsigned char *src2,
+ unsigned char *src3,
+ unsigned char *dst1,
+ unsigned char *dst2,
+ unsigned char *dst3,
+ int srcPitch,
+ int srcPitch2,
+ int dstPitch,
+ int h,
+ int w
+){
+ int count;
+
+ /* Attempt data transfer with DMA and fall back to memcpy */
+
+ if (!R128DMA(info, src1, dst1, srcPitch, dstPitch, h, w)) {
+ count = h;
+ while(count--) {
+ memcpy(dst1, src1, w);
+ src1 += srcPitch;
+ dst1 += dstPitch;
+ }
+ }
+
+ w >>= 1;
+ h >>= 1;
+ dstPitch >>= 1;
+
+ if (!R128DMA(info, src2, dst2, srcPitch2, dstPitch, h, w)) {
+ count = h;
+ while(count--) {
+ memcpy(dst2, src2, w);
+ src2 += srcPitch2;
+ dst2 += dstPitch;
+ }
+ }
+
+ if (!R128DMA(info, src3, dst3, srcPitch2, dstPitch, h, w)) {
+ count = h;
+ while(count--) {
+ memcpy(dst3, src3, w);
+ src3 += srcPitch2;
+ dst3 += dstPitch;
+ }
+ }
+}
+
+
+static FBLinearPtr
+R128AllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBLinearPtr linear,
+ int size
+){
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+
+ xf86FreeOffscreenLinear(linear);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ NULL, NULL, NULL);
+
+ if(!new_linear) {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
+ PRIORITY_EXTREME);
+
+ if(max_size < size)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ NULL, NULL, NULL);
+ }
+
+ return new_linear;
+}
+
+static void
+R128DisplayVideo422(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset,
+ short width, short height,
+ int pitch,
+ int left, int right, int top,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int v_inc, h_inc, step_by, tmp;
+ int p1_h_accum_init, p23_h_accum_init;
+ int p1_v_accum_init;
+
+ v_inc = (src_h << 20) / drw_h;
+ h_inc = (src_w << 12) / drw_w;
+ step_by = 1;
+
+ while(h_inc >= (2 << 12)) {
+ step_by++;
+ h_inc >>= 1;
+ }
+
+ /* keep everything in 16.16 */
+
+ offset += ((left >> 16) & ~7) << 1;
+
+ tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
+ p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0xf0000000);
+
+ tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
+ p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0x70000000);
+
+ tmp = (top & 0x0000ffff) + 0x00018000;
+ p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
+
+ left = (left >> 16) & 7;
+
+ OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
+ while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)));
+
+ OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
+ OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8));
+ OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16));
+ OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16));
+ OUTREG(R128_OV0_V_INC, v_inc);
+ OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
+ OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch);
+ OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16));
+ left >>= 1; width >>= 1;
+ OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16));
+ OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16));
+ OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0);
+ OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
+ OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0);
+ OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
+ OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
+
+ if(id == FOURCC_UYVY)
+ OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03);
+ else
+ OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03);
+
+ OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
+}
+
+static void
+R128DisplayVideo420(
+ ScrnInfoPtr pScrn,
+ short width, short height,
+ int pitch,
+ int offset1, int offset2, int offset3,
+ int left, int right, int top,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ unsigned char *R128MMIO = info->MMIO;
+ int v_inc, h_inc, step_by, tmp, leftUV;
+ int p1_h_accum_init, p23_h_accum_init;
+ int p1_v_accum_init, p23_v_accum_init;
+
+ v_inc = (src_h << 20) / drw_h;
+ h_inc = (src_w << 12) / drw_w;
+ step_by = 1;
+
+ while(h_inc >= (2 << 12)) {
+ step_by++;
+ h_inc >>= 1;
+ }
+
+ /* keep everything in 16.16 */
+
+ offset1 += (left >> 16) & ~15;
+ offset2 += (left >> 17) & ~15;
+ offset3 += (left >> 17) & ~15;
+
+ tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
+ p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0xf0000000);
+
+ tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
+ p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0x70000000);
+
+ tmp = (top & 0x0000ffff) + 0x00018000;
+ p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
+
+ tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
+ p23_v_accum_init = ((tmp << 4) & 0x01ff8000) | 0x00000001;
+
+ leftUV = (left >> 17) & 15;
+ left = (left >> 16) & 15;
+
+ OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
+ while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)));
+
+ OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
+ OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8));
+ OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16));
+ OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16));
+ OUTREG(R128_OV0_V_INC, v_inc);
+ OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
+ src_h = (src_h + 1) >> 1;
+ OUTREG(R128_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | ((src_h - 1) << 16));
+ OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch);
+ OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1);
+ OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16));
+ width >>= 1;
+ OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16));
+ OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16));
+ OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0);
+ OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, (offset2 & 0xfffffff0) | 0x00000001);
+ OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, (offset3 & 0xfffffff0) | 0x00000001);
+ OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
+ OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init);
+ OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
+ OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
+ OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03);
+
+ OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
+}
+
+
+
+static int
+R128PutImage(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool Sync,
+ RegionPtr clipBoxes, pointer data
+){
+ R128InfoPtr info = R128PTR(pScrn);
+ R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+ INT32 xa, xb, ya, yb;
+ int pitch, new_size, offset, s1offset, s2offset, s3offset;
+ int srcPitch, srcPitch2, dstPitch;
+ int d1line, d2line, d3line, d1offset, d2offset, d3offset;
+ int top, left, npixels, nlines, bpp;
+ BoxRec dstBox;
+ CARD32 tmp;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ unsigned char *R128MMIO = info->MMIO;
+ CARD32 config_cntl = INREG(R128_CONFIG_CNTL);
+
+ /* We need to disable byte swapping, or the data gets mangled */
+ OUTREG(R128_CONFIG_CNTL, config_cntl &
+ ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP));
+#endif
+
+ /*
+ * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes
+ * of the source.
+ *
+ * d1offset, d2offset, d3offset - byte offsets to the Y, U and V planes
+ * of the destination.
+ *
+ * offset - byte offset within the framebuffer to where the destination
+ * is stored.
+ *
+ * d1line, d2line, d3line - byte offsets within the destination to the
+ * first displayed scanline in each plane.
+ *
+ */
+
+ if(src_w > (drw_w << 4))
+ drw_w = src_w >> 4;
+ if(src_h > (drw_h << 4))
+ drw_h = src_h >> 4;
+
+ /* Clip */
+ xa = src_x;
+ xb = src_x + src_w;
+ ya = src_y;
+ yb = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!R128ClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ bpp = pScrn->bitsPerPixel >> 3;
+ pitch = bpp * pScrn->displayWidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ dstPitch = (width + 31) & ~31; /* of luma */
+ new_size = ((dstPitch * (height + (height >> 1))) + bpp - 1) / bpp;
+ s1offset = 0;
+ s2offset = srcPitch * height;
+ s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = width << 1;
+ srcPitch2 = 0;
+ dstPitch = ((width << 1) + 15) & ~15;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ s1offset = 0;
+ s2offset = 0;
+ s3offset = 0;
+ break;
+ }
+
+ if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear,
+ pPriv->doubleBuffer ? (new_size << 1) : new_size)))
+ {
+ return BadAlloc;
+ }
+
+ pPriv->currentBuffer ^= 1;
+
+ /* copy data */
+ top = ya >> 16;
+ left = (xa >> 16) & ~1;
+ npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
+
+ offset = pPriv->linear->offset * bpp;
+ if(pPriv->doubleBuffer)
+ offset += pPriv->currentBuffer * new_size * bpp;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ d1line = top * dstPitch;
+ d2line = (height * dstPitch) + ((top >> 1) * (dstPitch >> 1));
+ d3line = d2line + ((height >> 1) * (dstPitch >> 1));
+
+ top &= ~1;
+
+ d1offset = (top * dstPitch) + left + offset;
+ d2offset = d2line + (left >> 1) + offset;
+ d3offset = d3line + (left >> 1) + offset;
+
+ s1offset += (top * srcPitch) + left;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ s2offset += tmp;
+ s3offset += tmp;
+ if(id == FOURCC_YV12) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+
+ nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
+ R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset,
+ info->FB+d1offset, info->FB+d2offset, info->FB+d3offset,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ left <<= 1;
+ d1line = top * dstPitch;
+ d2line = 0;
+ d3line = 0;
+ d1offset = d1line + left + offset;
+ d2offset = 0;
+ d3offset = 0;
+ s1offset += (top * srcPitch) + left;
+ nlines = ((yb + 0xffff) >> 16) - top;
+ R128CopyData422(info, buf + s1offset, info->FB + d1offset,
+ srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* restore byte swapping */
+ OUTREG(R128_CONFIG_CNTL, config_cntl);
+#endif
+
+ /* update cliplist */
+ if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ (*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy,
+ (CARD32)~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ R128DisplayVideo420(pScrn, width, height, dstPitch,
+ offset + d1line, offset + d2line, offset + d3line,
+ xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch,
+ xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+ break;
+ }
+
+ if (info->cursor_start && !(pPriv->videoStatus & CLIENT_VIDEO_ON))
+ xf86ForceHWCursor (pScrn->pScreen, TRUE);
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ info->VideoTimerCallback = R128VideoTimerCallback;
+
+ return Success;
+}
+
+
+static int
+R128QueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > MAXWIDTH) *w = MAXWIDTH;
+ if(*h > MAXHEIGHT) *h = MAXHEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static void
+R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now)
+{
+ R128InfoPtr info = R128PTR(pScrn);
+ R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < now) {
+ unsigned char *R128MMIO = info->MMIO;
+ OUTREG(R128_OV0_SCALE_CNTL, 0);
+ if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = now + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if(pPriv->freeTime < now) {
+ if(pPriv->linear) {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ pPriv->videoStatus = 0;
+ info->VideoTimerCallback = NULL;
+ }
+ }
+ } else /* shouldn't get here */
+ info->VideoTimerCallback = NULL;
+}
+
+
+#endif /* !XvExtension */
diff --git a/src/radeon.h b/src/radeon.h
new file mode 100644
index 0000000..81e0db7
--- /dev/null
+++ b/src/radeon.h
@@ -0,0 +1,750 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.37 2003/02/23 23:28:48 dawes Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ */
+
+#ifndef _RADEON_H_
+#define _RADEON_H_
+
+#include "xf86str.h"
+
+ /* PCI support */
+#include "xf86Pci.h"
+
+ /* XAA and Cursor Support */
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+ /* DDC support */
+#include "xf86DDC.h"
+
+ /* Xv support */
+#include "xf86xv.h"
+
+ /* DRI support */
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "radeon_dripriv.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#endif
+
+ /* Render support */
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#define RADEON_DEBUG 0 /* Turn off debugging output */
+#define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */
+#define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */
+#define RADEON_MMIOSIZE 0x80000
+
+#define RADEON_VBIOS_SIZE 0x00010000
+#define RADEON_USE_RMX 0x80000000 /* mode flag for using RMX
+ * Need to comfirm this is not used
+ * for something else.
+ */
+
+#if RADEON_DEBUG
+#define RADEONTRACE(x) \
+do { \
+ ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex); \
+ ErrorF x; \
+} while (0);
+#else
+#define RADEONTRACE(x)
+#endif
+
+
+/* Other macros */
+#define RADEON_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
+#define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate)
+
+typedef struct {
+ /* All values in XCLKS */
+ int ML; /* Memory Read Latency */
+ int MB; /* Memory Burst Length */
+ int Trcd; /* RAS to CAS delay */
+ int Trp; /* RAS percentage */
+ int Twr; /* Write Recovery */
+ int CL; /* CAS Latency */
+ int Tr2w; /* Read to Write Delay */
+ int Rloop; /* Loop Latency */
+ int Rloop_fudge; /* Add to ML to get Rloop */
+ char *name;
+} RADEONRAMRec, *RADEONRAMPtr;
+
+typedef struct {
+ /* Common registers */
+ CARD32 ovr_clr;
+ CARD32 ovr_wid_left_right;
+ CARD32 ovr_wid_top_bottom;
+ CARD32 ov0_scale_cntl;
+ CARD32 mpp_tb_config;
+ CARD32 mpp_gp_config;
+ CARD32 subpic_cntl;
+ CARD32 viph_control;
+ CARD32 i2c_cntl_1;
+ CARD32 gen_int_cntl;
+ CARD32 cap0_trig_cntl;
+ CARD32 cap1_trig_cntl;
+ CARD32 bus_cntl;
+ CARD32 surface_cntl;
+
+ /* Other registers to save for VT switches */
+ CARD32 dp_datatype;
+ CARD32 rbbm_soft_reset;
+ CARD32 clock_cntl_index;
+ CARD32 amcgpio_en_reg;
+ CARD32 amcgpio_mask;
+
+ /* CRTC registers */
+ CARD32 crtc_gen_cntl;
+ CARD32 crtc_ext_cntl;
+ CARD32 dac_cntl;
+ CARD32 crtc_h_total_disp;
+ CARD32 crtc_h_sync_strt_wid;
+ CARD32 crtc_v_total_disp;
+ CARD32 crtc_v_sync_strt_wid;
+ CARD32 crtc_offset;
+ CARD32 crtc_offset_cntl;
+ CARD32 crtc_pitch;
+
+ /* CRTC2 registers */
+ CARD32 crtc2_gen_cntl;
+
+ CARD32 dac2_cntl;
+ CARD32 disp_output_cntl;
+ CARD32 disp_hw_debug;
+ CARD32 crtc2_h_total_disp;
+ CARD32 crtc2_h_sync_strt_wid;
+ CARD32 crtc2_v_total_disp;
+ CARD32 crtc2_v_sync_strt_wid;
+ CARD32 crtc2_offset;
+ CARD32 crtc2_offset_cntl;
+ CARD32 crtc2_pitch;
+ /* Flat panel registers */
+ CARD32 fp_crtc_h_total_disp;
+ CARD32 fp_crtc_v_total_disp;
+ CARD32 fp_gen_cntl;
+ CARD32 fp2_gen_cntl;
+ CARD32 fp_h_sync_strt_wid;
+ CARD32 fp2_h_sync_strt_wid;
+ CARD32 fp_horz_stretch;
+ CARD32 fp_panel_cntl;
+ CARD32 fp_v_sync_strt_wid;
+ CARD32 fp2_v_sync_strt_wid;
+ CARD32 fp_vert_stretch;
+ CARD32 lvds_gen_cntl;
+ CARD32 lvds_pll_cntl;
+ CARD32 tmds_pll_cntl;
+
+ /* Computed values for PLL */
+ CARD32 dot_clock_freq;
+ CARD32 pll_output_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ CARD32 ppll_ref_div;
+ CARD32 ppll_div_3;
+ CARD32 htotal_cntl;
+
+ /* Computed values for PLL2 */
+ CARD32 dot_clock_freq_2;
+ CARD32 pll_output_freq_2;
+ int feedback_div_2;
+ int post_div_2;
+
+ /* PLL2 registers */
+ CARD32 p2pll_ref_div;
+ CARD32 p2pll_div_0;
+ CARD32 htotal_cntl2;
+
+ /* Pallet */
+ Bool palette_valid;
+ CARD32 palette[256];
+ CARD32 palette2[256];
+} RADEONSaveRec, *RADEONSavePtr;
+
+typedef struct {
+ CARD16 reference_freq;
+ CARD16 reference_div;
+ CARD32 min_pll_freq;
+ CARD32 max_pll_freq;
+ CARD16 xclk;
+} RADEONPLLRec, *RADEONPLLPtr;
+
+typedef struct {
+ int bitsPerPixel;
+ int depth;
+ int displayWidth;
+ int pixel_code;
+ int pixel_bytes;
+ DisplayModePtr mode;
+} RADEONFBLayout;
+
+typedef enum {
+ MT_NONE,
+ MT_CRT,
+ MT_LCD,
+ MT_DFP,
+ MT_CTV,
+ MT_STV
+} RADEONMonitorType;
+
+typedef enum {
+ DDC_NONE_DETECTED,
+ DDC_MONID,
+ DDC_DVI,
+ DDC_VGA,
+ DDC_CRT2
+} RADEONDDCType;
+
+typedef enum {
+ CONNECTOR_NONE,
+ CONNECTOR_PROPRIETARY,
+ CONNECTOR_CRT,
+ CONNECTOR_DVI_I,
+ CONNECTOR_DVI_D
+} RADEONConnectorType;
+
+typedef enum {
+ CHIP_FAMILY_UNKNOW,
+ CHIP_FAMILY_LEGACY,
+ CHIP_FAMILY_R128,
+ CHIP_FAMILY_M3,
+ CHIP_FAMILY_RADEON,
+ CHIP_FAMILY_VE,
+ CHIP_FAMILY_M6,
+ CHIP_FAMILY_RV200,
+ CHIP_FAMILY_M7,
+ CHIP_FAMILY_R200,
+ CHIP_FAMILY_RV250,
+ CHIP_FAMILY_M9,
+ CHIP_FAMILY_R300
+} RADEONChipFamily;
+
+typedef struct {
+ EntityInfoPtr pEnt;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ int Chipset;
+ RADEONChipFamily ChipFamily;
+
+ Bool FBDev;
+
+ unsigned long LinearAddr; /* Frame buffer physical address */
+ unsigned long MMIOAddr; /* MMIO region physical address */
+ unsigned long BIOSAddr; /* BIOS physical address */
+
+ unsigned char *MMIO; /* Map of MMIO region */
+ unsigned char *FB; /* Map of frame buffer */
+ CARD8 *VBIOS; /* Video BIOS pointer */
+
+ CARD32 MemCntl;
+ CARD32 BusCntl;
+ unsigned long FbMapSize; /* Size of frame buffer, in bytes */
+ int Flags; /* Saved copy of mode flags */
+
+ /* VE/M6 support */
+ RADEONMonitorType DisplayType; /* Monitor connected on */
+ RADEONDDCType DDCType;
+ RADEONConnectorType ConnectorType;
+ Bool HasCRTC2; /* All cards except original Radeon */
+ Bool IsSecondary; /* Second Screen */
+ Bool IsSwitching; /* Flag for switching mode */
+ Bool IsDell; /* Dell OEM VE card */
+ int DellType;
+ Bool Clone; /* Force second head to clone primary*/
+ RADEONMonitorType CloneType;
+ RADEONDDCType CloneDDCType;
+ DisplayModePtr CloneModes;
+ DisplayModePtr CurCloneMode;
+ int CloneFrameX0;
+ int CloneFrameY0;
+ Bool OverlayOnCRTC2;
+ Bool PanelOff; /* Force panel (LCD/DFP) off */
+ int FPBIOSstart; /* Start of the flat panel info */
+ Bool ddc_mode; /* Validate mode by matching exactly
+ * the modes supported in DDC data
+ */
+ Bool R300CGWorkaround;
+
+ /* EDID or BIOS values for FPs */
+ int PanelXRes;
+ int PanelYRes;
+ int HOverPlus;
+ int HSyncWidth;
+ int HBlank;
+ int VOverPlus;
+ int VSyncWidth;
+ int VBlank;
+ int PanelPwrDly;
+ int DotClock;
+
+ /* EDID data using DDC interface */
+ Bool ddc_bios;
+ Bool ddc1;
+ Bool ddc2;
+ I2CBusPtr pI2CBus;
+ CARD32 DDCReg;
+
+ RADEONPLLRec pll;
+ RADEONRAMPtr ram;
+
+ RADEONSaveRec SavedReg; /* Original (text) mode */
+ RADEONSaveRec ModeReg; /* Current mode */
+ Bool (*CloseScreen)(int, ScreenPtr);
+
+ void (*BlockHandler)(int, pointer, pointer, pointer);
+
+ Bool PaletteSavedOnVT; /* Palette saved on last VT switch */
+
+ XAAInfoRecPtr accel;
+ Bool accelOn;
+ xf86CursorInfoPtr cursor;
+ unsigned long cursor_start;
+ unsigned long cursor_end;
+#ifdef ARGB_CURSOR
+ Bool cursor_argb;
+#endif
+ int cursor_fg;
+ int cursor_bg;
+
+ /*
+ * XAAForceTransBlit is used to change the behavior of the XAA
+ * SetupForScreenToScreenCopy function, to make it DGA-friendly.
+ */
+ Bool XAAForceTransBlit;
+
+ int fifo_slots; /* Free slots in the FIFO (64 max) */
+ int pix24bpp; /* Depth of pixmap for 24bpp fb */
+ Bool dac6bits; /* Use 6 bit DAC? */
+
+ /* Computed values for Radeon */
+ int pitch;
+ int datatype;
+ CARD32 dp_gui_master_cntl;
+ CARD32 dp_gui_master_cntl_clip;
+ CARD32 trans_color;
+
+ /* Saved values for ScreenToScreenCopy */
+ int xdir;
+ int ydir;
+
+ /* ScanlineScreenToScreenColorExpand support */
+ unsigned char *scratch_buffer[1];
+ unsigned char *scratch_save;
+ int scanline_x;
+ int scanline_y;
+ int scanline_w;
+ int scanline_h;
+ int scanline_h_w;
+ int scanline_words;
+ int scanline_direct;
+ int scanline_bpp; /* Only used for ImageWrite */
+ int scanline_fg;
+ int scanline_bg;
+ int scanline_hpass;
+ int scanline_x1clip;
+ int scanline_x2clip;
+
+ /* Saved values for DashedTwoPointLine */
+ int dashLen;
+ CARD32 dashPattern;
+ int dash_fg;
+ int dash_bg;
+
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+ DGAFunctionRec DGAFuncs;
+
+ RADEONFBLayout CurrentLayout;
+#ifdef XF86DRI
+ Bool noBackBuffer;
+ Bool directRenderingEnabled;
+ DRIInfoPtr pDRIInfo;
+ int drmFD;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ RADEONConfigPrivPtr pVisualConfigsPriv;
+
+ drmHandle fbHandle;
+
+ drmSize registerSize;
+ drmHandle registerHandle;
+
+ Bool IsPCI; /* Current card is a PCI card */
+ drmSize pciSize;
+ drmHandle pciMemHandle;
+ unsigned char *PCI; /* Map */
+
+ Bool depthMoves; /* Enable depth moves -- slow! */
+ Bool allowPageFlip; /* Enable 3d page flipping */
+ Bool have3DWindows; /* Are there any 3d clients? */
+ int drmMinor;
+
+ drmSize agpSize;
+ drmHandle agpMemHandle; /* Handle from drmAgpAlloc */
+ unsigned long agpOffset;
+ unsigned char *AGP; /* Map */
+ int agpMode;
+ int agpFastWrite;
+
+ CARD32 pciCommand;
+
+ Bool CPRuns; /* CP is running */
+ Bool CPInUse; /* CP has been used by X server */
+ Bool CPStarted; /* CP has started */
+ int CPMode; /* CP mode that server/clients use */
+ int CPFifoSize; /* Size of the CP command FIFO */
+ int CPusecTimeout; /* CP timeout in usecs */
+
+ /* CP ring buffer data */
+ unsigned long ringStart; /* Offset into AGP space */
+ drmHandle ringHandle; /* Handle from drmAddMap */
+ drmSize ringMapSize; /* Size of map */
+ int ringSize; /* Size of ring (in MB) */
+ unsigned char *ring; /* Map */
+ int ringSizeLog2QW;
+
+ unsigned long ringReadOffset; /* Offset into AGP space */
+ drmHandle ringReadPtrHandle; /* Handle from drmAddMap */
+ drmSize ringReadMapSize; /* Size of map */
+ unsigned char *ringReadPtr; /* Map */
+
+ /* CP vertex/indirect buffer data */
+ unsigned long bufStart; /* Offset into AGP space */
+ drmHandle bufHandle; /* Handle from drmAddMap */
+ drmSize bufMapSize; /* Size of map */
+ int bufSize; /* Size of buffers (in MB) */
+ unsigned char *buf; /* Map */
+ int bufNumBufs; /* Number of buffers */
+ drmBufMapPtr buffers; /* Buffer map */
+
+ /* CP AGP Texture data */
+ unsigned long agpTexStart; /* Offset into AGP space */
+ drmHandle agpTexHandle; /* Handle from drmAddMap */
+ drmSize agpTexMapSize; /* Size of map */
+ int agpTexSize; /* Size of AGP tex space (in MB) */
+ unsigned char *agpTex; /* Map */
+ int log2AGPTexGran;
+
+ /* CP accleration */
+ drmBufPtr indirectBuffer;
+ int indirectStart;
+
+ /* DRI screen private data */
+ int fbX;
+ int fbY;
+ int backX;
+ int backY;
+ int depthX;
+ int depthY;
+
+ int frontOffset;
+ int frontPitch;
+ int backOffset;
+ int backPitch;
+ int depthOffset;
+ int depthPitch;
+ int textureOffset;
+ int textureSize;
+ int log2TexGran;
+
+ CARD32 frontPitchOffset;
+ CARD32 backPitchOffset;
+ CARD32 depthPitchOffset;
+
+ CARD32 dst_pitch_offset;
+
+ /* offscreen memory management */
+ int backLines;
+ FBAreaPtr backArea;
+ int depthTexLines;
+ FBAreaPtr depthTexArea;
+
+ /* Saved scissor values */
+ CARD32 sc_left;
+ CARD32 sc_right;
+ CARD32 sc_top;
+ CARD32 sc_bottom;
+
+ CARD32 re_top_left;
+ CARD32 re_width_height;
+
+ CARD32 aux_sc_cntl;
+
+ int irq;
+
+#ifdef PER_CONTEXT_SAREA
+ int perctx_sarea_size;
+#endif
+#endif
+
+ /* XVideo */
+ XF86VideoAdaptorPtr adaptor;
+ void (*VideoTimerCallback)(ScrnInfoPtr, Time);
+ FBLinearPtr videoLinear;
+ int videoKey;
+
+ /* general */
+ Bool showCache;
+ OptionInfoPtr Options;
+#ifdef XFree86LOADER
+ XF86ModReqInfo xaaReq;
+#endif
+} RADEONInfoRec, *RADEONInfoPtr;
+
+#define RADEONWaitForFifo(pScrn, entries) \
+do { \
+ if (info->fifo_slots < entries) \
+ RADEONWaitForFifoFunction(pScrn, entries); \
+ info->fifo_slots -= entries; \
+} while (0)
+
+extern void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
+extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
+#ifdef XF86DRI
+extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
+#endif
+
+extern void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y,
+ int clone);
+
+extern void RADEONEngineReset(ScrnInfoPtr pScrn);
+extern void RADEONEngineFlush(ScrnInfoPtr pScrn);
+extern void RADEONEngineRestore(ScrnInfoPtr pScrn);
+
+extern unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr);
+extern void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn);
+extern void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn);
+
+extern void RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer);
+
+extern Bool RADEONAccelInit(ScreenPtr pScreen);
+extern void RADEONEngineInit(ScrnInfoPtr pScrn);
+extern Bool RADEONCursorInit(ScreenPtr pScreen);
+extern Bool RADEONDGAInit(ScreenPtr pScreen);
+
+extern int RADEONMinBits(int val);
+
+extern void RADEONInitVideo(ScreenPtr pScreen);
+
+extern void R300CGWorkaround(ScrnInfoPtr pScrn);
+
+#ifdef XF86DRI
+extern Bool RADEONDRIScreenInit(ScreenPtr pScreen);
+extern void RADEONDRICloseScreen(ScreenPtr pScreen);
+extern Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen);
+
+extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn);
+extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard);
+extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn);
+extern int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info);
+
+
+#define RADEONCP_START(pScrn, info) \
+do { \
+ int _ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_START); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CP start %d\n", __FUNCTION__, _ret); \
+ } \
+ info->CPStarted = TRUE; \
+} while (0)
+
+#define RADEONCP_STOP(pScrn, info) \
+do { \
+ int _ret; \
+ if (info->CPStarted) { \
+ _ret = RADEONCPStop(pScrn, info); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CP stop %d\n", __FUNCTION__, _ret); \
+ } \
+ info->CPStarted = FALSE; \
+ } \
+ RADEONEngineRestore(pScrn); \
+ info->CPRuns = FALSE; \
+} while (0)
+
+#define RADEONCP_RESET(pScrn, info) \
+do { \
+ if (RADEONCP_USE_RING_BUFFER(info->CPMode)) { \
+ int _ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_RESET); \
+ if (_ret) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
+ "%s: CP reset %d\n", __FUNCTION__, _ret); \
+ } \
+ } \
+} while (0)
+
+#define RADEONCP_REFRESH(pScrn, info) \
+do { \
+ if (!info->CPInUse) { \
+ RADEON_WAIT_UNTIL_IDLE(); \
+ BEGIN_RING(6); \
+ OUT_RING_REG(RADEON_RE_TOP_LEFT, info->re_top_left); \
+ OUT_RING_REG(RADEON_RE_WIDTH_HEIGHT, info->re_width_height); \
+ OUT_RING_REG(RADEON_AUX_SC_CNTL, info->aux_sc_cntl); \
+ ADVANCE_RING(); \
+ info->CPInUse = TRUE; \
+ } \
+} while (0)
+
+
+#define CP_PACKET0(reg, n) \
+ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1(reg0, reg1) \
+ (RADEON_CP_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CP_PACKET2() \
+ (RADEON_CP_PACKET2)
+#define CP_PACKET3(pkt, n) \
+ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+
+#define RADEON_VERBOSE 0
+
+#define RING_LOCALS CARD32 *__head = NULL; int __count = 0
+
+#define BEGIN_RING(n) do { \
+ if (RADEON_VERBOSE) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "BEGIN_RING(%d) in %s\n", n, __FUNCTION__); \
+ } \
+ if (!info->indirectBuffer) { \
+ info->indirectBuffer = RADEONCPGetBuffer(pScrn); \
+ info->indirectStart = 0; \
+ } else if (info->indirectBuffer->used + (n) * (int)sizeof(CARD32) > \
+ info->indirectBuffer->total) { \
+ RADEONCPFlushIndirect(pScrn, 1); \
+ } \
+ __head = (pointer)((char *)info->indirectBuffer->address + \
+ info->indirectBuffer->used); \
+ __count = 0; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if (RADEON_VERBOSE) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "ADVANCE_RING() start: %d used: %d count: %d\n", \
+ info->indirectStart, \
+ info->indirectBuffer->used, \
+ __count * sizeof(CARD32)); \
+ } \
+ info->indirectBuffer->used += __count * (int)sizeof(CARD32); \
+} while (0)
+
+#define OUT_RING(x) do { \
+ if (RADEON_VERBOSE) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ " OUT_RING(0x%08x)\n", (unsigned int)(x)); \
+ } \
+ __head[__count++] = (x); \
+} while (0)
+
+#define OUT_RING_REG(reg, val) \
+do { \
+ OUT_RING(CP_PACKET0(reg, 0)); \
+ OUT_RING(val); \
+} while (0)
+
+#define FLUSH_RING() \
+do { \
+ if (RADEON_VERBOSE) \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "FLUSH_RING in %s\n", __FUNCTION__); \
+ if (info->indirectBuffer) { \
+ RADEONCPFlushIndirect(pScrn, 0); \
+ } \
+} while (0)
+
+
+#define RADEON_WAIT_UNTIL_2D_IDLE() \
+do { \
+ BEGIN_RING(2); \
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); \
+ OUT_RING((RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN)); \
+ ADVANCE_RING(); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE() \
+do { \
+ BEGIN_RING(2); \
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); \
+ OUT_RING((RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN)); \
+ ADVANCE_RING(); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE() \
+do { \
+ if (RADEON_VERBOSE) { \
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \
+ "WAIT_UNTIL_IDLE() in %s\n", __FUNCTION__); \
+ } \
+ BEGIN_RING(2); \
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); \
+ OUT_RING((RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN)); \
+ ADVANCE_RING(); \
+} while (0)
+
+#define RADEON_FLUSH_CACHE() \
+do { \
+ BEGIN_RING(2); \
+ OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(RADEON_RB2D_DC_FLUSH); \
+ ADVANCE_RING(); \
+} while (0)
+
+#define RADEON_PURGE_CACHE() \
+do { \
+ BEGIN_RING(2); \
+ OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(RADEON_RB2D_DC_FLUSH_ALL); \
+ ADVANCE_RING(); \
+} while (0)
+
+#endif /* XF86DRI */
+
+#endif /* _RADEON_H_ */
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
new file mode 100644
index 0000000..1d9fbcf
--- /dev/null
+++ b/src/radeon_accel.c
@@ -0,0 +1,607 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c,v 1.32 2003/01/17 19:54:03 martin Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * Credits:
+ *
+ * Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source
+ * code to his Radeon driver. Portions of this file are based on the
+ * initialization code for that driver.
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ * Notes on unimplemented XAA optimizations:
+ *
+ * SetClipping: This has been removed as XAA expects 16bit registers
+ * for full clipping.
+ * TwoPointLine: The Radeon supports this. Not Bresenham.
+ * DashedLine with non-power-of-two pattern length: Apparently, there is
+ * no way to set the length of the pattern -- it is always
+ * assumed to be 8 or 32 (or 1024?).
+ * ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference
+ * Manual where it states that monochrome expansion of frame
+ * buffer data is not supported.
+ * CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid
+ * direct/indirect method. If we had more data registers,
+ * then we could do better. If XAA supported a trigger write
+ * address, the code would be simpler.
+ * Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8
+ * pattern from frame buffer memory.
+ * ImageWrites: Same as CPUToScreenColorExpandFill
+ *
+ */
+
+ /* Driver data structures */
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_reg.h"
+#include "radeon_version.h"
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "radeon_dri.h"
+#include "radeon_sarea.h"
+#endif
+
+ /* Line support */
+#include "miline.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+static struct {
+ int rop;
+ int pattern;
+} RADEON_ROP[] = {
+ { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */
+ { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */
+ { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */
+ { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */
+ { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */
+ { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */
+ { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */
+ { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */
+ { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */
+ { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */
+ { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */
+ { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */
+ { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */
+ { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */
+ { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */
+ { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */
+};
+
+extern int gRADEONEntityIndex;
+
+/* The FIFO has 64 slots. This routines waits until at least `entries'
+ * of these slots are empty.
+ */
+void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+ for (;;) {
+ for (i = 0; i < RADEON_TIMEOUT; i++) {
+ info->fifo_slots =
+ INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
+ if (info->fifo_slots >= entries) return;
+ }
+ RADEONTRACE(("FIFO timed out: %d entries, stat=0x%08x\n",
+ INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
+ INREG(RADEON_RBBM_STATUS)));
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "FIFO timed out, resetting engine...\n");
+ RADEONEngineReset(pScrn);
+ RADEONEngineRestore(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_RESET(pScrn, info);
+ RADEONCP_START(pScrn, info);
+ }
+#endif
+ }
+}
+
+/* Flush all dirty data in the Pixel Cache to memory */
+void RADEONEngineFlush(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+ OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT,
+ RADEON_RB2D_DC_FLUSH_ALL,
+ ~RADEON_RB2D_DC_FLUSH_ALL);
+ for (i = 0; i < RADEON_TIMEOUT; i++) {
+ if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY))
+ break;
+ }
+}
+
+/* Reset graphics card to known state */
+void RADEONEngineReset(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 clock_cntl_index;
+ CARD32 mclk_cntl;
+ CARD32 rbbm_soft_reset;
+ CARD32 host_path_cntl;
+
+ RADEONEngineFlush(pScrn);
+
+ clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
+ if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+
+ /* Some ASICs have bugs with dynamic-on feature, which are
+ * ASIC-version dependent, so we force all blocks on for now
+ */
+ if (info->HasCRTC2) {
+ CARD32 tmp;
+
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ OUTPLL(RADEON_SCLK_CNTL, ((tmp & ~RADEON_DYN_STOP_LAT_MASK) |
+ RADEON_CP_MAX_DYN_STOP_LAT |
+ RADEON_SCLK_FORCEON_MASK));
+
+ if (info->ChipFamily == CHIP_FAMILY_RV200) {
+ tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
+ OUTPLL(RADEON_SCLK_MORE_CNTL, tmp | RADEON_SCLK_MORE_FORCEON);
+ }
+ }
+
+ mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL);
+ OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
+ RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_MCLKB |
+ RADEON_FORCEON_YCLKA |
+ RADEON_FORCEON_YCLKB |
+ RADEON_FORCEON_MC |
+ RADEON_FORCEON_AIC));
+
+ /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some
+ * unexpected behaviour on some machines. Here we use
+ * RADEON_HOST_PATH_CNTL to reset it.
+ */
+ host_path_cntl = INREG(RADEON_HOST_PATH_CNTL);
+ rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
+
+ if (info->ChipFamily == CHIP_FAMILY_R300) {
+ CARD32 tmp;
+
+ OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+ RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_E2));
+ INREG(RADEON_RBBM_SOFT_RESET);
+ OUTREG(RADEON_RBBM_SOFT_RESET, 0);
+ tmp = INREG(RADEON_RB2D_DSTCACHE_MODE);
+ OUTREG(RADEON_RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
+ } else {
+ OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+ RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB));
+ INREG(RADEON_RBBM_SOFT_RESET);
+ OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (CARD32)
+ ~(RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB)));
+ INREG(RADEON_RBBM_SOFT_RESET);
+ }
+
+ OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET);
+ INREG(RADEON_HOST_PATH_CNTL);
+ OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl);
+
+ if (info->ChipFamily != CHIP_FAMILY_R300)
+ OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTPLL(RADEON_MCLK_CNTL, mclk_cntl);
+ if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+}
+
+/* Restore the acceleration hardware to its previous state */
+void RADEONEngineRestore(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int pitch64;
+
+ RADEONTRACE(("EngineRestore (%d/%d)\n",
+ info->CurrentLayout.pixel_code,
+ info->CurrentLayout.bitsPerPixel));
+
+ RADEONWaitForFifo(pScrn, 1);
+
+ /* NOTE: The following RB2D_DSTCACHE_MODE setting will cause the
+ * R300 to hang. ATI does not see a reason to change it from the
+ * default BIOS settings (even on non-R300 cards). This setting
+ * might be removed in future versions of the Radeon driver.
+ */
+
+ /* Turn of all automatic flushing - we'll do it all */
+ if (info->ChipFamily != CHIP_FAMILY_R300)
+ OUTREG(RADEON_RB2D_DSTCACHE_MODE, 0);
+
+ pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6;
+
+ RADEONWaitForFifo(pScrn, 1);
+ OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000)
+ | (pitch64 << 22)));
+
+ RADEONWaitForFifo(pScrn, 1);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ OUTREGP(RADEON_DP_DATATYPE,
+ RADEON_HOST_BIG_ENDIAN_EN,
+ ~RADEON_HOST_BIG_ENDIAN_EN);
+#else
+ OUTREGP(RADEON_DP_DATATYPE, 0, ~RADEON_HOST_BIG_ENDIAN_EN);
+#endif
+
+ /* Restore SURFACE_CNTL */
+ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl);
+
+ RADEONWaitForFifo(pScrn, 1);
+ OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
+ | RADEON_DEFAULT_SC_BOTTOM_MAX));
+ RADEONWaitForFifo(pScrn, 1);
+ OUTREG(RADEON_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
+ | RADEON_GMC_BRUSH_SOLID_COLOR
+ | RADEON_GMC_SRC_DATATYPE_COLOR));
+
+ RADEONWaitForFifo(pScrn, 7);
+ OUTREG(RADEON_DST_LINE_START, 0);
+ OUTREG(RADEON_DST_LINE_END, 0);
+ OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
+ OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
+ OUTREG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
+ OUTREG(RADEON_DP_SRC_BKGD_CLR, 0x00000000);
+ OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff);
+
+ RADEONWaitForIdleMMIO(pScrn);
+}
+
+/* Initialize the acceleration hardware */
+void RADEONEngineInit(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ RADEONTRACE(("EngineInit (%d/%d)\n",
+ info->CurrentLayout.pixel_code,
+ info->CurrentLayout.bitsPerPixel));
+
+ OUTREG(RADEON_RB3D_CNTL, 0);
+#if defined(__powerpc__)
+#if defined(XF86_DRI)
+ if(!info->directRenderingEnabled)
+#endif
+ {
+ OUTREG(RADEON_MC_FB_LOCATION, 0xffff0000);
+ OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000);
+ }
+#endif
+
+ RADEONEngineReset(pScrn);
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8: info->datatype = 2; break;
+ case 15: info->datatype = 3; break;
+ case 16: info->datatype = 4; break;
+ case 24: info->datatype = 5; break;
+ case 32: info->datatype = 6; break;
+ default:
+ RADEONTRACE(("Unknown depth/bpp = %d/%d (code = %d)\n",
+ info->CurrentLayout.depth,
+ info->CurrentLayout.bitsPerPixel,
+ info->CurrentLayout.pixel_code));
+ }
+ info->pitch = ((info->CurrentLayout.displayWidth / 8) *
+ (info->CurrentLayout.pixel_bytes == 3 ? 3 : 1));
+
+ RADEONTRACE(("Pitch for acceleration = %d\n", info->pitch));
+
+ info->dp_gui_master_cntl =
+ ((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
+ | RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+#ifdef XF86DRI
+ info->sc_left = 0x00000000;
+ info->sc_right = RADEON_DEFAULT_SC_RIGHT_MAX;
+ info->sc_top = 0x00000000;
+ info->sc_bottom = RADEON_DEFAULT_SC_BOTTOM_MAX;
+
+ info->re_top_left = 0x00000000;
+ info->re_width_height = ((0x7ff << RADEON_RE_WIDTH_SHIFT) |
+ (0x7ff << RADEON_RE_HEIGHT_SHIFT));
+
+ info->aux_sc_cntl = 0x00000000;
+#endif
+
+ RADEONEngineRestore(pScrn);
+}
+
+#define ACCEL_MMIO
+#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO
+#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n))
+#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val)
+#define FINISH_ACCEL()
+
+#include "radeon_accelfuncs.c"
+
+#undef ACCEL_MMIO
+#undef ACCEL_PREAMBLE
+#undef BEGIN_ACCEL
+#undef OUT_ACCEL_REG
+#undef FINISH_ACCEL
+
+#ifdef XF86DRI
+
+#define ACCEL_CP
+#define ACCEL_PREAMBLE() \
+ RING_LOCALS; \
+ RADEONCP_REFRESH(pScrn, info)
+#define BEGIN_ACCEL(n) BEGIN_RING(2*(n))
+#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val)
+#define FINISH_ACCEL() ADVANCE_RING()
+
+#include "radeon_accelfuncs.c"
+
+#undef ACCEL_CP
+#undef ACCEL_PREAMBLE
+#undef BEGIN_ACCEL
+#undef OUT_ACCEL_REG
+#undef FINISH_ACCEL
+
+/* Stop the CP */
+int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info)
+{
+ drmRadeonCPStop stop;
+ int ret, i;
+
+ stop.flush = 1;
+ stop.idle = 1;
+
+ ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop,
+ sizeof(drmRadeonCPStop));
+
+ if (ret == 0) {
+ return 0;
+ } else if (errno != EBUSY) {
+ return -errno;
+ }
+
+ stop.flush = 0;
+
+ i = 0;
+ do {
+ ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop,
+ sizeof(drmRadeonCPStop));
+ } while (ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY);
+
+ if (ret == 0) {
+ return 0;
+ } else if (errno != EBUSY) {
+ return -errno;
+ }
+
+ stop.idle = 0;
+
+ if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP,
+ &stop, sizeof(drmRadeonCPStop))) {
+ return -errno;
+ } else {
+ return 0;
+ }
+}
+
+/* Get an indirect buffer for the CP 2D acceleration commands */
+drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ drmDMAReq dma;
+ drmBufPtr buf = NULL;
+ int indx = 0;
+ int size = 0;
+ int i = 0;
+ int ret;
+
+#if 0
+ /* FIXME: pScrn->pScreen has not been initialized when this is first
+ * called from RADEONSelectBuffer via RADEONDRICPInit. We could use
+ * the screen index from pScrn, which is initialized, and then get
+ * the screen from screenInfo.screens[index], but that is a hack.
+ */
+ dma.context = DRIGetContext(pScrn->pScreen);
+#else
+ /* This is the X server's context */
+ dma.context = 0x00000001;
+#endif
+
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = RADEON_BUFFER_SIZE;
+ dma.request_list = &indx;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+ while (1) {
+ do {
+ ret = drmDMA(info->drmFD, &dma);
+ if (ret && ret != -EBUSY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%s: CP GetBuffer %d\n", __FUNCTION__, ret);
+ }
+ } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT));
+
+ if (ret == 0) {
+ buf = &info->buffers->list[indx];
+ buf->used = 0;
+ if (RADEON_VERBOSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ " GetBuffer returning %d %08x\n",
+ buf->idx, buf->address);
+ }
+ return buf;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "GetBuffer timed out, resetting engine...\n");
+ RADEONEngineReset(pScrn);
+ RADEONEngineRestore(pScrn);
+
+ /* Always restart the engine when doing CP 2D acceleration */
+ RADEONCP_RESET(pScrn, info);
+ RADEONCP_START(pScrn, info);
+ }
+}
+
+/* Flush the indirect buffer to the kernel for submission to the card */
+void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ drmBufPtr buffer = info->indirectBuffer;
+ int start = info->indirectStart;
+ drmRadeonIndirect indirect;
+
+ if (!buffer) return;
+ if (start == buffer->used && !discard) return;
+
+ if (RADEON_VERBOSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n",
+ buffer->idx);
+ }
+
+ indirect.idx = buffer->idx;
+ indirect.start = start;
+ indirect.end = buffer->used;
+ indirect.discard = discard;
+
+ drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT,
+ &indirect, sizeof(drmRadeonIndirect));
+
+ if (discard) {
+ info->indirectBuffer = RADEONCPGetBuffer(pScrn);
+ info->indirectStart = 0;
+ } else {
+ /* Start on a double word boundary */
+ info->indirectStart = buffer->used = (buffer->used + 7) & ~7;
+ if (RADEON_VERBOSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Starting at %d\n",
+ info->indirectStart);
+ }
+ }
+}
+
+/* Flush and release the indirect buffer */
+void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ drmBufPtr buffer = info->indirectBuffer;
+ int start = info->indirectStart;
+ drmRadeonIndirect indirect;
+
+ info->indirectBuffer = NULL;
+ info->indirectStart = 0;
+
+ if (!buffer) return;
+
+ if (RADEON_VERBOSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n",
+ buffer->idx);
+ }
+
+ indirect.idx = buffer->idx;
+ indirect.start = start;
+ indirect.end = buffer->used;
+ indirect.discard = 1;
+
+ drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT,
+ &indirect, sizeof(drmRadeonIndirect));
+}
+#endif
+
+/* Initialize XAA for supported acceleration and also initialize the
+ * graphics hardware for acceleration
+ */
+Bool RADEONAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ XAAInfoRecPtr a;
+
+ if (!(a = info->accel = XAACreateInfoRec())) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n");
+ return FALSE;
+ }
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled)
+ RADEONAccelInitCP(pScreen, a);
+ else
+#endif
+ RADEONAccelInitMMIO(pScreen, a);
+
+ RADEONEngineInit(pScrn);
+
+ if (!XAAInit(pScreen, a)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c
new file mode 100644
index 0000000..06dcfd6
--- /dev/null
+++ b/src/radeon_accelfuncs.c
@@ -0,0 +1,1372 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.6 2003/01/29 18:06:06 martin Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ * Michel Dänzer <michel@daenzer.net>
+ *
+ * Credits:
+ *
+ * Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source
+ * code to his Radeon driver. Portions of this file are based on the
+ * initialization code for that driver.
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ * Notes on unimplemented XAA optimizations:
+ *
+ * SetClipping: This has been removed as XAA expects 16bit registers
+ * for full clipping.
+ * TwoPointLine: The Radeon supports this. Not Bresenham.
+ * DashedLine with non-power-of-two pattern length: Apparently, there is
+ * no way to set the length of the pattern -- it is always
+ * assumed to be 8 or 32 (or 1024?).
+ * ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference
+ * Manual where it states that monochrome expansion of frame
+ * buffer data is not supported.
+ * CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid
+ * direct/indirect method. If we had more data registers,
+ * then we could do better. If XAA supported a trigger write
+ * address, the code would be simpler.
+ * Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8
+ * pattern from frame buffer memory.
+ * ImageWrites: Same as CPUToScreenColorExpandFill
+ *
+ */
+
+#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
+#error Cannot define both MMIO and CP acceleration!
+#endif
+
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
+#else
+#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
+#endif
+
+#ifdef ACCEL_MMIO
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
+#else
+#ifdef ACCEL_CP
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
+#else
+#error No accel type defined!
+#endif
+#endif
+
+/* MMIO:
+ *
+ * Wait for the graphics engine to be completely idle: the FIFO has
+ * drained, the Pixel Cache is flushed, and the engine is idle. This is
+ * a standard "sync" function that will make the hardware "quiescent".
+ *
+ * CP:
+ *
+ * Wait until the CP is completely idle: the FIFO has drained and the CP
+ * is idle.
+ */
+void
+FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i = 0;
+
+#ifdef ACCEL_CP
+ /* Make sure the CP is idle first */
+ if (info->CPStarted) {
+ int ret;
+ FLUSH_RING();
+
+ for (;;) {
+ do {
+ ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE);
+ if (ret && ret != -EBUSY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%s: CP idle %d\n", __FUNCTION__, ret);
+ }
+ } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT));
+
+ if (ret == 0) return;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Idle timed out, resetting engine...\n");
+ RADEONEngineReset(pScrn);
+ RADEONEngineRestore(pScrn);
+
+ /* Always restart the engine when doing CP 2D acceleration */
+ RADEONCP_RESET(pScrn, info);
+ RADEONCP_START(pScrn, info);
+ }
+ }
+#endif
+
+ RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n",
+ INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
+ INREG(RADEON_RBBM_STATUS)));
+
+ /* Wait for the engine to go idle */
+ RADEONWaitForFifoFunction(pScrn, 64);
+
+ for (;;) {
+ for (i = 0; i < RADEON_TIMEOUT; i++) {
+ if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) {
+ RADEONEngineFlush(pScrn);
+ return;
+ }
+ }
+ RADEONTRACE(("Idle timed out: %d entries, stat=0x%08x\n",
+ INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
+ INREG(RADEON_RBBM_STATUS)));
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Idle timed out, resetting engine...\n");
+ RADEONEngineReset(pScrn);
+ RADEONEngineRestore(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_RESET(pScrn, info);
+ RADEONCP_START(pScrn, info);
+ }
+#endif
+ }
+}
+
+/* This callback is required for multiheader cards using XAA */
+static void
+FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+#ifdef ACCEL_MMIO
+
+ CARD32 pitch64;
+ RADEONEntPtr pRADEONEnt;
+ DevUnion *pPriv;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+#if 0
+ /* Not working yet */
+ if (pRADEONEnt->IsDRIEnabled) {
+ RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn);
+ RADEONCP_TO_MMIO(pRADEONEnt->pPrimaryScrn, info0);
+ }
+#endif
+ pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6;
+
+ OUTREG(RADEON_DEFAULT_OFFSET, ((pScrn->fbOffset>>10) |
+ (pitch64 << 22)));
+
+ /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */
+
+ RADEONWaitForIdleMMIO(pScrn);
+
+#else /* ACCEL_CP */
+
+ RADEONWaitForFifo(pScrn, 1);
+ OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset);
+
+ RADEONWaitForIdleMMIO(pScrn);
+
+#if 0
+ /* Not working yet */
+ RADEONMMIO_TO_CP(pScrn, info);
+#endif
+
+ /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */
+#endif
+}
+
+/* Setup for XAA SolidFill */
+static void
+FUNC_NAME(RADEONSetupForSolidFill)(ScrnInfoPtr pScrn,
+ int color,
+ int rop,
+ unsigned int planemask)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_BRUSH_SOLID_COLOR
+ | RADEON_GMC_SRC_DATATYPE_COLOR
+ | RADEON_ROP[rop].pattern);
+
+ BEGIN_ACCEL(4);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
+ | RADEON_DST_Y_TOP_TO_BOTTOM));
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA SolidFillRect
+ *
+ * Tests: xtest CH06/fllrctngl, xterm
+ */
+static void
+FUNC_NAME(RADEONSubsequentSolidFillRect)(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(2);
+
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
+ OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
+
+ FINISH_ACCEL();
+}
+
+/* Setup for XAA solid lines */
+static void
+FUNC_NAME(RADEONSetupForSolidLine)(ScrnInfoPtr pScrn,
+ int color,
+ int rop,
+ unsigned int planemask)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_BRUSH_SOLID_COLOR
+ | RADEON_GMC_SRC_DATATYPE_COLOR
+ | RADEON_ROP[rop].pattern);
+
+ if (info->ChipFamily >= CHIP_FAMILY_RV200) {
+ BEGIN_ACCEL(1);
+ OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT,
+ 0x55 << RADEON_BRES_CNTL_SHIFT);
+ }
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA solid horizontal and vertical lines */
+static void
+FUNC_NAME(RADEONSubsequentSolidHorVertLine)(ScrnInfoPtr pScrn,
+ int x, int y,
+ int len,
+ int dir)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int w = 1;
+ int h = 1;
+ ACCEL_PREAMBLE();
+
+ if (dir == DEGREES_0) w = len;
+ else h = len;
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
+ | RADEON_DST_Y_TOP_TO_BOTTOM));
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
+ OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h);
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA solid TwoPointLine line
+ *
+ * Tests: xtest CH06/drwln, ico, Mark Vojkovich's linetest program
+ *
+ * [See http://www.xfree86.org/devel/archives/devel/1999-Jun/0102.shtml for
+ * Mark Vojkovich's linetest program, posted 2Jun99 to devel@xfree86.org.]
+ */
+static void
+FUNC_NAME(RADEONSubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* TODO: Check bounds -- RADEON only has 14 bits */
+
+ if (!(flags & OMIT_LAST))
+ FUNC_NAME(RADEONSubsequentSolidHorVertLine)(pScrn,
+ xb, yb, 1,
+ DEGREES_0);
+
+ BEGIN_ACCEL(2);
+
+ OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa);
+ OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb);
+
+ FINISH_ACCEL();
+}
+
+/* Setup for XAA dashed lines
+ *
+ * Tests: xtest CH05/stdshs, XFree86/drwln
+ *
+ * NOTE: Since we can only accelerate lines with power-of-2 patterns of
+ * length <= 32
+ */
+static void
+FUNC_NAME(RADEONSetupForDashedLine)(ScrnInfoPtr pScrn,
+ int fg,
+ int bg,
+ int rop,
+ unsigned int planemask,
+ int length,
+ unsigned char *pattern)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 pat = *(CARD32 *)(pointer)pattern;
+ ACCEL_PREAMBLE();
+
+ /* Save for determining whether or not to draw last pixel */
+ info->dashLen = length;
+ info->dashPattern = pat;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+# define PAT_SHIFT(pat, shift) (pat >> shift)
+#else
+# define PAT_SHIFT(pat, shift) (pat << shift)
+#endif
+
+ switch (length) {
+ case 2: pat |= PAT_SHIFT(pat, 2); /* fall through */
+ case 4: pat |= PAT_SHIFT(pat, 4); /* fall through */
+ case 8: pat |= PAT_SHIFT(pat, 8); /* fall through */
+ case 16: pat |= PAT_SHIFT(pat, 16);
+ }
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | (bg == -1
+ ? RADEON_GMC_BRUSH_32x1_MONO_FG_LA
+ : RADEON_GMC_BRUSH_32x1_MONO_FG_BG)
+ | RADEON_ROP[rop].pattern
+ | RADEON_GMC_BYTE_LSB_TO_MSB);
+ info->dash_fg = fg;
+ info->dash_bg = bg;
+
+ BEGIN_ACCEL((bg == -1) ? 4 : 5);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
+ if (bg != -1)
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
+ OUT_ACCEL_REG(RADEON_BRUSH_DATA0, pat);
+
+ FINISH_ACCEL();
+}
+
+/* Helper function to draw last point for dashed lines */
+static void
+FUNC_NAME(RADEONDashedLastPel)(ScrnInfoPtr pScrn,
+ int x, int y,
+ int fg)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 dp_gui_master_cntl = info->dp_gui_master_cntl_clip;
+ ACCEL_PREAMBLE();
+
+ dp_gui_master_cntl &= ~RADEON_GMC_BRUSH_DATATYPE_MASK;
+ dp_gui_master_cntl |= RADEON_GMC_BRUSH_SOLID_COLOR;
+
+ dp_gui_master_cntl &= ~RADEON_GMC_SRC_DATATYPE_MASK;
+ dp_gui_master_cntl |= RADEON_GMC_SRC_DATATYPE_COLOR;
+
+ BEGIN_ACCEL(7);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, dp_gui_master_cntl);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
+ OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT
+ | RADEON_DST_Y_TOP_TO_BOTTOM));
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
+ OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (1 << 16) | 1);
+
+ /* Restore old values */
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->dash_fg);
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA dashed line */
+static void
+FUNC_NAME(RADEONSubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int flags,
+ int phase)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* TODO: Check bounds -- RADEON only has 14 bits */
+
+ if (!(flags & OMIT_LAST)) {
+ int deltax = abs(xa - xb);
+ int deltay = abs(ya - yb);
+ int shift;
+
+ if (deltax > deltay) shift = deltax;
+ else shift = deltay;
+
+ shift += phase;
+ shift %= info->dashLen;
+
+ if ((info->dashPattern >> shift) & 1)
+ FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_fg);
+ else if (info->dash_bg != -1)
+ FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_bg);
+ }
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa);
+ OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, phase);
+ OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb);
+
+ FINISH_ACCEL();
+}
+
+/* Set up for transparency
+ *
+ * Mmmm, Seems as though the transparency compare is opposite to r128.
+ * It should only draw when source != trans_color, this is the opposite
+ * of that.
+ */
+static void
+FUNC_NAME(RADEONSetTransparency)(ScrnInfoPtr pScrn,
+ int trans_color)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if ((trans_color != -1) || (info->XAAForceTransBlit == TRUE)) {
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_CLR_CMP_CLR_SRC, trans_color);
+ OUT_ACCEL_REG(RADEON_CLR_CMP_MASK, RADEON_CLR_CMP_MSK);
+ OUT_ACCEL_REG(RADEON_CLR_CMP_CNTL, (RADEON_SRC_CMP_EQ_COLOR
+ | RADEON_CLR_CMP_SRC_SOURCE));
+
+ FINISH_ACCEL();
+ }
+}
+
+/* Setup for XAA screen-to-screen copy
+ *
+ * Tests: xtest CH06/fllrctngl (also tests transparency)
+ */
+static void
+FUNC_NAME(RADEONSetupForScreenToScreenCopy)(ScrnInfoPtr pScrn,
+ int xdir, int ydir,
+ int rop,
+ unsigned int planemask,
+ int trans_color)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ info->xdir = xdir;
+ info->ydir = ydir;
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_BRUSH_NONE
+ | RADEON_GMC_SRC_DATATYPE_COLOR
+ | RADEON_ROP[rop].rop
+ | RADEON_DP_SRC_SOURCE_MEMORY);
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_DP_CNTL,
+ ((xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
+ (ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
+
+ FINISH_ACCEL();
+
+ info->trans_color = trans_color;
+ FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
+}
+
+/* Subsequent XAA screen-to-screen copy */
+static void
+FUNC_NAME(RADEONSubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int w, int h)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ if (info->xdir < 0) xa += w - 1, xb += w - 1;
+ if (info->ydir < 0) ya += h - 1, yb += h - 1;
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_SRC_Y_X, (ya << 16) | xa);
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (yb << 16) | xb);
+ OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
+
+ FINISH_ACCEL();
+}
+
+/* Setup for XAA mono 8x8 pattern color expansion. Patterns with
+ * transparency use `bg == -1'. This routine is only used if the XAA
+ * pixmap cache is turned on.
+ *
+ * Tests: xtest XFree86/fllrctngl (no other test will test this routine with
+ * both transparency and non-transparency)
+ */
+static void
+FUNC_NAME(RADEONSetupForMono8x8PatternFill)(ScrnInfoPtr pScrn,
+ int patternx,
+ int patterny,
+ int fg,
+ int bg,
+ int rop,
+ unsigned int planemask)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ unsigned char pattern[8];
+#endif
+ ACCEL_PREAMBLE();
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* Take care of endianness */
+ pattern[0] = (patternx & 0x000000ff);
+ pattern[1] = (patternx & 0x0000ff00) >> 8;
+ pattern[2] = (patternx & 0x00ff0000) >> 16;
+ pattern[3] = (patternx & 0xff000000) >> 24;
+ pattern[4] = (patterny & 0x000000ff);
+ pattern[5] = (patterny & 0x0000ff00) >> 8;
+ pattern[6] = (patterny & 0x00ff0000) >> 16;
+ pattern[7] = (patterny & 0xff000000) >> 24;
+#endif
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | (bg == -1
+ ? RADEON_GMC_BRUSH_8X8_MONO_FG_LA
+ : RADEON_GMC_BRUSH_8X8_MONO_FG_BG)
+ | RADEON_ROP[rop].pattern
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ | RADEON_GMC_BYTE_MSB_TO_LSB
+#endif
+ );
+
+ BEGIN_ACCEL((bg == -1) ? 5 : 6);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
+ if (bg != -1)
+ OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, bg);
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ OUT_ACCEL_REG(RADEON_BRUSH_DATA0, patternx);
+ OUT_ACCEL_REG(RADEON_BRUSH_DATA1, patterny);
+#else
+ OUT_ACCEL_REG(RADEON_BRUSH_DATA0, *(CARD32 *)(pointer)&pattern[0]);
+ OUT_ACCEL_REG(RADEON_BRUSH_DATA1, *(CARD32 *)(pointer)&pattern[4]);
+#endif
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA 8x8 pattern color expansion. Because they are used in
+ * the setup function, `patternx' and `patterny' are not used here.
+ */
+static void
+FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn,
+ int patternx,
+ int patterny,
+ int x, int y,
+ int w, int h)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (patterny << 8) | patternx);
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
+ OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
+
+ FINISH_ACCEL();
+}
+
+#if 0
+/* Setup for XAA color 8x8 pattern fill
+ *
+ * Tests: xtest XFree86/fllrctngl (with Mono8x8PatternFill off)
+ */
+static void
+FUNC_NAME(RADEONSetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int rop,
+ unsigned int planemask,
+ int trans_color)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_BRUSH_8x8_COLOR
+ | RADEON_GMC_SRC_DATATYPE_COLOR
+ | RADEON_ROP[rop].pattern
+ | RADEON_DP_SRC_SOURCE_MEMORY);
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_SRC_Y_X, (paty << 16) | patx);
+
+ FINISH_ACCEL();
+
+ info->trans_color = trans_color;
+ FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
+}
+
+/* Subsequent XAA 8x8 pattern color expansion */
+static void
+FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int x, int y,
+ int w, int h)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (paty << 16) | patx);
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x);
+ OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
+
+ FINISH_ACCEL();
+}
+#endif
+
+#ifdef ACCEL_CP
+#define CP_BUFSIZE (info->indirectBuffer->total/4-9)
+
+/* Helper function to write out a HOSTDATA_BLT packet into the indirect
+ * buffer and set the XAA scratch buffer address appropriately.
+ */
+static void
+RADEONCPScanlinePacket(ScrnInfoPtr pScrn, int bufno)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int chunk_words = info->scanline_hpass * info->scanline_words;
+ ACCEL_PREAMBLE();
+
+ if (RADEON_VERBOSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "CPScanline Packet h=%d hpass=%d chunkwords=%d\n",
+ info->scanline_h, info->scanline_hpass, chunk_words);
+ }
+ BEGIN_RING(chunk_words+9);
+
+ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+9-2));
+ OUT_RING(info->dp_gui_master_cntl_clip);
+ OUT_RING((info->scanline_y << 16) |
+ (info->scanline_x1clip & 0xffff));
+ OUT_RING(((info->scanline_y+info->scanline_hpass) << 16) |
+ (info->scanline_x2clip & 0xffff));
+ OUT_RING(info->scanline_fg);
+ OUT_RING(info->scanline_bg);
+ OUT_RING((info->scanline_y << 16) |
+ (info->scanline_x & 0xffff));
+ OUT_RING((info->scanline_hpass << 16) |
+ (info->scanline_w & 0xffff));
+ OUT_RING(chunk_words);
+
+ info->scratch_buffer[bufno] = (unsigned char *)&__head[__count];
+ __count += chunk_words;
+
+ /* The ring can only be advanced after the __head and __count have
+ been adjusted above */
+ FINISH_ACCEL();
+
+ info->scanline_y += info->scanline_hpass;
+ info->scanline_h -= info->scanline_hpass;
+}
+#endif
+
+/* Setup for XAA indirect CPU-to-screen color expansion (indirect).
+ * Because of how the scratch buffer is initialized, this is really a
+ * mainstore-to-screen color expansion. Transparency is supported when
+ * `bg == -1'.
+ */
+static void
+FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn,
+ int fg,
+ int bg,
+ int rop,
+ unsigned int
+ planemask)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_DST_CLIPPING
+ | RADEON_GMC_BRUSH_NONE
+ | (bg == -1
+ ? RADEON_GMC_SRC_DATATYPE_MONO_FG_LA
+ : RADEON_GMC_SRC_DATATYPE_MONO_FG_BG)
+ | RADEON_ROP[rop].rop
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ | RADEON_GMC_BYTE_LSB_TO_MSB
+#else
+ | RADEON_GMC_BYTE_MSB_TO_LSB
+#endif
+ | RADEON_DP_SRC_SOURCE_HOST_DATA);
+
+#ifdef ACCEL_MMIO
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ BEGIN_ACCEL(4);
+#else
+ BEGIN_ACCEL(5);
+
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
+#endif
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+ OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR, fg);
+ OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR, bg);
+
+#else /* ACCEL_CP */
+
+ info->scanline_fg = fg;
+ info->scanline_bg = bg;
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ BEGIN_ACCEL(1);
+#else
+ BEGIN_ACCEL(2);
+
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT);
+#endif
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+
+#endif
+
+ FINISH_ACCEL();
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion. This is only
+ * called once for each rectangle.
+ */
+static void
+FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr
+ pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+#ifdef ACCEL_MMIO
+ ACCEL_PREAMBLE();
+
+ info->scanline_h = h;
+ info->scanline_words = (w + 31) >> 5;
+
+#ifdef __alpha__
+ /* Always use indirect for Alpha */
+ if (0)
+#else
+ if ((info->scanline_words * h) <= 9)
+#endif
+ {
+ /* Turn on direct for less than 9 dword colour expansion */
+ info->scratch_buffer[0] =
+ (unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
+ - (info->scanline_words - 1));
+ info->scanline_direct = 1;
+ } else {
+ /* Use indirect for anything else */
+ info->scratch_buffer[0] = info->scratch_save;
+ info->scanline_direct = 0;
+ }
+
+ BEGIN_ACCEL(4 + (info->scanline_direct ?
+ (info->scanline_words * h) : 0));
+
+ OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft)
+ & 0xffff));
+ OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff));
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | (x & 0xffff));
+ /* Have to pad the width here and use clipping engine */
+ OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | ((w + 31) & ~31));
+
+ FINISH_ACCEL();
+
+#else /* ACCEL_CP */
+
+ info->scanline_x = x;
+ info->scanline_y = y;
+ /* Have to pad the width here and use clipping engine */
+ info->scanline_w = (w + 31) & ~31;
+ info->scanline_h = h;
+
+ info->scanline_x1clip = x + skipleft;
+ info->scanline_x2clip = x + w;
+
+ info->scanline_words = info->scanline_w / 32;
+ info->scanline_hpass = min(h,(CP_BUFSIZE/info->scanline_words));
+
+ RADEONCPScanlinePacket(pScrn, 0);
+
+#endif
+}
+
+/* Subsequent XAA indirect CPU-to-screen color expansion and indirect
+ * image write. This is called once for each scanline.
+ */
+static void
+FUNC_NAME(RADEONSubsequentScanline)(ScrnInfoPtr pScrn,
+ int bufno)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+#ifdef ACCEL_MMIO
+ CARD32 *p = (pointer)info->scratch_buffer[bufno];
+ int i;
+ int left = info->scanline_words;
+ volatile CARD32 *d;
+ ACCEL_PREAMBLE();
+
+ if (info->scanline_direct) return;
+
+ --info->scanline_h;
+
+ while (left) {
+ write_mem_barrier();
+ if (left <= 8) {
+ /* Last scanline - finish write to DATA_LAST */
+ if (info->scanline_h == 0) {
+ BEGIN_ACCEL(left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(RADEON_HOST_DATA_LAST) - (left - 1); left; --left)
+ *d++ = *p++;
+ return;
+ } else {
+ BEGIN_ACCEL(left);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(RADEON_HOST_DATA7) - (left - 1); left; --left)
+ *d++ = *p++;
+ }
+ } else {
+ BEGIN_ACCEL(8);
+ /* Unrolling doesn't improve performance */
+ for (d = ADDRREG(RADEON_HOST_DATA0), i = 0; i < 8; i++)
+ *d++ = *p++;
+ left -= 8;
+ }
+ }
+
+ FINISH_ACCEL();
+
+#else /* ACCEL_CP */
+
+ if (--info->scanline_hpass) {
+ info->scratch_buffer[bufno] += 4 * info->scanline_words;
+ } else if (info->scanline_h) {
+ info->scanline_hpass =
+ min(info->scanline_h,(CP_BUFSIZE/info->scanline_words));
+ RADEONCPScanlinePacket(pScrn, bufno);
+ }
+
+#endif
+}
+
+/* Setup for XAA indirect image write */
+static void
+FUNC_NAME(RADEONSetupForScanlineImageWrite)(ScrnInfoPtr pScrn,
+ int rop,
+ unsigned int planemask,
+ int trans_color,
+ int bpp,
+ int depth)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ info->scanline_bpp = bpp;
+
+ /* Save for later clipping */
+ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl
+ | RADEON_GMC_DST_CLIPPING
+ | RADEON_GMC_BRUSH_NONE
+ | RADEON_GMC_SRC_DATATYPE_COLOR
+ | RADEON_ROP[rop].rop
+ | RADEON_GMC_BYTE_MSB_TO_LSB
+ | RADEON_DP_SRC_SOURCE_HOST_DATA);
+
+#ifdef ACCEL_MMIO
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ BEGIN_ACCEL(2);
+#else
+ BEGIN_ACCEL(3);
+
+ if (bpp == 16)
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_16BIT);
+ else if (bpp == 32)
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT);
+ else
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
+#endif
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+
+#else /* ACCEL_CP */
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ BEGIN_ACCEL(1);
+#else
+ BEGIN_ACCEL(2);
+
+ if (bpp == 16)
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW);
+ else
+ OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
+#endif
+#endif
+ OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
+
+ FINISH_ACCEL();
+
+ info->trans_color = trans_color;
+ FUNC_NAME(RADEONSetTransparency)(pScrn, trans_color);
+}
+
+/* Subsequent XAA indirect image write. This is only called once for
+ * each rectangle.
+ */
+static void
+FUNC_NAME(RADEONSubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef ACCEL_MMIO
+
+ int shift = 0; /* 32bpp */
+ ACCEL_PREAMBLE();
+
+ if (pScrn->bitsPerPixel == 8) shift = 3;
+ else if (pScrn->bitsPerPixel == 16) shift = 1;
+
+ info->scanline_h = h;
+ info->scanline_words = (w * info->scanline_bpp + 31) >> 5;
+
+#ifdef __alpha__
+ /* Always use indirect for Alpha */
+ if (0)
+#else
+ if ((info->scanline_words * h) <= 9)
+#endif
+ {
+ /* Turn on direct for less than 9 dword colour expansion */
+ info->scratch_buffer[0]
+ = (unsigned char *)(ADDRREG(RADEON_HOST_DATA_LAST)
+ - (info->scanline_words - 1));
+ info->scanline_direct = 1;
+ } else {
+ /* Use indirect for anything else */
+ info->scratch_buffer[0] = info->scratch_save;
+ info->scanline_direct = 0;
+ }
+
+ BEGIN_ACCEL(4 + (info->scanline_direct ?
+ (info->scanline_words * h) : 0));
+
+ OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft)
+ & 0xffff));
+ OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff));
+ OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | (x & 0xffff));
+ /* Have to pad the width here and use clipping engine */
+ OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | ((w + shift) &
+ ~shift));
+
+ FINISH_ACCEL();
+
+#else /* ACCEL_CP */
+
+ int pad = 0; /* 32bpp */
+
+ if (pScrn->bitsPerPixel == 8) pad = 3;
+ else if (pScrn->bitsPerPixel == 16) pad = 1;
+
+ info->scanline_x = x;
+ info->scanline_y = y;
+ /* Have to pad the width here and use clipping engine */
+ info->scanline_w = (w + pad) & ~pad;
+ info->scanline_h = h;
+
+ info->scanline_x1clip = x + skipleft;
+ info->scanline_x2clip = x + w;
+
+ info->scanline_words = (w * info->scanline_bpp + 31) / 32;
+ info->scanline_hpass = min(h,(CP_BUFSIZE/info->scanline_words));
+
+ RADEONCPScanlinePacket(pScrn, 0);
+
+#endif
+}
+
+/* Set up the clipping rectangle */
+static void
+FUNC_NAME(RADEONSetClippingRectangle)(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long tmp1 = 0;
+ unsigned long tmp2 = 0;
+ ACCEL_PREAMBLE();
+
+ if (xa < 0) {
+ tmp1 = (-xa) & 0x3fff;
+ tmp1 |= RADEON_SC_SIGN_MASK_LO;
+ } else {
+ tmp1 = xa;
+ }
+
+ if (ya < 0) {
+ tmp1 |= (((-ya) & 0x3fff) << 16);
+ tmp1 |= RADEON_SC_SIGN_MASK_HI;
+ } else {
+ tmp1 |= (ya << 16);
+ }
+
+ xb++; yb++;
+
+ if (xb < 0) {
+ tmp2 = (-xb) & 0x3fff;
+ tmp2 |= RADEON_SC_SIGN_MASK_LO;
+ } else {
+ tmp2 = xb;
+ }
+
+ if (yb < 0) {
+ tmp2 |= (((-yb) & 0x3fff) << 16);
+ tmp2 |= RADEON_SC_SIGN_MASK_HI;
+ } else {
+ tmp2 |= (yb << 16);
+ }
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl_clip
+ | RADEON_GMC_DST_CLIPPING));
+ OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, tmp1);
+ OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, tmp2);
+
+ FINISH_ACCEL();
+
+ FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color);
+}
+
+/* Disable the clipping rectangle */
+static void
+FUNC_NAME(RADEONDisableClipping)(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(3);
+
+ OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->dp_gui_master_cntl_clip);
+ OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, 0);
+ OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX |
+ RADEON_DEFAULT_SC_BOTTOM_MAX));
+
+ FINISH_ACCEL();
+
+ FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color);
+}
+
+#ifdef ACCEL_CP
+/* Point the DST_PITCH_OFFSET register at the current buffer. This
+ * allows us to interact with the back and depth buffers. All CP 2D
+ * acceleration commands use the DST_PITCH_OFFSET register.
+ */
+void
+RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ switch (buffer) {
+ case RADEON_BACK:
+ info->dst_pitch_offset = info->backPitchOffset;
+ break;
+ case RADEON_DEPTH:
+ info->dst_pitch_offset = info->depthPitchOffset;
+ break;
+ default:
+ case RADEON_FRONT:
+ info->dst_pitch_offset = info->frontPitchOffset;
+ break;
+ }
+
+ BEGIN_ACCEL(1);
+
+ OUT_ACCEL_REG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset);
+
+ FINISH_ACCEL();
+}
+#endif
+
+static void
+FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ a->Flags = (PIXMAP_CACHE
+ | OFFSCREEN_PIXMAPS
+ | LINEAR_FRAMEBUFFER);
+
+ /* Sync */
+ a->Sync = FUNC_NAME(RADEONWaitForIdle);
+
+ /* Solid Filled Rectangle */
+ a->PolyFillRectSolidFlags = 0;
+ a->SetupForSolidFill
+ = FUNC_NAME(RADEONSetupForSolidFill);
+ a->SubsequentSolidFillRect
+ = FUNC_NAME(RADEONSubsequentSolidFillRect);
+
+ /* Screen-to-screen Copy */
+ a->ScreenToScreenCopyFlags = 0;
+ a->SetupForScreenToScreenCopy
+ = FUNC_NAME(RADEONSetupForScreenToScreenCopy);
+ a->SubsequentScreenToScreenCopy
+ = FUNC_NAME(RADEONSubsequentScreenToScreenCopy);
+
+ /* Mono 8x8 Pattern Fill (Color Expand) */
+ a->SetupForMono8x8PatternFill
+ = FUNC_NAME(RADEONSetupForMono8x8PatternFill);
+ a->SubsequentMono8x8PatternFillRect
+ = FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect);
+ a->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS
+ | HARDWARE_PATTERN_PROGRAMMED_ORIGIN
+ | HARDWARE_PATTERN_SCREEN_ORIGIN);
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ if (info->ChipFamily >= CHIP_FAMILY_RV200)
+ a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_MSBFIRST;
+ else
+ a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
+#else
+ a->Mono8x8PatternFillFlags |= BIT_ORDER_IN_BYTE_LSBFIRST;
+#endif
+
+ /* Indirect CPU-To-Screen Color Expand */
+
+ /* RADEON gets upset, when using HOST provided data without a source
+ rop. To show run 'xtest's drwarc. */
+ a->ScanlineCPUToScreenColorExpandFillFlags
+ = (LEFT_EDGE_CLIPPING
+ | ROP_NEEDS_SOURCE
+ | LEFT_EDGE_CLIPPING_NEGATIVE_X);
+ a->NumScanlineColorExpandBuffers = 1;
+ a->ScanlineColorExpandBuffers = info->scratch_buffer;
+ info->scratch_save
+ = xalloc(((pScrn->virtualX+31)/32*4)
+ + (pScrn->virtualX * info->CurrentLayout.pixel_bytes));
+ info->scratch_buffer[0] = info->scratch_save;
+ a->SetupForScanlineCPUToScreenColorExpandFill
+ = FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill);
+ a->SubsequentScanlineCPUToScreenColorExpandFill
+ = FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill);
+ a->SubsequentColorExpandScanline = FUNC_NAME(RADEONSubsequentScanline);
+
+ /* Solid Lines */
+ a->SetupForSolidLine
+ = FUNC_NAME(RADEONSetupForSolidLine);
+ a->SubsequentSolidHorVertLine
+ = FUNC_NAME(RADEONSubsequentSolidHorVertLine);
+
+#ifdef XFree86LOADER
+ if (info->xaaReq.minorversion >= 1) {
+#endif
+
+ /* RADEON only supports 14 bits for lines and clipping and only
+ * draws lines that are completely on-screen correctly. This will
+ * cause display corruption problem in the cases when out-of-range
+ * commands are issued, like when dimming screen during GNOME logout
+ * in dual-head setup. Solid and dashed lines are therefore limited
+ * to the virtual screen.
+ */
+
+ a->SolidLineFlags = LINE_LIMIT_COORDS;
+ a->SolidLineLimits.x1 = 0;
+ a->SolidLineLimits.y1 = 0;
+ a->SolidLineLimits.x2 = pScrn->virtualX-1;
+ a->SolidLineLimits.y2 = pScrn->virtualY-1;
+
+ /* Call miSetZeroLineBias() to have mi/mfb/cfb/fb routines match
+ hardware accel two point lines */
+ miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8));
+
+ a->SubsequentSolidTwoPointLine
+ = FUNC_NAME(RADEONSubsequentSolidTwoPointLine);
+
+ /* Disabled on RV200 and newer because it does not pass XTest */
+ if (info->ChipFamily < CHIP_FAMILY_RV200) {
+ a->SetupForDashedLine
+ = FUNC_NAME(RADEONSetupForDashedLine);
+ a->SubsequentDashedTwoPointLine
+ = FUNC_NAME(RADEONSubsequentDashedTwoPointLine);
+ a->DashPatternMaxLength = 32;
+ /* ROP3 doesn't seem to work properly for dashedline with GXinvert */
+ a->DashedLineFlags = (LINE_PATTERN_LSBFIRST_LSBJUSTIFIED
+ | LINE_PATTERN_POWER_OF_2_ONLY
+ | LINE_LIMIT_COORDS
+ | ROP_NEEDS_SOURCE);
+ a->DashedLineLimits.x1 = 0;
+ a->DashedLineLimits.y1 = 0;
+ a->DashedLineLimits.x2 = pScrn->virtualX-1;
+ a->DashedLineLimits.y2 = pScrn->virtualY-1;
+ }
+
+#ifdef XFree86LOADER
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "libxaa too old, can't accelerate TwoPoint lines\n");
+ }
+#endif
+
+ /* Clipping, note that without this, all line accelerations will
+ * not be called
+ */
+ a->SetClippingRectangle
+ = FUNC_NAME(RADEONSetClippingRectangle);
+ a->DisableClipping
+ = FUNC_NAME(RADEONDisableClipping);
+ a->ClippingFlags
+ = (HARDWARE_CLIP_SOLID_LINE
+ | HARDWARE_CLIP_DASHED_LINE
+ /* | HARDWARE_CLIP_SOLID_FILL -- seems very slow with this on */
+ | HARDWARE_CLIP_MONO_8x8_FILL
+ | HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY);
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+
+ /* If there are more than one devices sharing this entity, we
+ * have to assign this call back, otherwise the XAA will be
+ * disabled
+ */
+#ifdef ACCEL_MMIO
+ if (pRADEONEnt->HasSecondary || pRADEONEnt->BypassSecondary)
+#else /* ACCEL_CP */
+ if (!info->IsSecondary && xf86IsEntityShared(pScrn->entityList[0]))
+#endif
+ a->RestoreAccelState = FUNC_NAME(RADEONRestoreAccelState);
+ }
+
+ /* ImageWrite */
+ a->NumScanlineImageWriteBuffers = 1;
+ a->ScanlineImageWriteBuffers = info->scratch_buffer;
+ a->SetupForScanlineImageWrite
+ = FUNC_NAME(RADEONSetupForScanlineImageWrite);
+ a->SubsequentScanlineImageWriteRect
+ = FUNC_NAME(RADEONSubsequentScanlineImageWriteRect);
+ a->SubsequentImageWriteScanline = FUNC_NAME(RADEONSubsequentScanline);
+ a->ScanlineImageWriteFlags = (CPU_TRANSFER_PAD_DWORD
+#ifdef ACCEL_MMIO
+ /* Performance tests show that we shouldn't use GXcopy
+ * for uploads as a memcpy is faster
+ */
+ | NO_GXCOPY
+#endif
+ /* RADEON gets upset, when using HOST provided data
+ * without a source rop. To show run 'xtest's ptimg
+ */
+ | ROP_NEEDS_SOURCE
+ | SCANLINE_PAD_DWORD
+ | LEFT_EDGE_CLIPPING
+ | LEFT_EDGE_CLIPPING_NEGATIVE_X);
+
+#if 0
+ /* Color 8x8 Pattern Fill */
+ a->SetupForColor8x8PatternFill
+ = FUNC_NAME(RADEONSetupForColor8x8PatternFill);
+ a->SubsequentColor8x8PatternFillRect
+ = FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect);
+ a->Color8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_ORIGIN
+ | HARDWARE_PATTERN_SCREEN_ORIGIN
+ | BIT_ORDER_IN_BYTE_LSBFIRST);
+#endif
+}
+
+#undef FUNC_NAME
diff --git a/src/radeon_common.h b/src/radeon_common.h
new file mode 100644
index 0000000..bbc80a7
--- /dev/null
+++ b/src/radeon_common.h
@@ -0,0 +1,432 @@
+/* radeon_common.h -- common header definitions for Radeon 2D/3D/DRM suite
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ * Gareth Hughes <gareth@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Converted to common header format:
+ * Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.1 2002/10/30 12:52:13 alanh Exp $
+ *
+ */
+
+#ifndef _RADEON_COMMON_H_
+#define _RADEON_COMMON_H_
+
+#include "xf86drm.h"
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (radeon_drm.h)
+ */
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_RADEON_CP_INIT 0x00
+#define DRM_RADEON_CP_START 0x01
+#define DRM_RADEON_CP_STOP 0x02
+#define DRM_RADEON_CP_RESET 0x03
+#define DRM_RADEON_CP_IDLE 0x04
+#define DRM_RADEON_RESET 0x05
+#define DRM_RADEON_FULLSCREEN 0x06
+#define DRM_RADEON_SWAP 0x07
+#define DRM_RADEON_CLEAR 0x08
+#define DRM_RADEON_VERTEX 0x09
+#define DRM_RADEON_INDICES 0x0a
+#define DRM_RADEON_STIPPLE 0x0c
+#define DRM_RADEON_INDIRECT 0x0d
+#define DRM_RADEON_TEXTURE 0x0e
+#define DRM_RADEON_VERTEX2 0x0f
+#define DRM_RADEON_CMDBUF 0x10
+#define DRM_RADEON_GETPARAM 0x11
+#define DRM_RADEON_FLIP 0x12
+#define DRM_RADEON_ALLOC 0x13
+#define DRM_RADEON_FREE 0x14
+#define DRM_RADEON_INIT_HEAP 0x15
+#define DRM_RADEON_IRQ_EMIT 0x16
+#define DRM_RADEON_IRQ_WAIT 0x17
+#define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39
+
+
+#define RADEON_FRONT 0x1
+#define RADEON_BACK 0x2
+#define RADEON_DEPTH 0x4
+#define RADEON_STENCIL 0x8
+
+#define RADEON_CLEAR_X1 0
+#define RADEON_CLEAR_Y1 1
+#define RADEON_CLEAR_X2 2
+#define RADEON_CLEAR_Y2 3
+#define RADEON_CLEAR_DEPTH 4
+
+
+typedef struct {
+ enum {
+ DRM_RADEON_INIT_CP = 0x01,
+ DRM_RADEON_CLEANUP_CP = 0x02,
+ DRM_RADEON_INIT_R200_CP = 0x03
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ int cp_mode;
+ int agp_size;
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long ring_rptr_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+} drmRadeonInit;
+
+typedef struct {
+ int flush;
+ int idle;
+} drmRadeonCPStop;
+
+typedef struct {
+ int idx;
+ int start;
+ int end;
+ int discard;
+} drmRadeonIndirect;
+
+typedef union drmRadeonClearR {
+ float f[5];
+ unsigned int ui[5];
+} drmRadeonClearRect;
+
+typedef struct drmRadeonClearT {
+ unsigned int flags;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+ unsigned int depth_mask; /* misnamed field: should be stencil */
+ drmRadeonClearRect *depth_boxes;
+} drmRadeonClearType;
+
+typedef struct drmRadeonFullscreenT {
+ enum {
+ RADEON_INIT_FULLSCREEN = 0x01,
+ RADEON_CLEANUP_FULLSCREEN = 0x02
+ } func;
+} drmRadeonFullscreenType;
+
+typedef struct {
+ unsigned int *mask;
+} drmRadeonStipple;
+
+typedef struct {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ const void *data;
+} drmRadeonTexImage;
+
+typedef struct {
+ int offset;
+ int pitch;
+ int format;
+ int width; /* Texture image coordinates */
+ int height;
+ drmRadeonTexImage *image;
+} drmRadeonTexture;
+
+
+#define RADEON_MAX_TEXTURE_UNITS 3
+
+/* Layout matches drm_radeon_state_t in linux drm_radeon.h.
+ */
+typedef struct {
+ struct {
+ unsigned int pp_misc; /* 0x1c14 */
+ unsigned int pp_fog_color;
+ unsigned int re_solid_color;
+ unsigned int rb3d_blendcntl;
+ unsigned int rb3d_depthoffset;
+ unsigned int rb3d_depthpitch;
+ unsigned int rb3d_zstencilcntl;
+ unsigned int pp_cntl; /* 0x1c38 */
+ unsigned int rb3d_cntl;
+ unsigned int rb3d_coloroffset;
+ unsigned int re_width_height;
+ unsigned int rb3d_colorpitch;
+ } context;
+ struct {
+ unsigned int se_cntl;
+ } setup1;
+ struct {
+ unsigned int se_coord_fmt; /* 0x1c50 */
+ } vertex;
+ struct {
+ unsigned int re_line_pattern; /* 0x1cd0 */
+ unsigned int re_line_state;
+ unsigned int se_line_width; /* 0x1db8 */
+ } line;
+ struct {
+ unsigned int pp_lum_matrix; /* 0x1d00 */
+ unsigned int pp_rot_matrix_0; /* 0x1d58 */
+ unsigned int pp_rot_matrix_1;
+ } bumpmap;
+ struct {
+ unsigned int rb3d_stencilrefmask; /* 0x1d7c */
+ unsigned int rb3d_ropcntl;
+ unsigned int rb3d_planemask;
+ } mask;
+ struct {
+ unsigned int se_vport_xscale; /* 0x1d98 */
+ unsigned int se_vport_xoffset;
+ unsigned int se_vport_yscale;
+ unsigned int se_vport_yoffset;
+ unsigned int se_vport_zscale;
+ unsigned int se_vport_zoffset;
+ } viewport;
+ struct {
+ unsigned int se_cntl_status; /* 0x2140 */
+ } setup2;
+ struct {
+ unsigned int re_top_left; /*ignored*/ /* 0x26c0 */
+ unsigned int re_misc;
+ } misc;
+ struct {
+ unsigned int pp_txfilter;
+ unsigned int pp_txformat;
+ unsigned int pp_txoffset;
+ unsigned int pp_txcblend;
+ unsigned int pp_txablend;
+ unsigned int pp_tfactor;
+ unsigned int pp_border_color;
+ } texture[RADEON_MAX_TEXTURE_UNITS];
+ struct {
+ unsigned int se_zbias_factor;
+ unsigned int se_zbias_constant;
+ } zbias;
+ unsigned int dirty;
+} drmRadeonState;
+
+/* 1.1 vertex ioctl. Used in compatibility modes.
+ */
+typedef struct {
+ int prim;
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
+} drmRadeonVertex;
+
+typedef struct {
+ unsigned int start;
+ unsigned int finish;
+ unsigned int prim:8;
+ unsigned int stateidx:8;
+ unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
+ unsigned int vc_format;
+} drmRadeonPrim;
+
+typedef struct {
+ int idx; /* Index of vertex buffer */
+ int discard; /* Client finished with buffer? */
+ int nr_states;
+ drmRadeonState *state;
+ int nr_prims;
+ drmRadeonPrim *prim;
+} drmRadeonVertex2;
+
+#define RADEON_MAX_STATES 16
+#define RADEON_MAX_PRIMS 64
+
+/* Command buffer. Replace with true dma stream?
+ */
+typedef struct {
+ int bufsz;
+ char *buf;
+ int nbox;
+ drmClipRect *boxes;
+} drmRadeonCmdBuffer;
+
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command. Comments relate new packets to old
+ * state bits and the packet size:
+ */
+#define RADEON_EMIT_PP_MISC 0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/6 */
+#define R200_EMIT_TFACTOR_0 30 /* tf/6 */
+#define R200_EMIT_VTX_FMT_0 31 /* vtx/4 */
+#define R200_EMIT_VAP_CTL 32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
+#define RADEON_MAX_STATE_PACKETS 61
+
+
+/* Commands understood by cmd_buffer ioctl. More can be added but
+ * obviously these can't be removed or changed:
+ */
+#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS 2 /* emit scalar data */
+#define RADEON_CMD_VECTORS 3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3 5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2 7 /* R200 stopgap */
+#define RADEON_CMD_WAIT 8 /* synchronization */
+
+typedef union {
+ int i;
+ struct {
+ unsigned char cmd_type, pad0, pad1, pad2;
+ } header;
+ struct {
+ unsigned char cmd_type, packet_id, pad0, pad1;
+ } packet;
+ struct {
+ unsigned char cmd_type, offset, stride, count;
+ } scalars;
+ struct {
+ unsigned char cmd_type, offset, stride, count;
+ } vectors;
+ struct {
+ unsigned char cmd_type, buf_idx, pad0, pad1;
+ } dma;
+ struct {
+ unsigned char cmd_type, flags, pad0, pad1;
+ } wait;
+} drmRadeonCmdHeader;
+
+
+#define RADEON_WAIT_2D 0x1
+#define RADEON_WAIT_3D 0x2
+
+
+typedef struct drm_radeon_getparam {
+ int param;
+ int *value;
+} drmRadeonGetParam;
+
+#define RADEON_PARAM_AGP_BUFFER_OFFSET 1
+#define RADEON_PARAM_LAST_FRAME 2
+#define RADEON_PARAM_LAST_DISPATCH 3
+#define RADEON_PARAM_LAST_CLEAR 4
+#define RADEON_PARAM_IRQ_NR 5
+#define RADEON_PARAM_AGP_BASE 6
+
+
+#define RADEON_MEM_REGION_AGP 1
+#define RADEON_MEM_REGION_FB 2
+
+typedef struct drm_radeon_mem_alloc {
+ int region;
+ int alignment;
+ int size;
+ int *region_offset; /* offset from start of fb or agp */
+} drmRadeonMemAlloc;
+
+typedef struct drm_radeon_mem_free {
+ int region;
+ int region_offset;
+} drmRadeonMemFree;
+
+typedef struct drm_radeon_mem_init_heap {
+ int region;
+ int size;
+ int start;
+} drmRadeonMemInitHeap;
+
+/* 1.6: Userspace can request & wait on irq's:
+ */
+typedef struct drm_radeon_irq_emit {
+ int *irq_seq;
+} drmRadeonIrqEmit;
+
+typedef struct drm_radeon_irq_wait {
+ int irq_seq;
+} drmRadeonIrqWait;
+
+
+#endif
diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c
new file mode 100644
index 0000000..868703d
--- /dev/null
+++ b/src/radeon_cursor.c
@@ -0,0 +1,486 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.23 2003/02/24 20:34:55 tsi Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+ /* Driver data structures */
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_reg.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+/* Mono ARGB cursor colours (premultiplied). */
+static CARD32 mono_cursor_color[] = {
+ 0x00000000, /* White, fully transparent. */
+ 0x00000000, /* Black, fully transparent. */
+ 0xffffffff, /* White, fully opaque. */
+ 0xff000000, /* Black, fully opaque. */
+};
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+/*
+ * The cursor bits are always 32bpp. On MSBFirst busses,
+ * configure byte swapping to swap 32 bit units when writing
+ * the cursor image. Byte swapping must always be returned
+ * to its previous value before returning.
+ */
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+
+#define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO;
+#define CURSOR_SWAPPING_DECL CARD32 __surface_cntl;
+#define CURSOR_SWAPPING_START() \
+ OUTREG(RADEON_SURFACE_CNTL, \
+ ((__surface_cntl = INREG(RADEON_SURFACE_CNTL)) | \
+ RADEON_NONSURF_AP0_SWP_32BPP) & \
+ ~RADEON_NONSURF_AP0_SWP_16BPP)
+#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, __surface_cntl))
+
+#else
+
+#define CURSOR_SWAPPING_DECL_MMIO
+#define CURSOR_SWAPPING_DECL
+#define CURSOR_SWAPPING_START()
+#define CURSOR_SWAPPING_END()
+
+#endif
+
+/* Set cursor foreground and background colors */
+static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_start);
+ int pixel, i;
+ CURSOR_SWAPPING_DECL_MMIO
+ CURSOR_SWAPPING_DECL
+
+#ifdef ARGB_CURSOR
+ /* Don't recolour cursors set with SetCursorARGB. */
+ if (info->cursor_argb)
+ return;
+#endif
+
+ fg |= 0xff000000;
+ bg |= 0xff000000;
+
+ /* Don't recolour the image if we don't have to. */
+ if (fg == info->cursor_fg && bg == info->cursor_bg)
+ return;
+
+ CURSOR_SWAPPING_START();
+
+ /* Note: We assume that the pixels are either fully opaque or fully
+ * transparent, so we won't premultiply them, and we can just
+ * check for non-zero pixel values; those are either fg or bg
+ */
+ for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++)
+ if ((pixel = *pixels))
+ *pixels = (pixel == info->cursor_fg) ? fg : bg;
+
+ CURSOR_SWAPPING_END();
+ info->cursor_fg = fg;
+ info->cursor_bg = bg;
+}
+
+
+/* Set cursor position to (x,y) with offset into cursor bitmap at
+ * (xorigin,yorigin)
+ */
+static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ xf86CursorInfoPtr cursor = info->cursor;
+ int xorigin = 0;
+ int yorigin = 0;
+ int total_y = pScrn->frameY1 - pScrn->frameY0;
+ int X2 = pScrn->frameX0 + x;
+ int Y2 = pScrn->frameY0 + y;
+ int stride = 256;
+
+ if (x < 0) xorigin = -x+1;
+ if (y < 0) yorigin = -y+1;
+ if (y > total_y) y = total_y;
+ if (info->Flags & V_DBLSCAN) y *= 2;
+ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
+ if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
+
+ if (info->Clone) {
+ int X0 = 0;
+ int Y0 = 0;
+
+ if ((info->CurCloneMode->VDisplay == pScrn->currentMode->VDisplay) &&
+ (info->CurCloneMode->HDisplay == pScrn->currentMode->HDisplay)) {
+ Y2 = y;
+ X2 = x;
+ X0 = pScrn->frameX0;
+ Y0 = pScrn->frameY0;
+ } else {
+ if (y < 0)
+ Y2 = pScrn->frameY0;
+
+ if (x < 0)
+ X2 = pScrn->frameX0;
+
+ if (Y2 >= info->CurCloneMode->VDisplay + info->CloneFrameY0) {
+ Y0 = Y2 - info->CurCloneMode->VDisplay;
+ Y2 = info->CurCloneMode->VDisplay - 1;
+ } else if (Y2 < info->CloneFrameY0) {
+ Y0 = Y2;
+ Y2 = 0;
+ } else {
+ Y2 -= info->CloneFrameY0;
+ Y0 = info->CloneFrameY0;
+ }
+
+ if (X2 >= info->CurCloneMode->HDisplay + info->CloneFrameX0) {
+ X0 = X2 - info->CurCloneMode->HDisplay;
+ X2 = info->CurCloneMode->HDisplay - 1;
+ } else if (X2 < info->CloneFrameX0) {
+ X0 = X2;
+ X2 = 0;
+ } else {
+ X2 -= info->CloneFrameX0;
+ X0 = info->CloneFrameX0;
+ }
+
+ if (info->CurCloneMode->Flags & V_DBLSCAN)
+ Y2 *= 2;
+ }
+
+ if ((X0 >= 0 || Y0 >= 0) &&
+ ((info->CloneFrameX0 != X0) || (info->CloneFrameY0 != Y0))) {
+ RADEONDoAdjustFrame(pScrn, X0, Y0, TRUE);
+ info->CloneFrameX0 = X0;
+ info->CloneFrameY0 = Y0;
+ }
+ }
+
+ if (!info->IsSecondary) {
+ OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK
+ | (xorigin << 16)
+ | yorigin));
+ OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
+ | ((xorigin ? 0 : x) << 16)
+ | (yorigin ? 0 : y)));
+ OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride);
+ } else {
+ OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK
+ | (xorigin << 16)
+ | yorigin));
+ OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
+ | ((xorigin ? 0 : x) << 16)
+ | (yorigin ? 0 : y)));
+ OUTREG(RADEON_CUR2_OFFSET,
+ info->cursor_start + pScrn->fbOffset + yorigin * stride);
+ }
+
+ if (info->Clone) {
+ xorigin = 0;
+ yorigin = 0;
+ if (X2 < 0) xorigin = -X2 + 1;
+ if (Y2 < 0) yorigin = -Y2 + 1;
+ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
+ if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
+
+ OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK
+ | (xorigin << 16)
+ | yorigin));
+ OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK
+ | ((xorigin ? 0 : X2) << 16)
+ | (yorigin ? 0 : Y2)));
+ OUTREG(RADEON_CUR2_OFFSET,
+ info->cursor_start + pScrn->fbOffset + yorigin * stride);
+ }
+}
+
+/* Copy cursor image from `image' to video memory. RADEONSetCursorPosition
+ * will be called after this, so we can ignore xorigin and yorigin.
+ */
+static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD8 *s = (CARD8 *)(pointer)image;
+ CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start);
+ CARD32 save1 = 0;
+ CARD32 save2 = 0;
+ CARD8 chunk;
+ CARD32 i, j;
+ CURSOR_SWAPPING_DECL
+
+ if (!info->IsSecondary) {
+ save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
+ save1 |= (CARD32) (2 << 20);
+ OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN);
+ }
+
+ if (info->IsSecondary || info->Clone) {
+ save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20);
+ save2 |= (CARD32) (2 << 20);
+ OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN);
+ }
+
+#ifdef ARGB_CURSOR
+ info->cursor_argb = FALSE;
+#endif
+
+ /*
+ * Convert the bitmap to ARGB32.
+ *
+ * HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 always places
+ * source in the low bit of the pair and mask in the high bit,
+ * and MSBFirst machines set HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+ * (which actually bit swaps the image) to make the bits LSBFirst
+ */
+ CURSOR_SWAPPING_START();
+#define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2)
+ for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK; i++) {
+ chunk = *s++;
+ for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2)
+ *d++ = mono_cursor_color[chunk & 3];
+ }
+ CURSOR_SWAPPING_END();
+
+ info->cursor_bg = mono_cursor_color[2];
+ info->cursor_fg = mono_cursor_color[3];
+
+ if (!info->IsSecondary)
+ OUTREG(RADEON_CRTC_GEN_CNTL, save1);
+
+ if (info->IsSecondary || info->Clone)
+ OUTREG(RADEON_CRTC2_GEN_CNTL, save2);
+
+}
+
+/* Hide hardware cursor. */
+static void RADEONHideCursor(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (info->IsSecondary || info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN);
+
+ if (!info->IsSecondary)
+ OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN);
+}
+
+/* Show hardware cursor. */
+static void RADEONShowCursor(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (info->IsSecondary || info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN,
+ ~RADEON_CRTC2_CUR_EN);
+
+ if (!info->IsSecondary)
+ OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN,
+ ~RADEON_CRTC_CUR_EN);
+}
+
+/* Determine if hardware cursor is in use. */
+static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ return info->cursor_start ? TRUE : FALSE;
+}
+
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->cursor_start &&
+ pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH)
+ return TRUE;
+ return FALSE;
+}
+
+static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start);
+ int x, y, w, h;
+ CARD32 save1 = 0;
+ CARD32 save2 = 0;
+ CARD32 *image = pCurs->bits->argb;
+ CARD32 *i;
+ CURSOR_SWAPPING_DECL
+
+ if (!image)
+ return; /* XXX can't happen */
+
+ if (!info->IsSecondary) {
+ save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
+ save1 |= (CARD32) (2 << 20);
+ OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN);
+ }
+
+ if (info->IsSecondary || info->Clone) {
+ save2 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
+ save2 |= (CARD32) (2 << 20);
+ OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN);
+ }
+
+#ifdef ARGB_CURSOR
+ info->cursor_argb = TRUE;
+#endif
+
+ CURSOR_SWAPPING_START();
+
+ w = pCurs->bits->width;
+ if (w > CURSOR_WIDTH)
+ w = CURSOR_WIDTH;
+ h = pCurs->bits->height;
+ if (h > CURSOR_HEIGHT)
+ h = CURSOR_HEIGHT;
+ for (y = 0; y < h; y++)
+ {
+ i = image;
+ image += pCurs->bits->width;
+ for (x = 0; x < w; x++)
+ *d++ = *i++;
+ /* pad to the right with transparent */
+ for (; x < CURSOR_WIDTH; x++)
+ *d++ = 0;
+ }
+ /* pad below with transparent */
+ for (; y < CURSOR_HEIGHT; y++)
+ for (x = 0; x < CURSOR_WIDTH; x++)
+ *d++ = 0;
+
+ CURSOR_SWAPPING_END ();
+
+ if (!info->IsSecondary)
+ OUTREG(RADEON_CRTC_GEN_CNTL, save1);
+
+ if (info->IsSecondary || info->Clone)
+ OUTREG(RADEON_CRTC2_GEN_CNTL, save2);
+
+}
+
+#endif
+
+
+/* Initialize hardware cursor support. */
+Bool RADEONCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86CursorInfoPtr cursor;
+ FBAreaPtr fbarea;
+ int width;
+ int width_bytes;
+ int height;
+ int size_bytes;
+
+ if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
+
+ cursor->MaxWidth = CURSOR_WIDTH;
+ cursor->MaxHeight = CURSOR_HEIGHT;
+ cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
+ | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* this is a lie --
+ * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+ * actually inverts the bit order, so
+ * this switches to LSBFIRST
+ */
+ | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+#endif
+ | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1);
+
+ cursor->SetCursorColors = RADEONSetCursorColors;
+ cursor->SetCursorPosition = RADEONSetCursorPosition;
+ cursor->LoadCursorImage = RADEONLoadCursorImage;
+ cursor->HideCursor = RADEONHideCursor;
+ cursor->ShowCursor = RADEONShowCursor;
+ cursor->UseHWCursor = RADEONUseHWCursor;
+
+#ifdef ARGB_CURSOR
+ cursor->UseHWCursorARGB = RADEONUseHWCursorARGB;
+ cursor->LoadCursorARGB = RADEONLoadCursorARGB;
+#endif
+ size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT;
+ width = pScrn->displayWidth;
+ width_bytes = width * (pScrn->bitsPerPixel / 8);
+ height = (size_bytes + width_bytes - 1) / width_bytes;
+ fbarea = xf86AllocateOffscreenArea(pScreen,
+ width,
+ height,
+ 256,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!fbarea) {
+ info->cursor_start = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Hardware cursor disabled"
+ " due to insufficient offscreen memory\n");
+ } else {
+ info->cursor_start = RADEON_ALIGN((fbarea->box.x1 +
+ fbarea->box.y1 * width) *
+ info->CurrentLayout.pixel_bytes,
+ 256);
+ info->cursor_end = info->cursor_start + size_bytes;
+ }
+
+ RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n",
+ info->cursor_start, info->cursor_end));
+
+ return xf86InitCursor(pScreen, cursor);
+}
diff --git a/src/radeon_dga.c b/src/radeon_dga.c
new file mode 100644
index 0000000..a0fe938
--- /dev/null
+++ b/src/radeon_dga.c
@@ -0,0 +1,397 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dga.c,v 1.11 2002/09/18 18:14:58 martin Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ *
+ * Credits:
+ *
+ * Thanks to Ove Kåven <ovek@transgaming.com> for writing the Rage 128
+ * DGA support. Portions of this file are based on the initialization
+ * code for that driver.
+ *
+ */
+
+ /* Driver data structures */
+#include "radeon.h"
+#include "radeon_probe.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+
+ /* DGA support */
+#include "dgaproc.h"
+
+
+static Bool RADEON_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool RADEON_SetMode(ScrnInfoPtr, DGAModePtr);
+static int RADEON_GetViewport(ScrnInfoPtr);
+static void RADEON_SetViewport(ScrnInfoPtr, int, int, int);
+static void RADEON_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void RADEON_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void RADEON_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+
+
+static DGAModePtr RADEONSetupDGAMode(ScrnInfoPtr pScrn,
+ DGAModePtr modes,
+ int *num,
+ int bitsPerPixel,
+ int depth,
+ Bool pixmap,
+ int secondPitch,
+ unsigned long red,
+ unsigned long green,
+ unsigned long blue,
+ short visualClass)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DGAModePtr newmodes = NULL;
+ DGAModePtr currentMode;
+ DisplayModePtr pMode;
+ DisplayModePtr firstMode;
+ unsigned int size;
+ int pitch;
+ int Bpp = bitsPerPixel >> 3;
+
+SECOND_PASS:
+
+ pMode = firstMode = pScrn->modes;
+
+ while (1) {
+ pitch = pScrn->displayWidth;
+ size = pitch * Bpp * pMode->VDisplay;
+
+ if ((!secondPitch || (pitch != secondPitch)) &&
+ (size <= info->FbMapSize)) {
+
+ if (secondPitch)
+ pitch = secondPitch;
+
+ if (!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec))))
+ break;
+
+ modes = newmodes;
+ currentMode = modes + *num;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS;
+
+ if (pixmap)
+ currentMode->flags |= DGA_PIXMAP_AVAILABLE;
+
+ if (info->accel) {
+ if (info->accel->SetupForSolidFill &&
+ info->accel->SubsequentSolidFillRect)
+ currentMode->flags |= DGA_FILL_RECT;
+ if (info->accel->SetupForScreenToScreenCopy &&
+ info->accel->SubsequentScreenToScreenCopy)
+ currentMode->flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;
+ if (currentMode->flags &
+ (DGA_PIXMAP_AVAILABLE | DGA_FILL_RECT |
+ DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS))
+ currentMode->flags &= ~DGA_CONCURRENT_ACCESS;
+ }
+ if (pMode->Flags & V_DBLSCAN)
+ currentMode->flags |= DGA_DOUBLESCAN;
+ if (pMode->Flags & V_INTERLACE)
+ currentMode->flags |= DGA_INTERLACED;
+
+ currentMode->byteOrder = pScrn->imageByteOrder;
+ currentMode->depth = depth;
+ currentMode->bitsPerPixel = bitsPerPixel;
+ currentMode->red_mask = red;
+ currentMode->green_mask = green;
+ currentMode->blue_mask = blue;
+ currentMode->visualClass = visualClass;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ currentMode->xViewportStep = 8;
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ currentMode->offset = 0;
+ currentMode->address = (unsigned char*)info->LinearAddr;
+ currentMode->bytesPerScanline = pitch * Bpp;
+ currentMode->imageWidth = pitch;
+ currentMode->imageHeight = (info->FbMapSize
+ / currentMode->bytesPerScanline);
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = (currentMode->imageWidth
+ - currentMode->viewportWidth);
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = (currentMode->imageHeight
+ - currentMode->viewportHeight);
+ (*num)++;
+ }
+
+ pMode = pMode->next;
+ if (pMode == firstMode)
+ break;
+ }
+
+ if (secondPitch) {
+ secondPitch = 0;
+ goto SECOND_PASS;
+ }
+
+ return modes;
+}
+
+Bool RADEONDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DGAModePtr modes = NULL;
+ int num = 0;
+
+ /* 8 */
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 8, 8,
+ (pScrn->bitsPerPixel == 8),
+ ((pScrn->bitsPerPixel != 8)
+ ? 0 : pScrn->displayWidth),
+ 0, 0, 0, PseudoColor);
+
+ /* 15 */
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel == 16),
+ ((pScrn->depth != 15)
+ ? 0 : pScrn->displayWidth),
+ 0x7c00, 0x03e0, 0x001f, TrueColor);
+
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel == 16),
+ ((pScrn->depth != 15)
+ ? 0 : pScrn->displayWidth),
+ 0x7c00, 0x03e0, 0x001f, DirectColor);
+
+ /* 16 */
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel == 16),
+ ((pScrn->depth != 16)
+ ? 0 : pScrn->displayWidth),
+ 0xf800, 0x07e0, 0x001f, TrueColor);
+
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel == 16),
+ ((pScrn->depth != 16)
+ ? 0 : pScrn->displayWidth),
+ 0xf800, 0x07e0, 0x001f, DirectColor);
+
+ /* 32 */
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel == 32),
+ ((pScrn->bitsPerPixel != 32)
+ ? 0 : pScrn->displayWidth),
+ 0xff0000, 0x00ff00, 0x0000ff, TrueColor);
+
+ modes = RADEONSetupDGAMode(pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel == 32),
+ ((pScrn->bitsPerPixel != 32)
+ ? 0 : pScrn->displayWidth),
+ 0xff0000, 0x00ff00, 0x0000ff, DirectColor);
+
+ info->numDGAModes = num;
+ info->DGAModes = modes;
+
+ info->DGAFuncs.OpenFramebuffer = RADEON_OpenFramebuffer;
+ info->DGAFuncs.CloseFramebuffer = NULL;
+ info->DGAFuncs.SetMode = RADEON_SetMode;
+ info->DGAFuncs.SetViewport = RADEON_SetViewport;
+ info->DGAFuncs.GetViewport = RADEON_GetViewport;
+
+ info->DGAFuncs.Sync = NULL;
+ info->DGAFuncs.FillRect = NULL;
+ info->DGAFuncs.BlitRect = NULL;
+ info->DGAFuncs.BlitTransRect = NULL;
+
+ if (info->accel) {
+ info->DGAFuncs.Sync = info->accel->Sync;
+ if (info->accel->SetupForSolidFill &&
+ info->accel->SubsequentSolidFillRect)
+ info->DGAFuncs.FillRect = RADEON_FillRect;
+ if (info->accel->SetupForScreenToScreenCopy &&
+ info->accel->SubsequentScreenToScreenCopy) {
+ info->DGAFuncs.BlitRect = RADEON_BlitRect;
+ info->DGAFuncs.BlitTransRect = RADEON_BlitTransRect;
+ }
+ }
+
+ return DGAInit(pScreen, &info->DGAFuncs, modes, num);
+}
+
+static Bool RADEON_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ static RADEONFBLayout SavedLayouts[MAXSCREENS];
+ int indx = pScrn->pScreen->myNum;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!pMode) { /* restore the original mode */
+ /* put the ScreenParameters back */
+ if (info->DGAactive)
+ memcpy(&info->CurrentLayout, &SavedLayouts[indx],
+ sizeof(RADEONFBLayout));
+
+ pScrn->currentMode = info->CurrentLayout.mode;
+
+ RADEONSwitchMode(indx, pScrn->currentMode, 0);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_STOP(pScrn, info);
+ }
+#endif
+ if (info->accelOn)
+ RADEONEngineInit(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_START(pScrn, info);
+ }
+#endif
+ RADEONAdjustFrame(indx, 0, 0, 0);
+ info->DGAactive = FALSE;
+ } else {
+ if (!info->DGAactive) { /* save the old parameters */
+ memcpy(&SavedLayouts[indx], &info->CurrentLayout,
+ sizeof(RADEONFBLayout));
+ info->DGAactive = TRUE;
+ }
+
+ info->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
+ info->CurrentLayout.depth = pMode->depth;
+ info->CurrentLayout.displayWidth = (pMode->bytesPerScanline /
+ (pMode->bitsPerPixel >> 3));
+ info->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8;
+ info->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16
+ ? pMode->bitsPerPixel
+ : pMode->depth);
+ /* RADEONModeInit() will set the mode field */
+
+ RADEONSwitchMode(indx, pMode->mode, 0);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_STOP(pScrn, info);
+ }
+#endif
+ if (info->accelOn)
+ RADEONEngineInit(pScrn);
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_START(pScrn, info);
+ }
+#endif
+ }
+
+ return TRUE;
+}
+
+static int RADEON_GetViewport(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ return info->DGAViewportStatus;
+}
+
+static void RADEON_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ RADEONAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ info->DGAViewportStatus = 0; /* FIXME */
+}
+
+static void RADEON_FillRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ (*info->accel->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0));
+ (*info->accel->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+static void RADEON_BlitRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
+ GXcopy, (CARD32)(~0), -1);
+ (*info->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+static void RADEON_BlitTransRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long color)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ info->XAAForceTransBlit = TRUE;
+
+ (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
+ GXcopy, (CARD32)(~0), color);
+
+ info->XAAForceTransBlit = FALSE;
+
+ (*info->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+
+ if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
+ SET_SYNC_FLAG(info->accel);
+}
+
+static Bool RADEON_OpenFramebuffer(ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size, int *offset, int *flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)info->LinearAddr;
+ *size = info->FbMapSize;
+ *offset = 0;
+ *flags = 0; /* DGA_NEED_ROOT; -- don't need root, just /dev/mem access */
+
+ return TRUE;
+}
diff --git a/src/radeon_dri.c b/src/radeon_dri.c
new file mode 100644
index 0000000..96787f1
--- /dev/null
+++ b/src/radeon_dri.c
@@ -0,0 +1,1861 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.32.2.1 2003/05/06 23:21:38 daenzer Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario,
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+
+ /* Driver data structures */
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_dri.h"
+#include "radeon_reg.h"
+#include "radeon_version.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+#include "windowstr.h"
+#include "xf86PciInfo.h"
+
+
+#include "shadowfb.h"
+ /* GLX/DRI/DRM definitions */
+#define _XF86DRI_SERVER_
+#include "GL/glxtokens.h"
+#include "sarea.h"
+#include "radeon_sarea.h"
+
+/* HACK - for now, put this here... */
+/* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
+#if defined(__alpha__)
+# define DRM_PAGE_SIZE 8192
+#elif defined(__ia64__)
+# define DRM_PAGE_SIZE getpagesize()
+#else
+# define DRM_PAGE_SIZE 4096
+#endif
+
+
+static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen);
+static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen);
+static void RADEONDRITransitionTo2d(ScreenPtr pScreen);
+static void RADEONDRITransitionTo3d(ScreenPtr pScreen);
+static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen);
+
+static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+/* Initialize the visual configs that are supported by the hardware.
+ * These are combined with the visual configs that the indirect
+ * rendering core supports, and the intersection is exported to the
+ * client.
+ */
+static Bool RADEONInitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ RADEONConfigPrivPtr pRADEONConfigs = 0;
+ RADEONConfigPrivPtr *pRADEONConfigPtrs = 0;
+ int i, accum, stencil, db, use_db;
+
+ use_db = !info->noBackBuffer ? 1 : 0;
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8: /* 8bpp mode is not support */
+ case 15: /* FIXME */
+ case 24: /* FIXME */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONInitVisualConfigs failed "
+ "(depth %d not supported). "
+ "Disabling DRI.\n", info->CurrentLayout.pixel_code);
+ return FALSE;
+
+#define RADEON_USE_ACCUM 1
+#define RADEON_USE_STENCIL 1
+
+ case 16:
+ numConfigs = 1;
+ if (RADEON_USE_ACCUM) numConfigs *= 2;
+ if (RADEON_USE_STENCIL) numConfigs *= 2;
+ if (use_db) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pRADEONConfigs
+ = (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pRADEONConfigPtrs
+ = (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pRADEONConfigs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= use_db; db++) {
+ for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) {
+ for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) {
+ pRADEONConfigPtrs[i] = &pRADEONConfigs[i];
+
+ pConfigs[i].vid = (VisualID)(-1);
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0x00000000;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ pConfigs[i].depthSize = 16;
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum) {
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ numConfigs = 1;
+ if (RADEON_USE_ACCUM) numConfigs *= 2;
+ if (RADEON_USE_STENCIL) numConfigs *= 2;
+ if (use_db) numConfigs *= 2;
+
+ if (!(pConfigs
+ = (__GLXvisualConfig *)xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pRADEONConfigs
+ = (RADEONConfigPrivPtr)xcalloc(sizeof(RADEONConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pRADEONConfigPtrs
+ = (RADEONConfigPrivPtr *)xcalloc(sizeof(RADEONConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pRADEONConfigs);
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= use_db; db++) {
+ for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) {
+ for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) {
+ pRADEONConfigPtrs[i] = &pRADEONConfigs[i];
+
+ pConfigs[i].vid = (VisualID)(-1);
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].alphaSize = 8;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+ pConfigs[i].alphaMask = 0xFF000000;
+ if (accum) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 16;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 32;
+ if (stencil) {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum) {
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+ }
+
+ info->numVisualConfigs = numConfigs;
+ info->pVisualConfigs = pConfigs;
+ info->pVisualConfigsPriv = pRADEONConfigs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pRADEONConfigPtrs);
+ return TRUE;
+}
+
+/* Create the Radeon-specific context information */
+static Bool RADEONCreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+#ifdef PER_CONTEXT_SAREA
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONDRIContextPtr ctx_info;
+
+ ctx_info = (RADEONDRIContextPtr)contextStore;
+ if (!ctx_info) return FALSE;
+
+ if (drmAddMap(info->drmFD, 0,
+ info->perctx_sarea_size,
+ DRM_SHM,
+ DRM_REMOVABLE,
+ &ctx_info->sarea_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] could not create private sarea for ctx id (%d)\n",
+ (int)hwContext);
+ return FALSE;
+ }
+
+ if (drmAddContextPrivateMapping(info->drmFD, hwContext,
+ ctx_info->sarea_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] could not associate private sarea to ctx id (%d)\n",
+ (int)hwContext);
+ drmRmMap(info->drmFD, ctx_info->sarea_handle);
+ return FALSE;
+ }
+
+ ctx_info->ctx_id = hwContext;
+#endif
+ return TRUE;
+}
+
+/* Destroy the Radeon-specific context information */
+static void RADEONDestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+#ifdef PER_CONTEXT_SAREA
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONDRIContextPtr ctx_info;
+
+ ctx_info = (RADEONDRIContextPtr)contextStore;
+ if (!ctx_info) return;
+
+ if (drmRmMap(info->drmFD, ctx_info->sarea_handle) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] could not remove private sarea for ctx id (%d)\n",
+ (int)hwContext);
+ }
+#endif
+}
+
+/* Called when the X server is woken up to allow the last client's
+ * context to be saved and the X server's context to be loaded. This is
+ * not necessary for the Radeon since the client detects when it's
+ * context is not currently loaded and then load's it itself. Since the
+ * registers to start and stop the CP are privileged, only the X server
+ * can start/stop the engine.
+ */
+static void RADEONEnterServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->accel) info->accel->NeedToSync = TRUE;
+}
+
+/* Called when the X server goes to sleep to allow the X server's
+ * context to be saved and the last client's context to be loaded. This
+ * is not necessary for the Radeon since the client detects when it's
+ * context is not currently loaded and then load's it itself. Since the
+ * registers to start and stop the CP are privileged, only the X server
+ * can start/stop the engine.
+ */
+static void RADEONLeaveServer(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RING_LOCALS;
+
+ /* The CP is always running, but if we've generated any CP commands
+ * we must flush them to the kernel module now.
+ */
+ if (info->CPInUse) {
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+ RADEONCPReleaseIndirect(pScrn);
+
+ info->CPInUse = FALSE;
+ }
+}
+
+/* Contexts can be swapped by the X server if necessary. This callback
+ * is currently only used to perform any functions necessary when
+ * entering or leaving the X server, and in the future might not be
+ * necessary.
+ */
+static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType,
+ void *oldContext,
+ DRIContextType newContextType,
+ void *newContext)
+{
+ if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
+ RADEONEnterServer(pScreen);
+ }
+
+ if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
+ (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
+ RADEONLeaveServer(pScreen);
+ }
+}
+
+/* The Radeon has depth tiling on all the time, so we have to convert
+ * the x,y coordinates into the memory bus address (mba) in the same
+ * manner as the engine. In each case, the linear block address (ba)
+ * is calculated, and then wired with x and y to produce the final
+ * memory address.
+ */
+static CARD32 radeon_mba_z16(RADEONInfoPtr info, int x, int y)
+{
+ CARD32 pitch = info->frontPitch;
+ CARD32 address = 0; /* a[0] = 0 */
+ CARD32 ba;
+
+ ba = (y / 16) * (pitch / 32) + (x / 32);
+
+ address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
+ address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
+ address |= (x & 0x8) << 4; /* a[7] = x[3] */
+ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
+ address |= (y & 0x8) << 7; /* a[10] = y[3] */
+ address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
+ address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */
+
+ return address;
+}
+
+static CARD32 radeon_mba_z32(RADEONInfoPtr info, int x, int y)
+{
+ CARD32 pitch = info->frontPitch;
+ CARD32 address = 0; /* a[0..1] = 0 */
+ CARD32 ba;
+
+ ba = (y / 16) * (pitch / 16) + (x / 16);
+
+ address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
+ address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
+ address |=
+ (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
+ address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
+
+ address |= (y & 0x8) << 7; /* a[10] = y[3] */
+ address |=
+ (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
+ address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */
+
+ return address;
+}
+
+/* 16-bit depth buffer functions */
+#define WRITE_DEPTH16(_x, _y, d) \
+ *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) = (d)
+
+#define READ_DEPTH16(d, _x, _y) \
+ (d) = *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y)))
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions */
+#define WRITE_DEPTH32(_x, _y, d) \
+do { \
+ CARD32 tmp = \
+ *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))); \
+ tmp &= 0xff000000; \
+ tmp |= ((d) & 0x00ffffff); \
+ *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) = tmp; \
+} while (0)
+
+#define READ_DEPTH32(d, _x, _y) \
+ d = (*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) \
+ & 0x00ffffff)
+
+/* Screen to screen copy of data in the depth buffer */
+static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn,
+ int xa, int ya,
+ int xb, int yb,
+ int w, int h)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *buf = info->FB + info->depthOffset;
+ int xstart, xend, xdir;
+ int ystart, yend, ydir;
+ int x, y, d;
+
+ if (xa < xb) xdir = -1, xstart = w-1, xend = 0;
+ else xdir = 1, xstart = 0, xend = w-1;
+
+ if (ya < yb) ydir = -1, ystart = h-1, yend = 0;
+ else ydir = 1, ystart = 0, yend = h-1;
+
+ switch (pScrn->bitsPerPixel) {
+ case 16:
+ for (x = xstart; x != xend; x += xdir) {
+ for (y = ystart; y != yend; y += ydir) {
+ READ_DEPTH16(d, xa+x, ya+y);
+ WRITE_DEPTH16(xb+x, yb+y, d);
+ }
+ }
+ break;
+
+ case 32:
+ for (x = xstart; x != xend; x += xdir) {
+ for (y = ystart; y != yend; y += ydir) {
+ READ_DEPTH32(d, xa+x, ya+y);
+ WRITE_DEPTH32(xb+x, yb+y, d);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Initialize the state of the back and depth buffers */
+static void RADEONDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
+{
+ /* NOOP. There's no need for the 2d driver to be clearing buffers
+ * for the 3d client. It knows how to do that on its own.
+ */
+}
+
+/* Copy the back and depth buffers when the X server moves a window.
+ *
+ * This routine is a modified form of XAADoBitBlt with the calls to
+ * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
+ * instead of destination. My origin is upside down so the ydir cases
+ * are reversed.
+ */
+static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 indx)
+{
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ BoxPtr pboxTmp, pboxNext, pboxBase;
+ DDXPointPtr pptTmp;
+ int xdir, ydir;
+
+ int screenwidth = pScrn->virtualX;
+ int screenheight = pScrn->virtualY;
+
+ BoxPtr pbox = REGION_RECTS(prgnSrc);
+ int nbox = REGION_NUM_RECTS(prgnSrc);
+
+ BoxPtr pboxNew1 = NULL;
+ BoxPtr pboxNew2 = NULL;
+ DDXPointPtr pptNew1 = NULL;
+ DDXPointPtr pptNew2 = NULL;
+ DDXPointPtr pptSrc = &ptOldOrg;
+
+ int dx = pParent->drawable.x - ptOldOrg.x;
+ int dy = pParent->drawable.y - ptOldOrg.y;
+
+ /* If the copy will overlap in Y, reverse the order */
+ if (dy > 0) {
+ ydir = -1;
+
+ if (nbox > 1) {
+ /* Keep ordering in each band, reverse order of bands */
+ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
+ if (!pboxNew1) return;
+
+ pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
+ if (!pptNew1) {
+ DEALLOCATE_LOCAL(pboxNew1);
+ return;
+ }
+
+ pboxBase = pboxNext = pbox+nbox-1;
+
+ while (pboxBase >= pbox) {
+ while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
+ pboxNext--;
+
+ pboxTmp = pboxNext+1;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+
+ while (pboxTmp <= pboxBase) {
+ *pboxNew1++ = *pboxTmp++;
+ *pptNew1++ = *pptTmp++;
+ }
+
+ pboxBase = pboxNext;
+ }
+
+ pboxNew1 -= nbox;
+ pbox = pboxNew1;
+ pptNew1 -= nbox;
+ pptSrc = pptNew1;
+ }
+ } else {
+ /* No changes required */
+ ydir = 1;
+ }
+
+ /* If the regions will overlap in X, reverse the order */
+ if (dx > 0) {
+ xdir = -1;
+
+ if (nbox > 1) {
+ /* reverse order of rects in each band */
+ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
+ pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
+
+ if (!pboxNew2 || !pptNew2) {
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+ return;
+ }
+
+ pboxBase = pboxNext = pbox;
+
+ while (pboxBase < pbox+nbox) {
+ while ((pboxNext < pbox+nbox)
+ && (pboxNext->y1 == pboxBase->y1))
+ pboxNext++;
+
+ pboxTmp = pboxNext;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+
+ while (pboxTmp != pboxBase) {
+ *pboxNew2++ = *--pboxTmp;
+ *pptNew2++ = *--pptTmp;
+ }
+
+ pboxBase = pboxNext;
+ }
+
+ pboxNew2 -= nbox;
+ pbox = pboxNew2;
+ pptNew2 -= nbox;
+ pptSrc = pptNew2;
+ }
+ } else {
+ /* No changes are needed */
+ xdir = 1;
+ }
+
+ (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy,
+ (CARD32)(-1), -1);
+
+ for (; nbox-- ; pbox++) {
+ int xa = pbox->x1;
+ int ya = pbox->y1;
+ int destx = xa + dx;
+ int desty = ya + dy;
+ int w = pbox->x2 - xa + 1;
+ int h = pbox->y2 - ya + 1;
+
+ if (destx < 0) xa -= destx, w += destx, destx = 0;
+ if (desty < 0) ya -= desty, h += desty, desty = 0;
+ if (destx + w > screenwidth) w = screenwidth - destx;
+ if (desty + h > screenheight) h = screenheight - desty;
+
+ if (w <= 0) continue;
+ if (h <= 0) continue;
+
+ RADEONSelectBuffer(pScrn, RADEON_BACK);
+ (*info->accel->SubsequentScreenToScreenCopy)(pScrn,
+ xa, ya,
+ destx, desty,
+ w, h);
+
+ if (info->depthMoves) {
+ RADEONSelectBuffer(pScrn, RADEON_DEPTH);
+ RADEONScreenToScreenCopyDepth(pScrn,
+ xa, ya,
+ destx, desty,
+ w, h);
+ }
+ }
+
+ RADEONSelectBuffer(pScrn, RADEON_FRONT);
+
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+
+ info->accel->NeedToSync = TRUE;
+}
+
+/* Initialize the AGP state. Request memory for use in AGP space, and
+ * initialize the Radeon registers to point to that memory.
+ */
+static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+ unsigned long mode;
+ unsigned int vendor, device;
+ unsigned long agpBase;
+ int ret;
+ int s, l;
+
+ if (drmAgpAcquire(info->drmFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
+ return FALSE;
+ }
+
+ /* Workaround for some hardware bugs */
+ if (info->ChipFamily < CHIP_FAMILY_R200)
+ OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000);
+
+ /* Modify the mode if the default mode
+ * is not appropriate for this
+ * particular combination of graphics
+ * card and AGP chipset.
+ */
+
+ mode = drmAgpGetMode(info->drmFD); /* Default mode */
+ vendor = drmAgpVendorId(info->drmFD);
+ device = drmAgpDeviceId(info->drmFD);
+
+ mode &= ~RADEON_AGP_MODE_MASK;
+ switch (info->agpMode) {
+ case 4: mode |= RADEON_AGP_4X_MODE;
+ case 2: mode |= RADEON_AGP_2X_MODE;
+ case 1: default: mode |= RADEON_AGP_1X_MODE;
+ }
+
+ if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE;
+
+ if ((vendor == PCI_VENDOR_AMD) &&
+ (device == PCI_CHIP_AMD761)) {
+ /* The combination of 761 with MOBILITY chips will lockup the
+ * system; however, currently there is no such a product on the
+ * market, so this is not yet a problem.
+ */
+ if ((info->ChipFamily == CHIP_FAMILY_M6) ||
+ (info->ChipFamily == CHIP_FAMILY_M7))
+ return FALSE;
+
+ /* Disable fast write for AMD 761 chipset, since they cause
+ * lockups when enabled.
+ */
+ mode &= ~0x10; /* FIXME: Magic number */
+ }
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ info->PciInfo->vendor,
+ info->PciInfo->chipType);
+
+ if (drmAgpEnable(info->drmFD, mode) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+
+ info->agpOffset = 0;
+
+ if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL,
+ &info->agpMemHandle)) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->agpMemHandle);
+
+ if (drmAgpBind(info->drmFD,
+ info->agpMemHandle, info->agpOffset) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
+ drmAgpFree(info->drmFD, info->agpMemHandle);
+ drmAgpRelease(info->drmFD);
+ return FALSE;
+ }
+
+ /* Initialize the CP ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ /* Reserve the rest for AGP textures */
+ info->agpTexStart = info->bufStart + info->bufMapSize;
+ s = (info->agpSize*1024*1024 - info->agpTexStart);
+ l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
+ if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
+ info->agpTexMapSize = (s >> l) << l;
+ info->log2AGPTexGran = l;
+
+ if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
+ DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+
+ if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring read ptr mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map ring read ptr\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+
+ if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
+ DRM_AGP, 0, &info->bufHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add vertex/indirect buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map vertex/indirect buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+
+ if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize,
+ DRM_AGP, 0, &info->agpTexHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add AGP texture map mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP texture map handle = 0x%08lx\n",
+ info->agpTexHandle);
+
+ if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize,
+ (drmAddressPtr)&info->agpTex) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map AGP texture map\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP Texture map mapped at 0x%08lx\n",
+ (unsigned long)info->agpTex);
+
+ /* Initialize Radeon's AGP registers */
+
+ agpBase = drmAgpBase(info->drmFD);
+ OUTREG(RADEON_AGP_BASE, agpBase);
+
+ return TRUE;
+}
+
+/* Initialize the PCIGART state. Request memory for use in PCI space,
+ * and initialize the Radeon registers to point to that memory.
+ */
+static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ int ret;
+ int flags;
+
+ info->agpOffset = 0;
+
+ ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024,
+ &info->pciMemHandle);
+ if (ret < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] %d kB allocated with handle 0x%08x\n",
+ info->agpSize*1024, info->pciMemHandle);
+
+ /* Initialize the CCE ring buffer data */
+ info->ringStart = info->agpOffset;
+ info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1;
+
+ info->ringReadOffset = info->ringStart + info->ringMapSize;
+ info->ringReadMapSize = DRM_PAGE_SIZE;
+
+ /* Reserve space for vertex/indirect buffers */
+ info->bufStart = info->ringReadOffset + info->ringReadMapSize;
+ info->bufMapSize = info->bufSize*1024*1024;
+
+ flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
+
+ if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add ring mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] ring handle = 0x%08lx\n", info->ringHandle);
+
+ if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
+ (drmAddressPtr)&info->ring) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring mapped at 0x%08lx\n",
+ (unsigned long)info->ring);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->ring);
+
+ if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
+ DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add ring read ptr mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] ring read ptr handle = 0x%08lx\n",
+ info->ringReadPtrHandle);
+
+ if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+ (drmAddressPtr)&info->ringReadPtr) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not map ring read ptr\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring read ptr mapped at 0x%08lx\n",
+ (unsigned long)info->ringReadPtr);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Ring read ptr contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->ringReadPtr);
+
+ if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
+ DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not add vertex/indirect buffers mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] vertex/indirect buffers handle = 0x%08lx\n",
+ info->bufHandle);
+
+ if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
+ (drmAddressPtr)&info->buf) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[pci] Could not map vertex/indirect buffers\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
+ (unsigned long)info->buf);
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[pci] Vertex/indirect buffers contents 0x%08lx\n",
+ *(unsigned long *)(pointer)info->buf);
+
+ return TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+ * DRI-based clients.
+ */
+static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ /* Map registers */
+ info->registerSize = RADEON_MMIOSIZE;
+ if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
+ DRM_REGISTERS, DRM_READ_ONLY, &info->registerHandle) < 0) {
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] register handle = 0x%08lx\n", info->registerHandle);
+
+ return TRUE;
+}
+
+/* Initialize the kernel data structures */
+static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ int cpp = info->CurrentLayout.pixel_bytes;
+ drmRadeonInit drmInfo;
+
+ memset(&drmInfo, 0, sizeof(drmRadeonInit));
+
+ if ( (info->ChipFamily == CHIP_FAMILY_R200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_M9) )
+ drmInfo.func = DRM_RADEON_INIT_R200_CP;
+ else
+ drmInfo.func = DRM_RADEON_INIT_CP;
+
+ drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ drmInfo.is_pci = info->IsPCI;
+ drmInfo.cp_mode = info->CPMode;
+ drmInfo.agp_size = info->agpSize*1024*1024;
+ drmInfo.ring_size = info->ringSize*1024*1024;
+ drmInfo.usec_timeout = info->CPusecTimeout;
+
+ drmInfo.fb_bpp = info->CurrentLayout.pixel_code;
+ drmInfo.depth_bpp = info->CurrentLayout.pixel_code;
+
+ drmInfo.front_offset = info->frontOffset;
+ drmInfo.front_pitch = info->frontPitch * cpp;
+ drmInfo.back_offset = info->backOffset;
+ drmInfo.back_pitch = info->backPitch * cpp;
+ drmInfo.depth_offset = info->depthOffset;
+ drmInfo.depth_pitch = info->depthPitch * cpp;
+
+ drmInfo.fb_offset = info->fbHandle;
+ drmInfo.mmio_offset = info->registerHandle;
+ drmInfo.ring_offset = info->ringHandle;
+ drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
+ drmInfo.buffers_offset = info->bufHandle;
+ drmInfo.agp_textures_offset = info->agpTexHandle;
+
+ if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
+ &drmInfo, sizeof(drmRadeonInit)) < 0)
+ return FALSE;
+
+ /* DRM_RADEON_CP_INIT does an engine reset, which resets some engine
+ * registers back to their default values, so we need to restore
+ * those engine register here.
+ */
+ RADEONEngineRestore(pScrn);
+
+ return TRUE;
+}
+
+static void RADEONDRIAgpHeapInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ drmRadeonMemInitHeap drmHeap;
+
+ /* Start up the simple memory manager for agp space */
+ if (info->drmMinor >= 6) {
+ drmHeap.region = RADEON_MEM_REGION_AGP;
+ drmHeap.start = 0;
+ drmHeap.size = info->agpTexMapSize;
+
+ if (drmCommandWrite(info->drmFD, DRM_RADEON_INIT_HEAP,
+ &drmHeap, sizeof(drmHeap))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to initialized agp heap manager\n");
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Initialized kernel agp heap manager, %d\n",
+ info->agpTexMapSize);
+ }
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Kernel module too old (1.%d) for agp heap manager\n",
+ info->drmMinor);
+ }
+}
+
+/* Add a map for the vertex buffers that will be accessed by any
+ * DRI-based clients.
+ */
+static Bool RADEONDRIBufInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ /* Initialize vertex buffers */
+ if (info->IsPCI) {
+ info->bufNumBufs = drmAddBufs(info->drmFD,
+ info->bufMapSize / RADEON_BUFFER_SIZE,
+ RADEON_BUFFER_SIZE,
+ DRM_SG_BUFFER,
+ info->bufStart);
+ } else {
+ info->bufNumBufs = drmAddBufs(info->drmFD,
+ info->bufMapSize / RADEON_BUFFER_SIZE,
+ RADEON_BUFFER_SIZE,
+ DRM_AGP_BUFFER,
+ info->bufStart);
+ }
+ if (info->bufNumBufs <= 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Could not create vertex/indirect buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Added %d %d byte vertex/indirect buffers\n",
+ info->bufNumBufs, RADEON_BUFFER_SIZE);
+
+ if (!(info->buffers = drmMapBufs(info->drmFD))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to map vertex/indirect buffers list\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Mapped %d vertex/indirect buffers\n",
+ info->buffers->count);
+
+ return TRUE;
+}
+
+static void RADEONDRIIrqInit(RADEONInfoPtr info, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (!info->irq) {
+ info->irq = drmGetInterruptFromBusID(
+ info->drmFD,
+ ((pciConfigPtr)info->PciInfo->thisCard)->busnum,
+ ((pciConfigPtr)info->PciInfo->thisCard)->devnum,
+ ((pciConfigPtr)info->PciInfo->thisCard)->funcnum);
+
+ if ((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding irq handler, "
+ "there is a device already using that irq\n"
+ "[drm] falling back to irq-free operation\n");
+ info->irq = 0;
+ } else {
+ unsigned char *RADEONMMIO = info->MMIO;
+ info->ModeReg.gen_int_cntl = INREG( RADEON_GEN_INT_CNTL );
+ }
+ }
+
+ if (info->irq)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n",
+ info->irq);
+}
+
+
+/* Initialize the CP state, and start the CP (if used by the X server) */
+static void RADEONDRICPInit(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ /* Turn on bus mastering */
+ info->BusCntl &= ~RADEON_BUS_MASTER_DIS;
+
+ /* Make sure the CP is on for the X server */
+ RADEONCP_START(pScrn, info);
+ RADEONSelectBuffer(pScrn, RADEON_FRONT);
+}
+
+
+/* Initialize the screen-specific data structures for the DRI and the
+ * Radeon. This is the main entry point to the device-specific
+ * initialization code. It calls device-independent DRI functions to
+ * create the DRI data structures and initialize the DRI state.
+ */
+Bool RADEONDRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ RADEONDRIPtr pRADEONDRI;
+ int major, minor, patch;
+ drmVersionPtr version;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module.
+ */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONDRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONDRIScreenInit failed because of a version "
+ "mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d but version 4.0.x is "
+ "needed.\n"
+ "[dri] Disabling DRI.\n",
+ major, minor, patch);
+ return FALSE;
+ }
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 8:
+ case 15:
+ case 24:
+ /* These modes are not supported (yet). */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONInitVisualConfigs failed "
+ "(depth %d not supported). "
+ "Disabling DRI.\n", info->CurrentLayout.pixel_code);
+ return FALSE;
+
+ /* Only 16 and 32 color depths are supports currently. */
+ case 16:
+ case 32:
+ break;
+ }
+
+ /* Create the DRI data structure, and fill it in before calling the
+ * DRIScreenInit().
+ */
+ if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
+
+ info->pDRIInfo = pDRIInfo;
+ pDRIInfo->drmDriverName = RADEON_DRIVER_NAME;
+
+ if (info->ChipFamily == CHIP_FAMILY_R200)
+ pDRIInfo->clientDriverName = R200_DRIVER_NAME;
+ else if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_M9))
+ pDRIInfo->clientDriverName = RV250_DRIVER_NAME;
+ else
+ pDRIInfo->clientDriverName = RADEON_DRIVER_NAME;
+
+ pDRIInfo->busIdString = xalloc(64);
+ sprintf(pDRIInfo->busIdString,
+ "PCI:%d:%d:%d",
+ info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+ pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH;
+ pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr;
+ pDRIInfo->frameBufferSize = info->FbMapSize;
+ pDRIInfo->frameBufferStride = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ pDRIInfo->ddxDrawableTableEntry = RADEON_MAX_DRAWABLES;
+ pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES
+ < RADEON_MAX_DRAWABLES
+ ? SAREA_MAX_DRAWABLES
+ : RADEON_MAX_DRAWABLES);
+
+#ifdef PER_CONTEXT_SAREA
+ /* This is only here for testing per-context SAREAs. When used, the
+ magic number below would be properly defined in a header file. */
+ info->perctx_sarea_size = 64 * 1024;
+#endif
+
+#ifdef NOT_DONE
+ /* FIXME: Need to extend DRI protocol to pass this size back to
+ * client for SAREA mapping that includes a device private record
+ */
+ pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff)
+ & 0x1000); /* round to page */
+ /* + shared memory device private rec */
+#else
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if (sizeof(XF86DRISAREARec)+sizeof(RADEONSAREAPriv) > SAREA_MAX) {
+ ErrorF("Data does not fit in SAREA\n");
+ return FALSE;
+ }
+ pDRIInfo->SAREASize = SAREA_MAX;
+#endif
+
+ if (!(pRADEONDRI = (RADEONDRIPtr)xcalloc(sizeof(RADEONDRIRec),1))) {
+ DRIDestroyInfoRec(info->pDRIInfo);
+ info->pDRIInfo = NULL;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pRADEONDRI;
+ pDRIInfo->devPrivateSize = sizeof(RADEONDRIRec);
+ pDRIInfo->contextSize = sizeof(RADEONDRIContextRec);
+
+ pDRIInfo->CreateContext = RADEONCreateContext;
+ pDRIInfo->DestroyContext = RADEONDestroyContext;
+ pDRIInfo->SwapContext = RADEONDRISwapContext;
+ pDRIInfo->InitBuffers = RADEONDRIInitBuffers;
+ pDRIInfo->MoveBuffers = RADEONDRIMoveBuffers;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+ pDRIInfo->OpenFullScreen = RADEONDRIOpenFullScreen;
+ pDRIInfo->CloseFullScreen = RADEONDRICloseFullScreen;
+ pDRIInfo->TransitionTo2d = RADEONDRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d;
+ pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d;
+ pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pDRIInfo);
+ pDRIInfo = NULL;
+ return FALSE;
+ }
+
+ /* Check the DRM lib version.
+ * drmGetLibVersion was not supported in version 1.0, so check for
+ * symbol first to avoid possible crash or hang.
+ */
+ if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
+ version = drmGetLibVersion(info->drmFD);
+ } else {
+ /* drmlib version 1.0.0 didn't have the drmGetLibVersion
+ * entry point. Fake it by allocating a version record
+ * via drmGetVersion and changing it to version 1.0.0.
+ */
+ version = drmGetVersion(info->drmFD);
+ version->version_major = 1;
+ version->version_minor = 0;
+ version->version_patchlevel = 0;
+ }
+
+ if (version) {
+ if (version->version_major != 1 ||
+ version->version_minor < 1) {
+ /* incompatible drm library version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONDRIScreenInit failed because of a "
+ "version mismatch.\n"
+ "[dri] libdrm.a module version is %d.%d.%d but "
+ "version 1.1.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Check the radeon DRM version */
+ version = drmGetVersion(info->drmFD);
+ if (version) {
+ int req_minor, req_patch;
+
+ if ((info->ChipFamily == CHIP_FAMILY_R200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_M9)) {
+ req_minor = 5;
+ req_patch = 0;
+ } else {
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ req_minor = 1;
+ req_patch = 0;
+#else
+ req_minor = 2;
+ req_patch = 1;
+#endif
+ }
+
+ if (version->version_major != 1 ||
+ version->version_minor < req_minor ||
+ (version->version_minor == req_minor &&
+ version->version_patchlevel < req_patch)) {
+ /* Incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] RADEONDRIScreenInit failed because of a version "
+ "mismatch.\n"
+ "[dri] radeon.o kernel module version is %d.%d.%d "
+ "but version 1.%d.%d or newer is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel,
+ req_minor,
+ req_patch);
+ drmFreeVersion(version);
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ if (version->version_minor < 3) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[dri] Some DRI features disabled because of version "
+ "mismatch.\n"
+ "[dri] radeon.o kernel module version is %d.%d.%d but "
+ "1.3.1 or later is preferred.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ }
+ info->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+
+ /* Initialize AGP */
+ if (!info->IsPCI && !RADEONDRIAgpInit(info, pScreen)) {
+#if defined(__alpha__) || defined(__powerpc__)
+ info->IsPCI = TRUE;
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[agp] AGP failed to initialize "
+ "-- falling back to PCI mode.\n");
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[agp] If this is an AGP card, you may want to make sure "
+ "the agpgart\nkernel module is loaded before the radeon "
+ "kernel module.\n");
+#else
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+#endif
+ }
+
+ /* Initialize PCI */
+ if (info->IsPCI && !RADEONDRIPciInit(info, pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* DRIScreenInit doesn't add all the
+ * common mappings. Add additional
+ * mappings here.
+ */
+ if (!RADEONDRIMapInit(info, pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* DRIScreenInit adds the frame buffer
+ map, but we need it as well */
+ {
+ void *scratch_ptr;
+ int scratch_int;
+
+ DRIGetDeviceInfo(pScreen, &info->fbHandle,
+ &scratch_int, &scratch_int,
+ &scratch_int, &scratch_int,
+ &scratch_ptr);
+ }
+
+ /* FIXME: When are these mappings unmapped? */
+
+ if (!RADEONInitVisualConfigs(pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
+
+ return TRUE;
+}
+
+/* Finish initializing the device-dependent DRI state, and call
+ * DRIFinishScreenInit() to complete the device-independent DRI
+ * initialization.
+ */
+Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONSAREAPrivPtr pSAREAPriv;
+ RADEONDRIPtr pRADEONDRI;
+
+ info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+ /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
+
+ /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
+ * because *DRIKernelInit requires that the hardware lock is held by
+ * the X server, and the first time the hardware lock is grabbed is
+ * in DRIFinishScreenInit.
+ */
+ if (!DRIFinishScreenInit(pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize the kernel data structures */
+ if (!RADEONDRIKernelInit(info, pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize the vertex buffers list */
+ if (!RADEONDRIBufInit(info, pScreen)) {
+ RADEONDRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Initialize IRQ */
+ RADEONDRIIrqInit(info, pScreen);
+
+ /* Initialize kernel agp memory manager */
+ RADEONDRIAgpHeapInit(info, pScreen);
+
+ /* Initialize and start the CP if required */
+ RADEONDRICPInit(pScrn);
+
+ /* Initialize the SAREA private data structure */
+ pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+ pRADEONDRI = (RADEONDRIPtr)info->pDRIInfo->devPrivate;
+
+ pRADEONDRI->deviceID = info->Chipset;
+ pRADEONDRI->width = pScrn->virtualX;
+ pRADEONDRI->height = pScrn->virtualY;
+ pRADEONDRI->depth = pScrn->depth;
+ pRADEONDRI->bpp = pScrn->bitsPerPixel;
+
+ pRADEONDRI->IsPCI = info->IsPCI;
+ pRADEONDRI->AGPMode = info->agpMode;
+
+ pRADEONDRI->frontOffset = info->frontOffset;
+ pRADEONDRI->frontPitch = info->frontPitch;
+ pRADEONDRI->backOffset = info->backOffset;
+ pRADEONDRI->backPitch = info->backPitch;
+ pRADEONDRI->depthOffset = info->depthOffset;
+ pRADEONDRI->depthPitch = info->depthPitch;
+ pRADEONDRI->textureOffset = info->textureOffset;
+ pRADEONDRI->textureSize = info->textureSize;
+ pRADEONDRI->log2TexGran = info->log2TexGran;
+
+ pRADEONDRI->registerHandle = info->registerHandle;
+ pRADEONDRI->registerSize = info->registerSize;
+
+ pRADEONDRI->statusHandle = info->ringReadPtrHandle;
+ pRADEONDRI->statusSize = info->ringReadMapSize;
+
+ pRADEONDRI->agpTexHandle = info->agpTexHandle;
+ pRADEONDRI->agpTexMapSize = info->agpTexMapSize;
+ pRADEONDRI->log2AGPTexGran = info->log2AGPTexGran;
+ pRADEONDRI->agpTexOffset = info->agpTexStart;
+
+ pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+#ifdef PER_CONTEXT_SAREA
+ /* Set per-context SAREA size */
+ pRADEONDRI->perctx_sarea_size = info->perctx_sarea_size;
+#endif
+
+ /* Have shadowfb run only while there is 3d active. */
+ if (info->allowPageFlip /* && info->drmMinor >= 3 */) {
+ ShadowFBInit( pScreen, RADEONDRIRefreshArea );
+ } else {
+ info->allowPageFlip = 0;
+ }
+
+ return TRUE;
+}
+
+/* The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ */
+void RADEONDRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ drmRadeonInit drmInfo;
+ RING_LOCALS;
+
+ /* Stop the CP */
+ if (info->directRenderingEnabled) {
+ /* If we've generated any CP commands, we must flush them to the
+ * kernel module now.
+ */
+ if (info->CPInUse) {
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+ RADEONCPReleaseIndirect(pScrn);
+
+ info->CPInUse = FALSE;
+ }
+ RADEONCP_STOP(pScrn, info);
+ }
+
+ if (info->irq) {
+ drmCtlUninstHandler(info->drmFD);
+ info->irq = 0;
+ info->ModeReg.gen_int_cntl = 0;
+ }
+
+ /* De-allocate vertex buffers */
+ if (info->buffers) {
+ drmUnmapBufs(info->buffers);
+ info->buffers = NULL;
+ }
+
+ /* De-allocate all kernel resources */
+ memset(&drmInfo, 0, sizeof(drmRadeonInit));
+ drmInfo.func = DRM_RADEON_CLEANUP_CP;
+ drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
+ &drmInfo, sizeof(drmRadeonInit));
+
+ /* De-allocate all AGP resources */
+ if (info->agpTex) {
+ drmUnmap(info->agpTex, info->agpTexMapSize);
+ info->agpTex = NULL;
+ }
+ if (info->buf) {
+ drmUnmap(info->buf, info->bufMapSize);
+ info->buf = NULL;
+ }
+ if (info->ringReadPtr) {
+ drmUnmap(info->ringReadPtr, info->ringReadMapSize);
+ info->ringReadPtr = NULL;
+ }
+ if (info->ring) {
+ drmUnmap(info->ring, info->ringMapSize);
+ info->ring = NULL;
+ }
+ if (info->agpMemHandle) {
+ drmAgpUnbind(info->drmFD, info->agpMemHandle);
+ drmAgpFree(info->drmFD, info->agpMemHandle);
+ info->agpMemHandle = 0;
+ drmAgpRelease(info->drmFD);
+ }
+ if (info->pciMemHandle) {
+ drmScatterGatherFree(info->drmFD, info->pciMemHandle);
+ info->pciMemHandle = 0;
+ }
+
+ /* De-allocate all DRI resources */
+ DRICloseScreen(pScreen);
+
+ /* De-allocate all DRI data structures */
+ if (info->pDRIInfo) {
+ if (info->pDRIInfo->devPrivate) {
+ xfree(info->pDRIInfo->devPrivate);
+ info->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(info->pDRIInfo);
+ info->pDRIInfo = NULL;
+ }
+ if (info->pVisualConfigs) {
+ xfree(info->pVisualConfigs);
+ info->pVisualConfigs = NULL;
+ }
+ if (info->pVisualConfigsPriv) {
+ xfree(info->pVisualConfigsPriv);
+ info->pVisualConfigsPriv = NULL;
+ }
+}
+
+
+
+/* Fullscreen hooks. The DRI fullscreen mode can probably be removed as
+ * it adds little or nothing above the mechanism below (and isn't widely
+ * used).
+ */
+static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+
+/* Use callbacks from dri.c to support pageflipping mode for a single
+ * 3d context without need for any specific full-screen extension.
+ *
+ * Also use these callbacks to allocate and free 3d-specific memory on
+ * demand.
+ */
+
+
+/* Use the shadowfb module to maintain a list of dirty rectangles.
+ * These are blitted to the back buffer to keep both buffers clean
+ * during page-flipping when the 3d application isn't fullscreen.
+ *
+ * Unlike most use of the shadowfb code, both buffers are in video memory.
+ *
+ * An alternative to this would be to organize for all on-screen drawing
+ * operations to be duplicated for the two buffers. That might be
+ * faster, but seems like a lot more work...
+ */
+
+
+static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int i;
+ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+ /* Don't want to do this when no 3d is active and pages are
+ * right-way-round
+ */
+ if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
+ return;
+
+ (*info->accel->SetupForScreenToScreenCopy)(pScrn,
+ 1, 1, GXcopy,
+ (CARD32)(-1), -1);
+
+ for (i = 0 ; i < num ; i++, pbox++) {
+ int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1);
+ int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1);
+
+ if (xa <= xb && ya <= yb) {
+ (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya,
+ xa + info->backX,
+ ya + info->backY,
+ xb - xa + 1,
+ yb - ya + 1);
+ }
+ }
+}
+
+static void RADEONEnablePageFlip(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ if (info->allowPageFlip) {
+ /* Duplicate the frontbuffer to the backbuffer */
+ (*info->accel->SetupForScreenToScreenCopy)(pScrn,
+ 1, 1, GXcopy,
+ (CARD32)(-1), -1);
+
+ (*info->accel->SubsequentScreenToScreenCopy)(pScrn,
+ 0,
+ 0,
+ info->backX,
+ info->backY,
+ pScrn->virtualX,
+ pScrn->virtualY);
+
+ pSAREAPriv->pfAllowPageFlip = 1;
+ }
+}
+
+static void RADEONDisablePageFlip(ScreenPtr pScreen)
+{
+ /* Tell the clients not to pageflip. How?
+ * -- Field in sarea, plus bumping the window counters.
+ * -- DRM needs to cope with Front-to-Back swapbuffers.
+ */
+ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ pSAREAPriv->pfAllowPageFlip = 0;
+}
+
+static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen)
+{
+ RADEONDisablePageFlip(pScreen);
+}
+
+static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen)
+{
+ /* Let the remaining 3d app start page flipping again */
+ RADEONEnablePageFlip(pScreen);
+}
+
+static void RADEONDRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ FBAreaPtr fbarea;
+ int width, height;
+
+ /* reserve offscreen area for back and depth buffers and textures */
+
+ /* If we still have an area for the back buffer reserved, free it
+ * first so we always start with all free offscreen memory, except
+ * maybe for Xv
+ */
+ if (info->backArea) {
+ xf86FreeOffscreenArea(info->backArea);
+ info->backArea = NULL;
+ }
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+ xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
+
+ /* Free Xv linear offscreen memory if necessary */
+ if (height < (info->depthTexLines + info->backLines)) {
+ xf86FreeOffscreenLinear(info->videoLinear);
+ info->videoLinear = NULL;
+ xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
+ }
+
+ /* Reserve placeholder area so the other areas will match the
+ * pre-calculated offsets
+ */
+ fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ height
+ - info->depthTexLines
+ - info->backLines,
+ pScrn->displayWidth,
+ NULL, NULL, NULL);
+ if (!fbarea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
+ "offscreen area, you might experience screen corruption\n");
+
+ info->backArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ info->backLines,
+ pScrn->displayWidth,
+ NULL, NULL, NULL);
+ if (!info->backArea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen "
+ "area for back buffer, you might experience screen "
+ "corruption\n");
+
+ info->depthTexArea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth,
+ info->depthTexLines,
+ pScrn->displayWidth,
+ NULL, NULL, NULL);
+ if (!info->depthTexArea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen "
+ "area for depth buffer and textures, you might "
+ "experience screen corruption\n");
+
+ xf86FreeOffscreenArea(fbarea);
+
+ RADEONEnablePageFlip(pScreen);
+
+ info->have3DWindows = 1;
+
+ if (info->cursor_start)
+ xf86ForceHWCursor (pScreen, TRUE);
+}
+
+static void RADEONDRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ /* Shut down shadowing if we've made it back to the front page */
+ if (pSAREAPriv->pfCurrentPage == 0) {
+ RADEONDisablePageFlip(pScreen);
+ xf86FreeOffscreenArea(info->backArea);
+ info->backArea = NULL;
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[dri] RADEONDRITransitionTo2d: "
+ "kernel failed to unflip buffers.\n");
+ }
+
+ xf86FreeOffscreenArea(info->depthTexArea);
+
+ info->have3DWindows = 0;
+
+ if (info->cursor_start)
+ xf86ForceHWCursor (pScreen, FALSE);
+}
diff --git a/src/radeon_dri.h b/src/radeon_dri.h
new file mode 100644
index 0000000..abfcb4e
--- /dev/null
+++ b/src/radeon_dri.h
@@ -0,0 +1,107 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h,v 1.4 2002/10/30 12:52:13 alanh Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario,
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ *
+ */
+
+#ifndef _RADEON_DRI_
+#define _RADEON_DRI_
+
+#include "xf86drm.h"
+#include "radeon_common.h"
+
+/* DRI Driver defaults */
+#define RADEON_DEFAULT_CP_PIO_MODE RADEON_CSQ_PRIPIO_INDPIO
+#define RADEON_DEFAULT_CP_BM_MODE RADEON_CSQ_PRIBM_INDBM
+#define RADEON_DEFAULT_AGP_MODE 1
+#define RADEON_DEFAULT_AGP_FAST_WRITE 0
+#define RADEON_DEFAULT_AGP_SIZE 8 /* MB (must be 2^n and > 4MB) */
+#define RADEON_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
+#define RADEON_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */
+#define RADEON_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
+
+#define RADEON_DEFAULT_CP_TIMEOUT 10000 /* usecs */
+
+#define RADEON_AGP_MAX_MODE 4
+
+#define RADEON_CARD_TYPE_RADEON 1
+
+/* Buffer are aligned on 4096 byte boundaries */
+#define RADEON_BUFFER_ALIGN 0x00000fff
+
+#define RADEONCP_USE_RING_BUFFER(m) \
+ (((m) == RADEON_CSQ_PRIBM_INDDIS) || \
+ ((m) == RADEON_CSQ_PRIBM_INDBM))
+
+typedef struct {
+ /* DRI screen private data */
+ int deviceID; /* PCI device ID */
+ int width; /* Width in pixels of display */
+ int height; /* Height in scanlines of display */
+ int depth; /* Depth of display (8, 15, 16, 24) */
+ int bpp; /* Bit depth of display (8, 16, 24, 32) */
+
+ int IsPCI; /* Current card is a PCI card */
+ int AGPMode;
+
+ int frontOffset; /* Start of front buffer */
+ int frontPitch;
+ int backOffset; /* Start of shared back buffer */
+ int backPitch;
+ int depthOffset; /* Start of shared depth buffer */
+ int depthPitch;
+ int textureOffset;/* Start of texture data in frame buffer */
+ int textureSize;
+ int log2TexGran;
+
+ /* MMIO register data */
+ drmHandle registerHandle;
+ drmSize registerSize;
+
+ /* CP in-memory status information */
+ drmHandle statusHandle;
+ drmSize statusSize;
+
+ /* CP AGP Texture data */
+ drmHandle agpTexHandle;
+ drmSize agpTexMapSize;
+ int log2AGPTexGran;
+ int agpTexOffset;
+ unsigned int sarea_priv_offset;
+
+#ifdef PER_CONTEXT_SAREA
+ drmSize perctx_sarea_size;
+#endif
+} RADEONDRIRec, *RADEONDRIPtr;
+
+#endif
diff --git a/src/radeon_dripriv.h b/src/radeon_dripriv.h
new file mode 100644
index 0000000..5f01192
--- /dev/null
+++ b/src/radeon_dripriv.h
@@ -0,0 +1,64 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dripriv.h,v 1.4 2002/10/30 12:52:13 alanh Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario,
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ *
+ */
+
+#ifndef _RADEON_DRIPRIV_H_
+#define _RADEON_DRIPRIV_H_
+
+#include "GL/glxint.h"
+#include "xf86drm.h"
+#include "radeon_common.h"
+
+#define RADEON_MAX_DRAWABLES 256
+
+extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
+ void **configprivs);
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} RADEONConfigPrivRec, *RADEONConfigPrivPtr;
+
+typedef struct {
+#ifdef PER_CONTEXT_SAREA
+ drmContext ctx_id;
+ drmHandle sarea_handle;
+#else
+ /* Nothing here yet */
+ int dummy;
+#endif
+} RADEONDRIContextRec, *RADEONDRIContextPtr;
+
+#endif
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
new file mode 100644
index 0000000..ae58433
--- /dev/null
+++ b/src/radeon_driver.c
@@ -0,0 +1,5944 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.91 2003/02/25 03:50:15 dawes Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * Credits:
+ *
+ * Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source
+ * code to his Radeon driver. Portions of this file are based on the
+ * initialization code for that driver.
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ * This server does not yet support these XFree86 4.0 features:
+ * !!!! FIXME !!!!
+ * DDC1 & DDC2
+ * shadowfb (Note: dri uses shadowfb for another purpose in radeon_dri.c)
+ * overlay planes
+ *
+ * Modified by Marc Aurele La France (tsi@xfree86.org) for ATI driver merge.
+ */
+
+ /* Driver data structures */
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_reg.h"
+#include "radeon_version.h"
+
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "radeon_dri.h"
+#include "radeon_sarea.h"
+#endif
+
+#define USE_FB /* not until overlays */
+#ifdef USE_FB
+#include "fb.h"
+#else
+
+ /* CFB support */
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb24.h"
+#include "cfb32.h"
+#endif
+
+ /* colormap initialization */
+#include "micmap.h"
+#include "dixstruct.h"
+
+ /* X and server generic header files */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86PciInfo.h"
+#include "xf86RAC.h"
+#include "xf86Resources.h"
+#include "xf86cmap.h"
+#include "vbe.h"
+
+ /* fbdevhw * vgaHW definitions */
+#include "fbdevhw.h"
+#include "vgaHW.h"
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+ /* Forward definitions for driver functions */
+static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode);
+static void RADEONSave(ScrnInfoPtr pScrn);
+static void RADEONRestore(ScrnInfoPtr pScrn);
+static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode,
+ int flags);
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_DAC_6BIT,
+ OPTION_DAC_8BIT,
+#ifdef XF86DRI
+ OPTION_IS_PCI,
+ OPTION_CP_PIO,
+ OPTION_USEC_TIMEOUT,
+ OPTION_AGP_MODE,
+ OPTION_AGP_FW,
+ OPTION_AGP_SIZE,
+ OPTION_RING_SIZE,
+ OPTION_BUFFER_SIZE,
+ OPTION_DEPTH_MOVE,
+ OPTION_PAGE_FLIP,
+ OPTION_NO_BACKBUFFER,
+#endif
+ OPTION_PANEL_OFF,
+ OPTION_DDC_MODE,
+ OPTION_CLONE_DISPLAY,
+ OPTION_CLONE_MODE,
+ OPTION_CLONE_HSYNC,
+ OPTION_CLONE_VREFRESH,
+ OPTION_FBDEV,
+ OPTION_VIDEO_KEY
+} RADEONOpts;
+
+const OptionInfoRec RADEONOptions[] = {
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE },
+#ifdef XF86DRI
+ { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CP_PIO, "CPPIOMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_USEC_TIMEOUT, "CPusecTimeout", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_AGP_FW, "AGPFastWrite", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_DEPTH_MOVE, "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NO_BACKBUFFER, "NoBackBuffer", OPTV_BOOLEAN, {0}, FALSE },
+#endif
+ { OPTION_PANEL_OFF, "PanelOff", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CLONE_DISPLAY, "CloneDisplay", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_CLONE_MODE, "CloneMode", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_CLONE_HSYNC, "CloneHSync", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+RADEONRAMRec RADEONRAM[] = { /* Memory Specifications
+ From Radeon Manual */
+ { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SDRAM" },
+ { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SDRAM" },
+};
+
+static const char *vgahwSymbols[] = {
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIndex",
+ "vgaHWLock",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWUnlock",
+ "vgaHWGetIOBase",
+ NULL
+};
+
+static const char *fbdevHWSymbols[] = {
+ "fbdevHWInit",
+ "fbdevHWUseBuildinMode",
+
+ "fbdevHWGetVidmem",
+
+ "fbdevHWDPMSSet",
+
+ /* colormap */
+ "fbdevHWLoadPalette",
+ /* ScrnInfo hooks */
+ "fbdevHWAdjustFrame",
+ "fbdevHWEnterVT",
+ "fbdevHWLeaveVT",
+ "fbdevHWModeInit",
+ "fbdevHWRestore",
+ "fbdevHWSave",
+ "fbdevHWSwitchMode",
+ "fbdevHWValidMode",
+
+ "fbdevHWMapMMIO",
+ "fbdevHWMapVidmem",
+ "fbdevHWUnmapMMIO",
+ "fbdevHWUnmapVidmem",
+
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ NULL
+};
+
+#ifdef USE_FB
+static const char *fbSymbols[] = {
+ "fbScreenInit",
+ "fbPictureInit",
+ NULL
+};
+#else
+static const char *cfbSymbols[] = {
+ "cfbScreenInit",
+ "cfb16ScreenInit",
+ "cfb24ScreenInit",
+ "cfb32ScreenInit",
+ NULL
+};
+#endif
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ NULL
+};
+
+#if 0
+static const char *xf8_32bppSymbols[] = {
+ "xf86Overlay8Plus32Init",
+ NULL
+};
+#endif
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86ForceHWCursor",
+ "xf86InitCursor",
+ NULL
+};
+
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmGetInterruptFromBusID",
+ "drmCtlInstHandler",
+ "drmCtlUninstHandler",
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAgpAcquire",
+ "drmAgpAlloc",
+ "drmAgpBase",
+ "drmAgpBind",
+ "drmAgpDeviceId",
+ "drmAgpEnable",
+ "drmAgpFree",
+ "drmAgpGetMode",
+ "drmAgpRelease",
+ "drmAgpUnbind",
+ "drmAgpVendorId",
+ "drmCommandNone",
+ "drmCommandRead",
+ "drmCommandWrite",
+ "drmCommandWriteRead",
+ "drmDMA",
+ "drmFreeVersion",
+ "drmGetLibVersion",
+ "drmGetVersion",
+ "drmMap",
+ "drmMapBufs",
+ "drmRadeonCleanupCP",
+ "drmRadeonClear",
+ "drmRadeonFlushIndirectBuffer",
+ "drmRadeonInitCP",
+ "drmRadeonResetCP",
+ "drmRadeonStartCP",
+ "drmRadeonStopCP",
+ "drmRadeonWaitForIdleCP",
+ "drmScatterGatherAlloc",
+ "drmScatterGatherFree",
+ "drmUnmap",
+ "drmUnmapBufs",
+ NULL
+};
+
+static const char *driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetContext",
+ "DRIGetDeviceInfo",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ NULL
+};
+
+static const char *driShadowFBSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+#endif
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86InitInt10",
+ "xf86FreeInt10",
+ "xf86int10Addr",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+void RADEONLoaderRefSymLists(void)
+{
+ /*
+ * Tell the loader about symbols from other modules that this module might
+ * refer to.
+ */
+ xf86LoaderRefSymLists(vgahwSymbols,
+#ifdef USE_FB
+ fbSymbols,
+#else
+ cfbSymbols,
+#endif
+ xaaSymbols,
+#if 0
+ xf8_32bppSymbols,
+#endif
+ ramdacSymbols,
+#ifdef XF86DRI
+ drmSymbols,
+ driSymbols,
+ driShadowFBSymbols,
+#endif
+ fbdevHWSymbols,
+ vbeSymbols,
+ int10Symbols,
+ i2cSymbols,
+ ddcSymbols,
+ NULL);
+}
+
+/* Established timings from EDID standard */
+static struct
+{
+ int hsize;
+ int vsize;
+ int refresh;
+} est_timings[] = {
+ {1280, 1024, 75},
+ {1024, 768, 75},
+ {1024, 768, 70},
+ {1024, 768, 60},
+ {1024, 768, 87},
+ {832, 624, 75},
+ {800, 600, 75},
+ {800, 600, 72},
+ {800, 600, 60},
+ {800, 600, 56},
+ {640, 480, 75},
+ {640, 480, 72},
+ {640, 480, 67},
+ {640, 480, 60},
+ {720, 400, 88},
+ {720, 400, 70},
+};
+
+extern int gRADEONEntityIndex;
+
+struct RADEONInt10Save {
+ CARD32 MEM_CNTL;
+ CARD32 MEMSIZE;
+ CARD32 MPP_TB_CONFIG;
+};
+
+static Bool RADEONMapMMIO(ScrnInfoPtr pScrn);
+static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn);
+
+static void
+RADEONPreInt10Save(ScrnInfoPtr pScrn, void **pPtr)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO;
+ int mapped = 0;
+ CARD32 CardTmp;
+ static struct RADEONInt10Save SaveStruct = { 0, 0, 0 };
+
+ /*
+ * First make sure we have the pci and mmio info and that mmio is mapped
+ */
+ if (!info->PciInfo)
+ info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
+ if (!info->PciTag)
+ info->PciTag = pciTag(info->PciInfo->bus, info->PciInfo->device,
+ info->PciInfo->func);
+ if (!info->MMIOAddr)
+ info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00;
+ if (!info->MMIO) {
+ RADEONMapMMIO(pScrn);
+ mapped = 1;
+ }
+ RADEONMMIO = info->MMIO;
+
+ /* Save the values and zap MEM_CNTL */
+ SaveStruct.MEM_CNTL = INREG(RADEON_MEM_CNTL);
+ SaveStruct.MEMSIZE = INREG(RADEON_CONFIG_MEMSIZE);
+ SaveStruct.MPP_TB_CONFIG = INREG(RADEON_MPP_TB_CONFIG);
+
+ /*
+ * Zap MEM_CNTL and set MPP_TB_CONFIG<31:24> to 4
+ */
+ OUTREG(RADEON_MEM_CNTL, 0);
+ CardTmp = SaveStruct.MPP_TB_CONFIG & 0x00ffffffu;
+ CardTmp |= 0x04 << 24;
+ OUTREG(RADEON_MPP_TB_CONFIG, CardTmp);
+
+ *pPtr = (void *)&SaveStruct;
+
+ /* Unmap mmio space if we mapped it */
+ if (mapped)
+ RADEONUnmapMMIO(pScrn);
+}
+
+static void
+RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO;
+ struct RADEONInt10Save *pSave = ptr;
+ CARD32 CardTmp;
+ int mapped = 0;
+
+ /* If we don't have a valid (non-zero) saved MEM_CNTL, get out now */
+ if (!pSave || !pSave->MEM_CNTL)
+ return;
+
+ /* First make sure that mmio is mapped */
+ if (!info->MMIO) {
+ RADEONMapMMIO(pScrn);
+ mapped = 1;
+ }
+ RADEONMMIO = info->MMIO;
+
+ /*
+ * If either MEM_CNTL is currently zero or inconistent (configured for
+ * two channels with the two channels configured differently), restore
+ * the saved registers.
+ */
+ CardTmp = INREG(RADEON_MEM_CNTL);
+ if (!CardTmp ||
+ ((CardTmp & 1) &&
+ (((CardTmp >> 8) & 0xff) != ((CardTmp >> 24) & 0xff)))) {
+ /* Restore the saved registers */
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Restoring MEM_CNTL (%08x), setting to %08x\n",
+ CardTmp, pSave->MEM_CNTL);
+ OUTREG(RADEON_MEM_CNTL, pSave->MEM_CNTL);
+
+ CardTmp = INREG(RADEON_CONFIG_MEMSIZE);
+ if (CardTmp != pSave->MEMSIZE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Restoring CONFIG_MEMSIZE (%08x), setting to %08x\n",
+ CardTmp, pSave->MEMSIZE);
+ OUTREG(RADEON_CONFIG_MEMSIZE, pSave->MEMSIZE);
+ }
+ }
+
+ CardTmp = INREG(RADEON_MPP_TB_CONFIG);
+ if ((CardTmp & 0xff000000u) != (pSave->MPP_TB_CONFIG & 0xff000000u)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Restoring MPP_TB_CONFIG<31:24> (%02x), setting to %02x\n",
+ CardTmp >> 24, pSave->MPP_TB_CONFIG >> 24);
+ CardTmp &= 0x00ffffffu;
+ CardTmp |= (pSave->MPP_TB_CONFIG & 0xff000000u);
+ OUTREG(RADEON_MPP_TB_CONFIG, CardTmp);
+ }
+
+ /* Unmap mmio space if we mapped it */
+ if (mapped)
+ RADEONUnmapMMIO(pScrn);
+}
+
+/* Allocate our private RADEONInfoRec */
+static Bool RADEONGetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate) return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(RADEONInfoRec), 1);
+ return TRUE;
+}
+
+/* Free our private RADEONInfoRec */
+static void RADEONFreeRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn || !pScrn->driverPrivate) return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+/* Memory map the MMIO region. Used during pre-init and by RADEONMapMem,
+ * below
+ */
+static Bool RADEONMapMMIO(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->FBDev) {
+ info->MMIO = fbdevHWMapMMIO(pScrn);
+ } else {
+ info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
+ info->PciTag,
+ info->MMIOAddr,
+ RADEON_MMIOSIZE);
+ }
+
+ if (!info->MMIO) return FALSE;
+ return TRUE;
+}
+
+/* Unmap the MMIO region. Used during pre-init and by RADEONUnmapMem,
+ * below
+ */
+static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->FBDev)
+ fbdevHWUnmapMMIO(pScrn);
+ else {
+ xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, RADEON_MMIOSIZE);
+ }
+ info->MMIO = NULL;
+ return TRUE;
+}
+
+/* Memory map the frame buffer. Used by RADEONMapMem, below. */
+static Bool RADEONMapFB(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->FBDev) {
+ info->FB = fbdevHWMapVidmem(pScrn);
+ } else {
+ info->FB = xf86MapPciMem(pScrn->scrnIndex,
+ VIDMEM_FRAMEBUFFER,
+ info->PciTag,
+ info->LinearAddr,
+ info->FbMapSize);
+ }
+
+ if (!info->FB) return FALSE;
+ return TRUE;
+}
+
+/* Unmap the frame buffer. Used by RADEONUnmapMem, below. */
+static Bool RADEONUnmapFB(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->FBDev)
+ fbdevHWUnmapVidmem(pScrn);
+ else
+ xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
+ info->FB = NULL;
+ return TRUE;
+}
+
+/* Memory map the MMIO region and the frame buffer */
+static Bool RADEONMapMem(ScrnInfoPtr pScrn)
+{
+ if (!RADEONMapMMIO(pScrn)) return FALSE;
+ if (!RADEONMapFB(pScrn)) {
+ RADEONUnmapMMIO(pScrn);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Unmap the MMIO region and the frame buffer */
+static Bool RADEONUnmapMem(ScrnInfoPtr pScrn)
+{
+ if (!RADEONUnmapMMIO(pScrn) || !RADEONUnmapFB(pScrn)) return FALSE;
+ return TRUE;
+}
+
+/* This function is required to workaround a hardware bug in some (all?)
+ * revisions of the R300. This workaround should be called after every
+ * CLOCK_CNTL_INDEX register access. If not, register reads afterward
+ * may not be correct.
+ */
+void R300CGWorkaround(ScrnInfoPtr pScrn) {
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 save, tmp;
+
+ save = INREG(RADEON_CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(RADEON_CLOCK_CNTL_DATA);
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, save);
+}
+
+/* Read PLL information */
+unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 data;
+
+ OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f);
+ data = INREG(RADEON_CLOCK_CNTL_DATA);
+ if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+
+ return data;
+}
+
+#if 0
+/* Read PAL information (only used for debugging) */
+static int RADEONINPAL(int idx)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREG(RADEON_PALETTE_INDEX, idx << 16);
+ return INREG(RADEON_PALETTE_DATA);
+}
+#endif
+
+/* Wait for vertical sync on primary CRTC */
+void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+ /* Clear the CRTC_VBLANK_SAVE bit */
+ OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR);
+
+ /* Wait for it to go back up */
+ for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
+ if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break;
+ usleep(1);
+ }
+}
+
+/* Wait for vertical sync on secondary CRTC */
+void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+ /* Clear the CRTC2_VBLANK_SAVE bit */
+ OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR);
+
+ /* Wait for it to go back up */
+ for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
+ if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break;
+ usleep(1);
+ }
+}
+
+/* Blank screen */
+static void RADEONBlank(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (!info->IsSecondary) {
+ switch(info->DisplayType) {
+ case MT_LCD:
+ case MT_CRT:
+ case MT_DFP:
+ OUTREGP(RADEON_CRTC_EXT_CNTL,
+ RADEON_CRTC_DISPLAY_DIS |
+ RADEON_CRTC_VSYNC_DIS |
+ RADEON_CRTC_HSYNC_DIS,
+ ~(RADEON_CRTC_DISPLAY_DIS |
+ RADEON_CRTC_VSYNC_DIS |
+ RADEON_CRTC_HSYNC_DIS));
+ break;
+
+ case MT_NONE:
+ default:
+ break;
+ }
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS,
+ ~(RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS));
+ } else {
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS,
+ ~(RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS));
+ }
+}
+
+/* Unblank screen */
+static void RADEONUnblank(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (!info->IsSecondary) {
+ switch (info->DisplayType) {
+ case MT_LCD:
+ case MT_CRT:
+ case MT_DFP:
+ OUTREGP(RADEON_CRTC_EXT_CNTL,
+ RADEON_CRTC_CRT_ON,
+ ~(RADEON_CRTC_DISPLAY_DIS |
+ RADEON_CRTC_VSYNC_DIS |
+ RADEON_CRTC_HSYNC_DIS));
+ break;
+
+ case MT_NONE:
+ default:
+ break;
+ }
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ 0,
+ ~(RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS));
+ } else {
+ switch (info->DisplayType) {
+ case MT_LCD:
+ case MT_DFP:
+ case MT_CRT:
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ 0,
+ ~(RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS));
+ break;
+
+ case MT_NONE:
+ default:
+ break;
+ }
+ }
+}
+
+/* Compute log base 2 of val */
+int RADEONMinBits(int val)
+{
+ int bits;
+
+ if (!val) return 1;
+ for (bits = 0; val; val >>= 1, ++bits);
+ return bits;
+}
+
+/* Compute n/d with rounding */
+static int RADEONDiv(int n, int d)
+{
+ return (n + (d / 2)) / d;
+}
+
+/* Read the Video BIOS block and the FP registers (if applicable) */
+static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long tmp, i;
+ unsigned char *RADEONMMIO;
+ Bool BypassSecondary = FALSE;
+ int CloneDispOption;
+
+#define RADEON_BIOS8(v) (info->VBIOS[v])
+#define RADEON_BIOS16(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8))
+#define RADEON_BIOS32(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8) | \
+ (info->VBIOS[(v) + 2] << 16) | \
+ (info->VBIOS[(v) + 3] << 24))
+
+ if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Cannot allocate space for hold Video BIOS!\n");
+ return FALSE;
+ }
+
+ if (pInt10) {
+ info->BIOSAddr = pInt10->BIOSseg << 4;
+ (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
+ RADEON_VBIOS_SIZE);
+ } else {
+ xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE);
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected in PCI space!\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Attempting to read Video BIOS from "
+ "legacy ISA space!\n");
+ info->BIOSAddr = 0x000c0000;
+ xf86ReadDomainMemory(info->PciTag, info->BIOSAddr,
+ RADEON_VBIOS_SIZE, info->VBIOS);
+ }
+ }
+
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ info->BIOSAddr = 0x00000000;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not found!\n");
+ return TRUE;
+ }
+
+ info->FPBIOSstart = RADEON_BIOS16(0x48);
+ info->OverlayOnCRTC2 = FALSE;
+
+ RADEONMapMMIO(pScrn);
+ RADEONMMIO = info->MMIO;
+
+ /* FIXME: using BIOS scratch registers to detect connected monitors
+ * may not be a reliable way.... should use EDID data. Also it only
+ * works with for VE/M6, no such registers in regular RADEON!!!
+ */
+
+ /* VE and M6 have both DVI and CRT ports (for M6 DVI port can be
+ * switch to DFP port). The DVI port can also be conneted to a CRT
+ * with an adapter. Here is the definition of ports for this
+ * driver:
+ *
+ * (1) If both port are connected, DVI port will be treated as the
+ * Primary port (first screen in XF86Config, uses CRTC1) and CRT
+ * port will be treated as the Secondary port (second screen in
+ * XF86Config, uses CRTC2)
+ *
+ * (2) If only one screen specified in XF86Config, it will be used
+ * for DVI port if a monitor is connected to DVI port, otherwise
+ * (only one monitor is connected the CRT port) it will be used for
+ * CRT port.
+ */
+
+ if (info->HasCRTC2) {
+ /* FIXME: this may not be reliable */
+ tmp = INREG(RADEON_BIOS_4_SCRATCH);
+
+ if (info->IsSecondary) {
+ /* Check Port2 (CRT port) -- for the existing boards (VE &
+ * M6), this port can only be connected to a CRT
+ */
+ if (tmp & 0x02) info->DisplayType = MT_CRT;
+ else if (tmp & 0x800) info->DisplayType = MT_DFP;
+ else if (tmp & 0x400) info->DisplayType = MT_LCD;
+ else if (tmp & 0x1000) info->DisplayType = MT_CTV;
+ else if (tmp & 0x2000) info->DisplayType = MT_STV;
+ else info->DisplayType = MT_CRT;
+
+ } else {
+ info->Clone = FALSE;
+ info->CloneType = MT_NONE;
+
+ /* Check Primary (DVI/DFP port) */
+ if (tmp & 0x08) info->DisplayType = MT_DFP;
+ else if (tmp & 0x04) info->DisplayType = MT_LCD;
+ else if (tmp & 0x0200) info->DisplayType = MT_CRT;
+ else if (tmp & 0x10) info->DisplayType = MT_CTV;
+ else if (tmp & 0x20) info->DisplayType = MT_STV;
+ else info->DisplayType = MT_NONE;
+
+ if (info->DisplayType == MT_NONE) {
+ /* DVI port has no monitor connected, try CRT port.
+ * If something on CRT port, treat it as primary
+ */
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+ pRADEONEnt->BypassSecondary = TRUE;
+ }
+
+ if (tmp & 0x02) info->DisplayType = MT_CRT;
+ else if (tmp & 0x800) info->DisplayType = MT_DFP;
+ else if (tmp & 0x400) info->DisplayType = MT_LCD;
+ else if (tmp & 0x1000) info->DisplayType = MT_CTV;
+ else if (tmp & 0x2000) info->DisplayType = MT_STV;
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No monitor detected!!!\n");
+ return FALSE;
+ }
+ BypassSecondary = TRUE;
+ } else {
+ if (tmp & 0x02) {
+ info->CloneType = MT_CRT;
+ info->Clone = TRUE;
+ } else if (tmp & 0x800) {
+ info->CloneType = MT_DFP;
+ info->Clone = TRUE;
+ }
+ }
+
+ /* FIXME: This option is too complicated. We need to
+ * find a better way to handle all cases.
+ *
+ * CloneDisplay options:
+ * 0 -- disable
+ * 1 -- auto-detect (default)
+ * 2 -- force on
+ * 3 -- auto-detect + 2nd head overlay.
+ * 4 -- force on + 2nd head overlay.
+ * others -- auto-detect
+ *
+ * Force on: it will force the clone mode on even no display
+ * is detected. With this option together with the proper
+ * CloneHSync and CloneVRefresh options, we can turn on the
+ * CRT ouput on the 2nd head regardless if a monitor is
+ * connected there. This way, we can plug in a CRT to the
+ * second head later after X server has started.
+ *
+ * 2nd head overlay: it will force the hardware overlay on
+ * CRTC2 (used by 2nd head). Since we only have one overlay,
+ * we have to decide which head to use it (the overlay space
+ * on the other head will be blank). 2nd head overlay is on
+ * automatically when PanelOff option is effective.
+ */
+ if (xf86GetOptValInteger(info->Options, OPTION_CLONE_DISPLAY,
+ &(CloneDispOption))) {
+ char *s = NULL;
+
+ if (CloneDispOption < 0 || CloneDispOption > 4) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Illegal CloneDisplay Option set, "
+ "using default\n");
+ CloneDispOption = 1;
+ }
+
+ switch (CloneDispOption) {
+ case 0: s = "Disable"; break;
+ case 1: s = "Auto-detect"; break;
+ case 2: s = "Force On"; break;
+ case 3: s = "Auto-detect -- use 2nd head overlay"; break;
+ case 4: s = "Force On -- use 2nd head overlay"; break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "CloneDisplay option: %s (%d)\n",
+ s, CloneDispOption);
+ } else {
+ /* Default to auto-detect */
+ CloneDispOption = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "CloneDisplay option not set -- "
+ "defaulting to auto-detect\n");
+ }
+
+ if (CloneDispOption == 0) {
+ info->Clone = FALSE;
+ } else if ((CloneDispOption == 2 || CloneDispOption == 4)
+ && !info->Clone) {
+ info->CloneType = MT_CRT;
+ info->Clone = TRUE;
+ }
+
+ /* This will be used to set OV0_SCALAR_CNTL */
+ if (info->Clone && (CloneDispOption == 3 || CloneDispOption == 4))
+ info->OverlayOnCRTC2 = TRUE;
+ }
+ } else {
+ /* Regular Radeon ASIC, only one CRTC, but it could be used for
+ * DFP with a DVI output, like AIW board
+ */
+ tmp = INREG(RADEON_FP_GEN_CNTL);
+ if (tmp & RADEON_FP_EN_TMDS) info->DisplayType = MT_DFP;
+ else info->DisplayType = MT_CRT;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n",
+ (info->IsSecondary ? "Secondary" : "Primary"),
+ info->DisplayType);
+
+ RADEONMMIO = NULL;
+ RADEONUnmapMMIO(pScrn);
+
+ info->HBlank = 0;
+ info->HOverPlus = 0;
+ info->HSyncWidth = 0;
+ info->VBlank = 0;
+ info->VOverPlus = 0;
+ info->VSyncWidth = 0;
+ info->DotClock = 0;
+
+ if (info->DisplayType == MT_LCD) {
+ tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40);
+ if (!tmp) {
+ info->PanelPwrDly = 200;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No Panel Info Table found in BIOS!\n");
+ } else {
+ char stmp[30];
+ int tmp0;
+
+ for (i = 0; i < 24; i++)
+ stmp[i] = RADEON_BIOS8(tmp+i+1);
+ stmp[24] = 0;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Panel ID string: %s\n", stmp);
+
+ info->PanelXRes = RADEON_BIOS16(tmp+25);
+ info->PanelYRes = RADEON_BIOS16(tmp+27);
+ xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n",
+ info->PanelXRes, info->PanelYRes);
+
+ info->PanelPwrDly = RADEON_BIOS16(tmp+44);
+ if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0)
+ info->PanelPwrDly = 2000;
+ for (i = 0; i < 20; i++) {
+ tmp0 = RADEON_BIOS16(tmp+64+i*2);
+ if (tmp0 == 0) break;
+ if ((RADEON_BIOS16(tmp0) == info->PanelXRes) &&
+ (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) {
+ info->HBlank = (RADEON_BIOS16(tmp0+17) -
+ RADEON_BIOS16(tmp0+19)) * 8;
+ info->HOverPlus = (RADEON_BIOS16(tmp0+21) -
+ RADEON_BIOS16(tmp0+19) - 1) * 8;
+ info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8;
+ info->VBlank = (RADEON_BIOS16(tmp0+24) -
+ RADEON_BIOS16(tmp0+26));
+ info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) -
+ RADEON_BIOS16(tmp0+26));
+ info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800)
+ >> 11);
+ info->DotClock = RADEON_BIOS16(tmp0+9) * 10;
+ info->Flags = 0;
+ }
+ }
+ }
+ } else if ((info->DisplayType == MT_DFP) && info->HasCRTC2) {
+ tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34);
+ if (tmp != 0) {
+ tmp = RADEON_BIOS16(tmp + 2);
+ if (tmp != 0) {
+ /* 18 bytes of EDID data should be here */
+ info->DotClock = RADEON_BIOS16(tmp) * 10;
+ info->PanelXRes =
+ ((RADEON_BIOS8(tmp + 4) & 0xf0) << 4) +
+ RADEON_BIOS8(tmp + 2);
+ info->HBlank =
+ ((RADEON_BIOS8(tmp + 4) & 0x0f) << 8) +
+ RADEON_BIOS8(tmp + 3);
+ info->PanelYRes =
+ ((RADEON_BIOS8(tmp + 7) & 0xf0) << 4) +
+ RADEON_BIOS8(tmp + 5);
+ info->VBlank =
+ ((RADEON_BIOS8(tmp + 7) & 0x0f) << 8) +
+ RADEON_BIOS8(tmp + 6);
+ info->HOverPlus =
+ ((RADEON_BIOS8(tmp + 11) & 0xc0) << 2) +
+ RADEON_BIOS8(tmp + 8);
+ info->HSyncWidth =
+ ((RADEON_BIOS8(tmp + 11) & 0x30) << 4) +
+ RADEON_BIOS8(tmp + 9);
+ info->VOverPlus =
+ ((RADEON_BIOS8(tmp + 11) & 0x0c) << 2) +
+ ((RADEON_BIOS8(tmp + 10) & 0xf0) >> 4);
+ info->VSyncWidth =
+ ((RADEON_BIOS8(tmp + 11) & 0x03) << 4) +
+ (RADEON_BIOS8(tmp + 10) & 0x0f);
+ info->Flags = 0;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No DFP timing table detected\n");
+ }
+ }
+
+ RADEONTRACE(("DFP Info: ----------------------\n"
+ "pixel clock: %d KHz\n"
+ "panel size: %dx%d\n"
+ "H. Blanking: %d\n"
+ "H. Sync. Offset: %d\n"
+ "H. Sync. Width: %d\n"
+ "V. Blanking: %d\n"
+ "V. Sync. Offset: %d\n"
+ "V. Sync. Width: %d\n",
+ info->DotClock,
+ info->PanelXRes, info->PanelYRes,
+ info->HBlank,
+ info->HOverPlus,
+ info->HSyncWidth,
+ info->VBlank, info->VOverPlus, info->VSyncWidth));
+ }
+
+ /* Detect connector type from BIOS, used for I2C/DDC qeurying EDID,
+ * Only available for VE or newer cards */
+
+ /* DELL OEM card doesn't seem to follow the conviention for BIOS's
+ * DDC type, we have to make a special case. Following hard coded
+ * type works with both CRT+CRT and DVI+DVI cases
+ */
+ if (info->IsDell && info->DellType == 2) {
+ if (info->IsSecondary)
+ info->DDCType = DDC_CRT2;
+ else
+ info->DDCType = DDC_DVI;
+ info->CloneDDCType = DDC_CRT2;
+ } else if ((tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) {
+ for (i = 1; i < 4; i++) {
+ unsigned int tmp0;
+ if (!RADEON_BIOS8(tmp + i*2) && i > 1) break;
+
+ /* Note: Secondary port (CRT port) actually uses primary DAC */
+ tmp0 = RADEON_BIOS16(tmp + i*2);
+ if (tmp0 & 0x01) {
+ if (!info->IsSecondary && !BypassSecondary)
+ info->DDCType = (tmp0 & 0x0f00) >> 8;
+ } else { /* Primary DAC */
+ if (info->Clone)
+ info->CloneDDCType = (tmp0 & 0x0f00) >> 8;
+ else if (info->IsSecondary ||
+ BypassSecondary ||
+ !info->HasCRTC2) {
+ info->DDCType = (tmp0 & 0x0f00) >> 8;
+ }
+ }
+ }
+ } else {
+ /* Orignal radeon cards, set it to DDC_VGA, this will not work
+ * with AIW, it should be DDC_DVI, let it fall back to VBE calls
+ * for AIW
+ */
+ info->DDCType = DDC_VGA;
+ }
+
+ return TRUE;
+}
+
+/* Read PLL parameters from BIOS block. Default to typical values if
+ * there is no BIOS.
+ */
+static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPLLPtr pll = &info->pll;
+ CARD16 bios_header;
+ CARD16 pll_info_block;
+
+ if (!info->VBIOS) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected, using default PLL parameters!\n");
+ /* These probably aren't going to work for
+ the card you are using. Specifically,
+ reference freq can be 29.50MHz,
+ 28.63MHz, or 14.32MHz. YMMV. */
+
+ /* These are somewhat sane defaults for Mac boards, we will need
+ * to find a good way of getting these from OpenFirmware
+ */
+ pll->reference_freq = 2700;
+ pll->reference_div = 67;
+ pll->min_pll_freq = 12500;
+ pll->max_pll_freq = 35000;
+ pll->xclk = 16615;
+ } else {
+ bios_header = RADEON_BIOS16(0x48);
+ pll_info_block = RADEON_BIOS16(bios_header + 0x30);
+ RADEONTRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
+ bios_header, pll_info_block));
+
+ pll->reference_freq = RADEON_BIOS16(pll_info_block + 0x0e);
+ pll->reference_div = RADEON_BIOS16(pll_info_block + 0x10);
+ pll->min_pll_freq = RADEON_BIOS32(pll_info_block + 0x12);
+ pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 0x16);
+ pll->xclk = RADEON_BIOS16(pll_info_block + 0x08);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
+ pll->reference_freq,
+ pll->reference_div,
+ pll->min_pll_freq,
+ pll->max_pll_freq,
+ pll->xclk);
+
+ return TRUE;
+}
+
+/* This is called by RADEONPreInit to set up the default visual */
+static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support32bppFb))
+ return FALSE;
+
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ break;
+
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by %s driver\n",
+ pScrn->depth, RADEON_DRIVER_NAME);
+ return FALSE;
+ }
+
+ xf86PrintDepthBpp(pScrn);
+
+ info->fifo_slots = 0;
+ info->pix24bpp = xf86GetBppFromDepth(pScrn,
+ pScrn->depth);
+ info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
+ info->CurrentLayout.depth = pScrn->depth;
+ info->CurrentLayout.pixel_bytes = pScrn->bitsPerPixel / 8;
+ info->CurrentLayout.pixel_code = (pScrn->bitsPerPixel != 16
+ ? pScrn->bitsPerPixel
+ : pScrn->depth);
+
+ if (info->pix24bpp == 24) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Radeon does NOT support 24bpp\n");
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
+ pScrn->depth,
+ info->CurrentLayout.pixel_bytes,
+ info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
+ info->pix24bpp);
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
+
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Default visual (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* This is called by RADEONPreInit to handle all color weight issues */
+static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ /* Save flag for 6 bit DAC to use for
+ setting CRTC registers. Otherwise use
+ an 8 bit DAC, even if xf86SetWeight sets
+ pScrn->rgbBits to some value other than
+ 8. */
+ info->dac6bits = FALSE;
+
+ if (pScrn->depth > 8) {
+ rgb defaultWeight = { 0, 0, 0 };
+
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
+ } else {
+ pScrn->rgbBits = 8;
+ if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) {
+ pScrn->rgbBits = 6;
+ info->dac6bits = TRUE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d bits per RGB (%d bit DAC)\n",
+ pScrn->rgbBits, info->dac6bits ? 6 : 8);
+
+ return TRUE;
+}
+
+/* This is called by RADEONPreInit to handle config file overrides for
+ * things like chipset and memory regions. Also determine memory size
+ * and type. If memory type ever needs an override, put it in this
+ * routine.
+ */
+static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ EntityInfoPtr pEnt = info->pEnt;
+ GDevPtr dev = pEnt->device;
+ int offset = 0; /* RAM Type */
+ MessageType from;
+ unsigned char *RADEONMMIO;
+
+ /* Chipset */
+ from = X_PROBED;
+ if (dev->chipset && *dev->chipset) {
+ info->Chipset = xf86StringToToken(RADEONChipsets, dev->chipset);
+ from = X_CONFIG;
+ } else if (dev->chipID >= 0) {
+ info->Chipset = dev->chipID;
+ from = X_CONFIG;
+ } else {
+ info->Chipset = info->PciInfo->chipType;
+ }
+
+ pScrn->chipset = (char *)xf86TokenToString(RADEONChipsets, info->Chipset);
+ if (!pScrn->chipset) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04x is not recognized\n", info->Chipset);
+ return FALSE;
+ }
+ if (info->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognized\n", pScrn->chipset);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Chipset: \"%s\" (ChipID = 0x%04x)\n",
+ pScrn->chipset,
+ info->Chipset);
+
+ info->HasCRTC2 = TRUE;
+ switch (info->Chipset) {
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ info->ChipFamily = CHIP_FAMILY_M6;
+ break;
+
+ case PCI_CHIP_RV100_QY:
+ case PCI_CHIP_RV100_QZ:
+ info->ChipFamily = CHIP_FAMILY_VE;
+ break;
+
+ case PCI_CHIP_R200_BB:
+ case PCI_CHIP_R200_QH:
+ case PCI_CHIP_R200_QI:
+ case PCI_CHIP_R200_QJ:
+ case PCI_CHIP_R200_QK:
+ case PCI_CHIP_R200_QL:
+ case PCI_CHIP_R200_QM:
+ case PCI_CHIP_R200_QN:
+ case PCI_CHIP_R200_QO:
+ case PCI_CHIP_R200_Qh:
+ case PCI_CHIP_R200_Qi:
+ case PCI_CHIP_R200_Qj:
+ case PCI_CHIP_R200_Qk:
+ case PCI_CHIP_R200_Ql:
+ info->ChipFamily = CHIP_FAMILY_R200;
+ break;
+
+ case PCI_CHIP_RV200_QW: /* RV200 desktop */
+ case PCI_CHIP_RV200_QX:
+ info->ChipFamily = CHIP_FAMILY_RV200;
+ break;
+
+ case PCI_CHIP_RADEON_LW:
+ case PCI_CHIP_RADEON_LX:
+ info->ChipFamily = CHIP_FAMILY_M7;
+ break;
+
+ case PCI_CHIP_RV250_Id:
+ case PCI_CHIP_RV250_Ie:
+ case PCI_CHIP_RV250_If:
+ case PCI_CHIP_RV250_Ig:
+ info->ChipFamily = CHIP_FAMILY_RV250;
+ break;
+
+ case PCI_CHIP_RV250_Ld:
+ case PCI_CHIP_RV250_Le:
+ case PCI_CHIP_RV250_Lf:
+ case PCI_CHIP_RV250_Lg:
+ info->ChipFamily = CHIP_FAMILY_M9;
+ break;
+
+ case PCI_CHIP_R300_AD:
+ case PCI_CHIP_R300_AE:
+ case PCI_CHIP_R300_AF:
+ case PCI_CHIP_R300_AG:
+ case PCI_CHIP_R300_ND:
+ case PCI_CHIP_R300_NE:
+ case PCI_CHIP_R300_NF:
+ case PCI_CHIP_R300_NG:
+ info->ChipFamily = CHIP_FAMILY_R300;
+ break;
+
+ default:
+ /* Original Radeon/7200 */
+ info->ChipFamily = CHIP_FAMILY_RADEON;
+ info->HasCRTC2 = FALSE;
+ }
+
+ /* Here is the special case for DELL's VE card.
+ * It needs some special handlings for it's 2nd head to work.
+ */
+ info->IsDell = FALSE;
+ if (info->ChipFamily == CHIP_FAMILY_VE &&
+ info->PciInfo->subsysVendor == PCI_VENDOR_ATI &&
+ info->PciInfo->subsysCard & (1 << 12)) { /* DELL's signature */
+ if (info->PciInfo->subsysCard & 0xb00) {
+ info->IsDell = TRUE;
+ info->DellType = 2; /* DVI+DVI config, this seems to be the
+ * only known type for now, can be
+ * connected to both DVI+DVI and VGA+VGA
+ * dongles.
+ */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "DELL OEM Card detected with %s (type %d)\n",
+ (info->DellType == 2) ? "DVI+DVI / VGA+VGA" : "VGA+VGA",
+ info->DellType);
+ } else {
+ info->DellType = 0; /* Unknown */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Unknown type of DELL's Card (SSCID %x), "
+ "treated as normal type\n",
+ info->PciInfo->subsysCard);
+ }
+ }
+
+ /* Framebuffer */
+
+ from = X_PROBED;
+ info->LinearAddr = info->PciInfo->memBase[0] & 0xfc000000;
+ pScrn->memPhysBase = info->LinearAddr;
+ if (dev->MemBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Linear address override, using 0x%08x instead of 0x%08x\n",
+ dev->MemBase,
+ info->LinearAddr);
+ info->LinearAddr = dev->MemBase;
+ from = X_CONFIG;
+ } else if (!info->LinearAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid linear framebuffer address\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
+
+ /* MMIO registers */
+ from = X_PROBED;
+ info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00;
+ if (dev->IOBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MMIO address override, using 0x%08x instead of 0x%08x\n",
+ dev->IOBase,
+ info->MMIOAddr);
+ info->MMIOAddr = dev->IOBase;
+ from = X_CONFIG;
+ } else if (!info->MMIOAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "MMIO registers at 0x%08lx\n", info->MMIOAddr);
+
+ /* BIOS */
+ from = X_PROBED;
+ info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000;
+ if (dev->BiosBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS address override, using 0x%08x instead of 0x%08x\n",
+ dev->BiosBase,
+ info->BIOSAddr);
+ info->BIOSAddr = dev->BiosBase;
+ from = X_CONFIG;
+ }
+ if (info->BIOSAddr) {
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "BIOS at 0x%08lx\n", info->BIOSAddr);
+ }
+
+ RADEONMapMMIO(pScrn);
+ RADEONMMIO = info->MMIO;
+
+ /* Read registers used to determine options */
+ from = X_PROBED;
+ if (info->FBDev)
+ pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024;
+ else
+ pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
+
+ /* Some production boards of m6 will return 0 if it's 8 MB */
+ if (pScrn->videoRam == 0) pScrn->videoRam = 8192;
+
+ if (info->IsSecondary) {
+ /* FIXME: For now, split FB into two equal sections. This should
+ * be able to be adjusted by user with a config option. */
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+ RADEONInfoPtr info1;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+ pScrn->videoRam /= 2;
+ pRADEONEnt->pPrimaryScrn->videoRam = pScrn->videoRam;
+
+ info1 = RADEONPTR(pRADEONEnt->pPrimaryScrn);
+ info1->FbMapSize = pScrn->videoRam * 1024;
+ info->LinearAddr += pScrn->videoRam * 1024;
+ info1->Clone = FALSE;
+ info1->CurCloneMode = NULL;
+ }
+
+ info->R300CGWorkaround =
+ (info->ChipFamily == CHIP_FAMILY_R300 &&
+ (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
+ == RADEON_CFG_ATI_REV_A11);
+
+ info->MemCntl = INREG(RADEON_SDRAM_MODE_REG);
+ info->BusCntl = INREG(RADEON_BUS_CNTL);
+ RADEONMMIO = NULL;
+ RADEONUnmapMMIO(pScrn);
+
+ /* RAM */
+ switch (info->MemCntl >> 30) {
+ case 0: offset = 0; break; /* 64-bit SDR SDRAM */
+ case 1: offset = 1; break; /* 64-bit DDR SDRAM */
+ default: offset = 0;
+ }
+ info->ram = &RADEONRAM[offset];
+
+ if (dev->videoRam) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Video RAM override, using %d kB instead of %d kB\n",
+ dev->videoRam,
+ pScrn->videoRam);
+ from = X_CONFIG;
+ pScrn->videoRam = dev->videoRam;
+ }
+ pScrn->videoRam &= ~1023;
+ info->FbMapSize = pScrn->videoRam * 1024;
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
+
+#ifdef XF86DRI
+ /* AGP/PCI */
+ if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
+ info->IsPCI = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
+ } else {
+ switch (info->Chipset) {
+#if 0
+ case PCI_CHIP_RADEON_XX: info->IsPCI = TRUE; break;
+#endif
+ case PCI_CHIP_RV100_QY:
+ case PCI_CHIP_RV100_QZ:
+ case PCI_CHIP_RADEON_LW:
+ case PCI_CHIP_RADEON_LX:
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ case PCI_CHIP_RADEON_QD:
+ case PCI_CHIP_RADEON_QE:
+ case PCI_CHIP_RADEON_QF:
+ case PCI_CHIP_RADEON_QG:
+ case PCI_CHIP_R200_BB:
+ case PCI_CHIP_R200_QH:
+ case PCI_CHIP_R200_QI:
+ case PCI_CHIP_R200_QJ:
+ case PCI_CHIP_R200_QK:
+ case PCI_CHIP_R200_QL:
+ case PCI_CHIP_R200_QM:
+ case PCI_CHIP_R200_QN:
+ case PCI_CHIP_R200_QO:
+ case PCI_CHIP_R200_Qh:
+ case PCI_CHIP_R200_Qi:
+ case PCI_CHIP_R200_Qj:
+ case PCI_CHIP_R200_Qk:
+ case PCI_CHIP_R200_Ql:
+ case PCI_CHIP_RV200_QW:
+ case PCI_CHIP_RV200_QX:
+ case PCI_CHIP_RV250_Id:
+ case PCI_CHIP_RV250_Ie:
+ case PCI_CHIP_RV250_If:
+ case PCI_CHIP_RV250_Ig:
+ case PCI_CHIP_RV250_Ld:
+ case PCI_CHIP_RV250_Le:
+ case PCI_CHIP_RV250_Lf:
+ case PCI_CHIP_RV250_Lg:
+ case PCI_CHIP_R300_AD:
+ case PCI_CHIP_R300_AE:
+ case PCI_CHIP_R300_AF:
+ case PCI_CHIP_R300_AG:
+ case PCI_CHIP_R300_ND:
+ case PCI_CHIP_R300_NE:
+ case PCI_CHIP_R300_NF:
+ case PCI_CHIP_R300_NG:
+ default: info->IsPCI = FALSE; break;
+ }
+ }
+#endif
+
+ return TRUE;
+}
+
+static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long val;
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ /* Get the result */
+ val = INREG(info->DDCReg);
+
+ *Clock = (val & RADEON_GPIO_Y_1) != 0;
+ *data = (val & RADEON_GPIO_Y_0) != 0;
+}
+
+static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long val;
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1);
+ val |= (Clock ? 0:RADEON_GPIO_EN_1);
+ val |= (data ? 0:RADEON_GPIO_EN_0);
+ OUTREG(info->DDCReg, val);
+}
+
+static Bool RADEONI2cInit(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ info->pI2CBus = xf86CreateI2CBusRec();
+ if (!info->pI2CBus) return FALSE;
+
+ info->pI2CBus->BusName = "DDC";
+ info->pI2CBus->scrnIndex = pScrn->scrnIndex;
+ info->pI2CBus->I2CPutBits = RADEONI2CPutBits;
+ info->pI2CBus->I2CGetBits = RADEONI2CGetBits;
+ info->pI2CBus->AcknTimeout = 5;
+
+ switch (info->DDCType) {
+ case DDC_MONID:
+ info->DDCReg = RADEON_GPIO_MONID;
+ break;
+ case DDC_DVI:
+ info->DDCReg = RADEON_GPIO_DVI_DDC;
+ break;
+ case DDC_VGA:
+ info->DDCReg = RADEON_GPIO_VGA_DDC;
+ break;
+ case DDC_CRT2:
+ info->DDCReg = RADEON_GPIO_CRT2_DDC;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!xf86I2CBusInit(info->pI2CBus)) return FALSE;
+ return TRUE;
+}
+
+static void RADEONPreInitDDC(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ /* vbeInfoPtr pVbe; */
+
+ info->ddc1 = FALSE;
+ info->ddc_bios = FALSE;
+ if (!xf86LoadSubModule(pScrn, "ddc")) {
+ info->ddc2 = FALSE;
+ } else {
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+ info->ddc2 = TRUE;
+ }
+
+ /* DDC can use I2C bus */
+ /* Load I2C if we have the code to use it */
+ if (info->ddc2) {
+ if (xf86LoadSubModule(pScrn, "i2c")) {
+ xf86LoaderReqSymLists(i2cSymbols,NULL);
+ info->ddc2 = RADEONI2cInit(pScrn);
+ }
+ else info->ddc2 = FALSE;
+ }
+}
+
+static xf86MonPtr RADEONDoDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86MonPtr MonInfo = NULL;
+ unsigned char *RADEONMMIO;
+ int i;
+
+ /* We'll use DDC2, BIOS EDID can only detect the monitor connected
+ * to one port. For VE, BIOS EDID detects the monitor connected to
+ * DVI port by default. If no monitor their, it will try CRT port
+ */
+
+ /* Read and output monitor info using DDC2 over I2C bus */
+ if (info->pI2CBus && info->ddc2) {
+ int j;
+
+ if (!RADEONMapMMIO(pScrn)) return NULL;
+ RADEONMMIO = info->MMIO;
+ OUTREG(info->DDCReg, INREG(info->DDCReg) &
+ (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
+
+ /* For some old monitors (like Compaq Presario FP500), we need
+ * following process to initialize/stop DDC
+ */
+ OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1));
+ for (j = 0; j < 3; j++) {
+ OUTREG(info->DDCReg,
+ INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0));
+ usleep(13000);
+
+ OUTREG(info->DDCReg,
+ INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1));
+ for (i = 0; i < 10; i++) {
+ usleep(15000);
+ if (INREG(info->DDCReg) & RADEON_GPIO_Y_1)
+ break;
+ }
+ if (i == 10) continue;
+
+ usleep(15000);
+
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0);
+ usleep(15000);
+
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1);
+ usleep(15000);
+ OUTREG(info->DDCReg,
+ INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0));
+ usleep(15000);
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus);
+
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1);
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0);
+ usleep(15000);
+ OUTREG(info->DDCReg,
+ INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1));
+ for (i = 0; i < 50; i++) {
+ usleep(15000);
+ if (INREG(info->DDCReg) & RADEON_GPIO_Y_1)
+ break;
+ }
+ usleep(15000);
+ OUTREG(info->DDCReg,
+ INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0));
+ usleep(15000);
+
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1);
+ OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0);
+ usleep(15000);
+ if (MonInfo)
+ break;
+ }
+
+ RADEONUnmapMMIO(pScrn);
+ }
+
+ if (!MonInfo && pInt10 && (info->DDCReg == RADEON_GPIO_VGA_DDC)) {
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ vbeInfoPtr pVbe;
+ pVbe = VBEInit(pInt10, info->pEnt->index);
+ if (pVbe) {
+ for (i = 0; i < 5; i++) {
+ MonInfo = vbeDoEDID(pVbe, NULL);
+ info->ddc_bios = TRUE;
+ if (MonInfo)
+ break;
+ }
+ } else
+ info->ddc_bios = FALSE;
+ }
+ }
+
+ if (MonInfo) {
+ if (info->ddc2)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C EDID Info:\n");
+ else if (info->ddc_bios)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS EDID Info:\n");
+ else return NULL;
+
+ xf86PrintEDID(MonInfo);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of DDC Monitor info\n\n");
+
+ xf86SetDDCproperties(pScrn, MonInfo);
+ return MonInfo;
+ }
+ else return NULL;
+}
+
+/* BIOS may not have right panel size, we search through all supported
+ * DDC modes looking for the maximum panel size.
+ */
+static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn)
+{
+ int j;
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ xf86MonPtr ddc = pScrn->monitor->DDC;
+ DisplayModePtr p;
+
+ /* Go thru detailed timing table first */
+ for (j = 0; j < 4; j++) {
+ if (ddc->det_mon[j].type == 0) {
+ struct detailed_timings *d_timings =
+ &ddc->det_mon[j].section.d_timings;
+ if (info->PanelXRes < d_timings->h_active &&
+ info->PanelYRes < d_timings->v_active) {
+
+ info->PanelXRes = d_timings->h_active;
+ info->PanelYRes = d_timings->v_active;
+ info->DotClock = d_timings->clock / 1000;
+ info->HOverPlus = d_timings->h_sync_off;
+ info->HSyncWidth = d_timings->h_sync_width;
+ info->HBlank = d_timings->h_blanking;
+ info->VOverPlus = d_timings->v_sync_off;
+ info->VSyncWidth = d_timings->v_sync_width;
+ info->VBlank = d_timings->v_blanking;
+ }
+ }
+ }
+
+ /* Search thru standard VESA modes from EDID */
+ for (j = 0; j < 8; j++) {
+ if ((info->PanelXRes < ddc->timings2[j].hsize) &&
+ (info->PanelYRes < ddc->timings2[j].vsize)) {
+ for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+ if ((ddc->timings2[j].hsize == p->HDisplay) &&
+ (ddc->timings2[j].vsize == p->VDisplay)) {
+ float refresh =
+ (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
+
+ if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) {
+ /* Is this good enough? */
+ info->PanelXRes = ddc->timings2[j].hsize;
+ info->PanelYRes = ddc->timings2[j].vsize;
+ info->HBlank = p->HTotal - p->HDisplay;
+ info->HOverPlus = p->HSyncStart - p->HDisplay;
+ info->HSyncWidth = p->HSyncEnd - p->HSyncStart;
+ info->VBlank = p->VTotal - p->VDisplay;
+ info->VOverPlus = p->VSyncStart - p->VDisplay;
+ info->VSyncWidth = p->VSyncEnd - p->VSyncStart;
+ info->DotClock = p->Clock;
+ info->Flags =
+ (ddc->det_mon[j].section.d_timings.interlaced
+ ? V_INTERLACE
+ : 0);
+ if (ddc->det_mon[j].section.d_timings.sync == 3) {
+ switch (ddc->det_mon[j].section.d_timings.misc) {
+ case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break;
+ case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break;
+ case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break;
+ case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size found from DDC: %dx%d\n",
+ info->PanelXRes, info->PanelYRes);
+}
+
+/* This function will sort all modes according to their resolution.
+ * Highest resolution first.
+ */
+static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first,
+ DisplayModePtr *last)
+{
+ DisplayModePtr p;
+
+ p = *last;
+ while (p) {
+ if ((((*new)->HDisplay < p->HDisplay) &&
+ ((*new)->VDisplay < p->VDisplay)) ||
+ (((*new)->HDisplay == p->HDisplay) &&
+ ((*new)->VDisplay == p->VDisplay) &&
+ ((*new)->Clock < p->Clock))) {
+
+ if (p->next) p->next->prev = *new;
+ (*new)->prev = p;
+ (*new)->next = p->next;
+ p->next = *new;
+ if (!((*new)->next)) *last = *new;
+ break;
+ }
+ if (!p->prev) {
+ (*new)->prev = NULL;
+ (*new)->next = p;
+ p->prev = *new;
+ *first = *new;
+ break;
+ }
+ p = p->prev;
+ }
+
+ if (!*first) {
+ *first = *new;
+ (*new)->prev = NULL;
+ (*new)->next = NULL;
+ *last = *new;
+ }
+}
+
+static void RADEONSetPitch (ScrnInfoPtr pScrn)
+{
+ int dummy = pScrn->virtualX;
+
+ /* FIXME: May need to validate line pitch here */
+ switch (pScrn->depth / 8) {
+ case 1: dummy = (pScrn->virtualX + 127) & ~127; break;
+ case 2: dummy = (pScrn->virtualX + 31) & ~31; break;
+ case 3:
+ case 4: dummy = (pScrn->virtualX + 15) & ~15; break;
+ }
+ pScrn->displayWidth = dummy;
+}
+
+/* When no mode provided in config file, this will add all modes supported in
+ * DDC date the pScrn->modes list
+ */
+static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn)
+{
+ DisplayModePtr p;
+ DisplayModePtr last = NULL;
+ DisplayModePtr new = NULL;
+ DisplayModePtr first = NULL;
+ int count = 0;
+ int j, tmp;
+ char stmp[32];
+ xf86MonPtr ddc = pScrn->monitor->DDC;
+
+ /* Go thru detailed timing table first */
+ for (j = 0; j < 4; j++) {
+ if (ddc->det_mon[j].type == 0) {
+ struct detailed_timings *d_timings =
+ &ddc->det_mon[j].section.d_timings;
+
+ if (d_timings->h_active == 0 || d_timings->v_active == 0) break;
+
+ new = xnfcalloc(1, sizeof (DisplayModeRec));
+ memset(new, 0, sizeof (DisplayModeRec));
+
+ new->HDisplay = d_timings->h_active;
+ new->VDisplay = d_timings->v_active;
+
+ sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay);
+ new->name = xnfalloc(strlen(stmp) + 1);
+ strcpy(new->name, stmp);
+
+ new->HTotal = new->HDisplay + d_timings->h_blanking;
+ new->HSyncStart = new->HDisplay + d_timings->h_sync_off;
+ new->HSyncEnd = new->HSyncStart + d_timings->h_sync_width;
+ new->VTotal = new->VDisplay + d_timings->v_blanking;
+ new->VSyncStart = new->VDisplay + d_timings->v_sync_off;
+ new->VSyncEnd = new->VSyncStart + d_timings->v_sync_width;
+ new->Clock = d_timings->clock / 1000;
+ new->Flags = (d_timings->interlaced ? V_INTERLACE : 0);
+ new->status = MODE_OK;
+ new->type = M_T_DEFAULT;
+
+ if (d_timings->sync == 3) {
+ switch (d_timings->misc) {
+ case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break;
+ case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break;
+ case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break;
+ case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break;
+ }
+ }
+ count++;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid Mode from Detailed timing table: %s\n",
+ new->name);
+
+ RADEONSortModes(&new, &first, &last);
+ }
+ }
+
+ /* Search thru standard VESA modes from EDID */
+ for (j = 0; j < 8; j++) {
+ for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+ /* Ignore all double scan modes */
+ if ((ddc->timings2[j].hsize == p->HDisplay) &&
+ (ddc->timings2[j].vsize == p->VDisplay)) {
+ float refresh =
+ (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
+
+ if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) {
+ /* Is this good enough? */
+ new = xnfcalloc(1, sizeof (DisplayModeRec));
+ memcpy(new, p, sizeof(DisplayModeRec));
+ new->name = xnfalloc(strlen(p->name) + 1);
+ strcpy(new->name, p->name);
+ new->status = MODE_OK;
+ new->type = M_T_DEFAULT;
+
+ count++;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid Mode from standard timing table: %s\n",
+ new->name);
+
+ RADEONSortModes(&new, &first, &last);
+ break;
+ }
+ }
+ }
+ }
+
+ /* Search thru established modes from EDID */
+ tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2;
+ for (j = 0; j < 16; j++) {
+ if (tmp & (1 << j)) {
+ for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
+ if ((est_timings[j].hsize == p->HDisplay) &&
+ (est_timings[j].vsize == p->VDisplay)) {
+ float refresh =
+ (float)p->Clock * 1000.0 / p->HTotal / p->VTotal;
+
+ if (abs((float)est_timings[j].refresh - refresh) < 1.0) {
+ /* Is this good enough? */
+ new = xnfcalloc(1, sizeof (DisplayModeRec));
+ memcpy(new, p, sizeof(DisplayModeRec));
+ new->name = xnfalloc(strlen(p->name) + 1);
+ strcpy(new->name, p->name);
+ new->status = MODE_OK;
+ new->type = M_T_DEFAULT;
+
+ count++;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid Mode from established timing "
+ "table: %s\n", new->name);
+
+ RADEONSortModes(&new, &first, &last);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Total of %d mode(s) found.\n", count);
+
+ return first;
+}
+
+/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes,
+ * so here is our own validation routine.
+ */
+static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName,
+ RADEONMonitorType DisplayType)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DisplayModePtr p;
+ DisplayModePtr last = NULL;
+ DisplayModePtr first = NULL;
+ DisplayModePtr ddcModes = NULL;
+ int count = 0;
+ int i, width, height;
+
+ pScrn->virtualX = pScrn->display->virtualX;
+ pScrn->virtualY = pScrn->display->virtualY;
+
+ if (pScrn->monitor->DDC) {
+ int maxVirtX = pScrn->virtualX;
+ int maxVirtY = pScrn->virtualY;
+
+ if (DisplayType != MT_CRT) {
+ /* The panel size we collected from BIOS may not be the
+ * maximum size supported by the panel. If not, we update
+ * it now. These will be used if no matching mode can be
+ * found from EDID data.
+ */
+ RADEONUpdatePanelSize(pScrn);
+ }
+
+ /* Collect all of the DDC modes */
+ first = last = ddcModes = RADEONDDCModes(pScrn);
+
+ for (p = ddcModes; p; p = p->next) {
+
+ /* If primary head is a flat panel, use RMX by default */
+ if ((!info->IsSecondary && DisplayType != MT_CRT) &&
+ !info->ddc_mode) {
+ /* These values are effective values after expansion.
+ * They are not really used to set CRTC registers.
+ */
+ p->HTotal = info->PanelXRes + info->HBlank;
+ p->HSyncStart = info->PanelXRes + info->HOverPlus;
+ p->HSyncEnd = p->HSyncStart + info->HSyncWidth;
+ p->VTotal = info->PanelYRes + info->VBlank;
+ p->VSyncStart = info->PanelYRes + info->VOverPlus;
+ p->VSyncEnd = p->VSyncStart + info->VSyncWidth;
+ p->Clock = info->DotClock;
+
+ p->Flags |= RADEON_USE_RMX;
+ }
+
+ maxVirtX = MAX(maxVirtX, p->HDisplay);
+ maxVirtY = MAX(maxVirtY, p->VDisplay);
+ count++;
+
+ last = p;
+ }
+
+ /* Match up modes that are specified in the XF86Config file */
+ if (ppModeName[0]) {
+ DisplayModePtr next;
+
+ /* Reset the max virtual dimensions */
+ maxVirtX = pScrn->virtualX;
+ maxVirtY = pScrn->virtualY;
+
+ /* Reset list */
+ first = last = NULL;
+
+ for (i = 0; ppModeName[i]; i++) {
+ /* FIXME: Use HDisplay and VDisplay instead of mode string */
+ if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) {
+ for (p = ddcModes; p; p = next) {
+ next = p->next;
+
+ if (p->HDisplay == width && p->VDisplay == height) {
+ /* We found a DDC mode that matches the one
+ requested in the XF86Config file */
+ p->type |= M_T_USERDEF;
+
+ /* Update the max virtual setttings */
+ maxVirtX = MAX(maxVirtX, width);
+ maxVirtY = MAX(maxVirtY, height);
+
+ /* Unhook from DDC modes */
+ if (p->prev) p->prev->next = p->next;
+ if (p->next) p->next->prev = p->prev;
+ if (p == ddcModes) ddcModes = p->next;
+
+ /* Add to used modes */
+ if (last) {
+ last->next = p;
+ p->prev = last;
+ } else {
+ first = p;
+ p->prev = NULL;
+ }
+ p->next = NULL;
+ last = p;
+
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Add remaining DDC modes if they're smaller than the user
+ * specified modes
+ */
+ for (p = ddcModes; p; p = next) {
+ next = p->next;
+ if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) {
+ /* Unhook from DDC modes */
+ if (p->prev) p->prev->next = p->next;
+ if (p->next) p->next->prev = p->prev;
+ if (p == ddcModes) ddcModes = p->next;
+
+ /* Add to used modes */
+ if (last) {
+ last->next = p;
+ p->prev = last;
+ } else {
+ first = p;
+ p->prev = NULL;
+ }
+ p->next = NULL;
+ last = p;
+ }
+ }
+
+ /* Delete unused modes */
+ while (ddcModes)
+ xf86DeleteMode(&ddcModes, ddcModes);
+ } else {
+ /*
+ * No modes were configured, so we make the DDC modes
+ * available for the user to cycle through.
+ */
+ for (p = ddcModes; p; p = p->next)
+ p->type |= M_T_USERDEF;
+ }
+
+ pScrn->virtualX = pScrn->display->virtualX = maxVirtX;
+ pScrn->virtualY = pScrn->display->virtualY = maxVirtY;
+ }
+
+ /* Close the doubly-linked mode list, if we found any usable modes */
+ if (last) {
+ last->next = first;
+ first->prev = last;
+ pScrn->modes = first;
+ RADEONSetPitch(pScrn);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Total number of valid DDC mode(s) found: %d\n", count);
+
+ return count;
+}
+
+/* This is used only when no mode is specified for FP and no ddc is
+ * available. We force it to native mode, if possible.
+ */
+static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DisplayModePtr new = NULL;
+ char stmp[32];
+
+ if (info->PanelXRes != 0 &&
+ info->PanelYRes != 0 &&
+ info->DotClock != 0) {
+
+ /* Add native panel size */
+ new = xnfcalloc(1, sizeof (DisplayModeRec));
+ sprintf(stmp, "%dx%d", info->PanelXRes, info->PanelYRes);
+ new->name = xnfalloc(strlen(stmp) + 1);
+ strcpy(new->name, stmp);
+ new->HDisplay = info->PanelXRes;
+ new->VDisplay = info->PanelYRes;
+
+ new->HTotal = new->HDisplay + info->HBlank;
+ new->HSyncStart = new->HDisplay + info->HOverPlus;
+ new->HSyncEnd = new->HSyncStart + info->HSyncWidth;
+ new->VTotal = new->VDisplay + info->VBlank;
+ new->VSyncStart = new->VDisplay + info->VOverPlus;
+ new->VSyncEnd = new->VSyncStart + info->VSyncWidth;
+
+ new->Clock = info->DotClock;
+ new->Flags = 0;
+ new->type = M_T_USERDEF;
+
+ new->next = NULL;
+ new->prev = NULL;
+
+ pScrn->display->virtualX =
+ pScrn->virtualX = MAX(pScrn->virtualX, info->PanelXRes);
+ pScrn->display->virtualY =
+ pScrn->virtualY = MAX(pScrn->virtualY, info->PanelYRes);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No valid mode specified, force to native mdoe\n");
+ }
+
+ return new;
+}
+
+/* XFree86's xf86ValidateModes routine doesn't work well with DFPs, so
+ * here is our own validation routine.
+ */
+static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DisplayModePtr last = NULL;
+ DisplayModePtr new = NULL;
+ DisplayModePtr first = NULL;
+ int count = 0;
+ int i, width, height;
+
+ pScrn->virtualX = pScrn->display->virtualX;
+ pScrn->virtualY = pScrn->display->virtualY;
+
+ /* We have a flat panel connected to the primary display, and we
+ * don't have any DDC info.
+ */
+ for (i = 0; ppModeName[i] != NULL; i++) {
+ /* FIXME: Use HDisplay and VDisplay instead of mode string */
+ if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) continue;
+
+ /* Note: We allow all non-standard modes as long as they do not
+ * exceed the native resolution of the panel. Since these modes
+ * need the internal RMX unit in the video chips (and there is
+ * only one per card), this will only apply to the primary head.
+ */
+ if (width < 320 || width > info->PanelXRes ||
+ height < 200 || height > info->PanelYRes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode %s is out of range.\n", ppModeName[i]);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Valid modes must be between 320x200-%dx%d\n",
+ info->PanelXRes, info->PanelYRes);
+ continue;
+ }
+
+ new = xnfcalloc(1, sizeof(DisplayModeRec));
+ new->name = xnfalloc(strlen(ppModeName[i]) + 1);
+ strcpy(new->name, ppModeName[i]);
+ new->HDisplay = width;
+ new->VDisplay = height;
+
+ /* These values are effective values after expansion They are
+ * not really used to set CRTC registers.
+ */
+ new->HTotal = info->PanelXRes + info->HBlank;
+ new->HSyncStart = info->PanelXRes + info->HOverPlus;
+ new->HSyncEnd = new->HSyncStart + info->HSyncWidth;
+ new->VTotal = info->PanelYRes + info->VBlank;
+ new->VSyncStart = info->PanelYRes + info->VOverPlus;
+ new->VSyncEnd = new->VSyncStart + info->VSyncWidth;
+ new->Clock = info->DotClock;
+ new->Flags |= RADEON_USE_RMX;
+
+ new->type |= M_T_USERDEF;
+
+ new->next = NULL;
+ new->prev = last;
+
+ if (last) last->next = new;
+ last = new;
+ if (!first) first = new;
+
+ pScrn->display->virtualX =
+ pScrn->virtualX = MAX(pScrn->virtualX, width);
+ pScrn->display->virtualY =
+ pScrn->virtualY = MAX(pScrn->virtualY, height);
+ count++;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid mode using on-chip RMX: %s\n", new->name);
+ }
+
+ /* If all else fails, add the native mode */
+ if (!count) {
+ first = last = RADEONFPNativeMode(pScrn);
+ if (first) count = 1;
+ }
+
+ /* Close the doubly-linked mode list, if we found any usable modes */
+ if (last) {
+ last->next = first;
+ first->prev = last;
+ pScrn->modes = first;
+ RADEONSetPitch(pScrn);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Total number of valid FP mode(s) found: %d\n", count);
+
+ return count;
+}
+
+/* This is called by RADEONPreInit to initialize gamma correction */
+static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn)
+{
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros)) return FALSE;
+ return TRUE;
+}
+
+static void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
+{
+ MonPtr mon = pScrn->monitor;
+ xf86MonPtr ddc = mon->DDC;
+ int i;
+
+ if (flag) { /* HSync */
+ for (i = 0; i < 4; i++) {
+ if (ddc->det_mon[i].type == DS_RANGES) {
+ mon->nHsync = 1;
+ mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h;
+ mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h;
+ return;
+ }
+ }
+ /* If no sync ranges detected in detailed timing table, let's
+ * try to derive them from supported VESA modes. Are we doing
+ * too much here!!!? */
+ i = 0;
+ if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */
+ mon->hsync[i].lo = mon->hsync[i].hi = 35.2;
+ i++;
+ }
+ if (ddc->timings1.t1 & 0x04) { /* 640x480@75 */
+ mon->hsync[i].lo = mon->hsync[i].hi = 37.5;
+ i++;
+ }
+ if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 37.9;
+ i++;
+ }
+ if (ddc->timings1.t2 & 0x40) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 46.9;
+ i++;
+ }
+ if ((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 48.1;
+ i++;
+ }
+ if (ddc->timings1.t2 & 0x04) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 56.5;
+ i++;
+ }
+ if (ddc->timings1.t2 & 0x02) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 60.0;
+ i++;
+ }
+ if (ddc->timings1.t2 & 0x01) {
+ mon->hsync[i].lo = mon->hsync[i].hi = 64.0;
+ i++;
+ }
+ mon->nHsync = i;
+ } else { /* Vrefresh */
+ for (i = 0; i < 4; i++) {
+ if (ddc->det_mon[i].type == DS_RANGES) {
+ mon->nVrefresh = 1;
+ mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v;
+ mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v;
+ return;
+ }
+ }
+
+ i = 0;
+ if (ddc->timings1.t1 & 0x02) { /* 800x600@56 */
+ mon->vrefresh[i].lo = mon->vrefresh[i].hi = 56;
+ i++;
+ }
+ if ((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) {
+ mon->vrefresh[i].lo = mon->vrefresh[i].hi = 60;
+ i++;
+ }
+ if (ddc->timings1.t2 & 0x04) {
+ mon->vrefresh[i].lo = mon->vrefresh[i].hi = 70;
+ i++;
+ }
+ if ((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) {
+ mon->vrefresh[i].lo = mon->vrefresh[i].hi = 72;
+ i++;
+ }
+ if ((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) ||
+ (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) {
+ mon->vrefresh[i].lo = mon->vrefresh[i].hi = 75;
+ i++;
+ }
+ mon->nVrefresh = i;
+ }
+}
+
+static int RADEONValidateCloneModes(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ClockRangePtr clockRanges;
+ DisplayModePtr tmp_mode = NULL;
+ DisplayModePtr clone_mode, save_mode;
+ int modesFound = 0;
+ int count = 0;
+ int tmp_hdisplay = 0;
+ int tmp_vdisplay = 0;
+ int i, save_n_hsync, save_n_vrefresh;
+ range save_hsync, save_vrefresh;
+ char *s;
+ char **clone_mode_names = NULL;
+ Bool ddc_mode = info->ddc_mode;
+
+ /* Save all infomations that will be changed by clone mode validateion */
+ save_mode = pScrn->modes;
+ pScrn->modes = NULL;
+
+ /* Clone display mode names, duplicate all mode names for primary
+ * head. Allocate one more, in case pScrn->display->modes[0] ==
+ * NULL */
+ while (pScrn->display->modes[count]) count++;
+ clone_mode_names = xnfalloc((count+2) * sizeof(char*));
+ for (i = 0; i < count; i++) {
+ clone_mode_names[i] = xnfalloc(strlen(pScrn->display->modes[i]) + 1);
+ strcpy(clone_mode_names[i], pScrn->display->modes[i]);
+ }
+ clone_mode_names[count] = NULL;
+ clone_mode_names[count+1] = NULL;
+
+ pScrn->progClock = TRUE;
+
+ clockRanges = xnfcalloc(sizeof(*clockRanges), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = info->pll.min_pll_freq;
+ clockRanges->maxClock = info->pll.max_pll_freq * 10;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = FALSE;
+ clockRanges->doubleScanAllowed = FALSE;
+
+ /* Only take one clone mode from config file for now, rest of clone
+ * modes will copy from primary head.
+ */
+ if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_MODE))) {
+ if (sscanf(s, "%dx%d", &tmp_hdisplay, &tmp_vdisplay) == 2) {
+ if(count > 0) free(clone_mode_names[0]);
+ else count++;
+ clone_mode_names[0] = xnfalloc(strlen(s)+1);
+ sprintf(clone_mode_names[0], "%dx%d", tmp_hdisplay, tmp_vdisplay);
+ xf86DrvMsg(0, X_INFO, "Clone mode %s in config file is used\n");
+ }
+ }
+
+ if (pScrn->display->virtualX < tmp_hdisplay)
+ pScrn->display->virtualX = tmp_hdisplay;
+ if (pScrn->display->virtualY < tmp_vdisplay)
+ pScrn->display->virtualY = tmp_vdisplay;
+
+ save_hsync = pScrn->monitor->hsync[0];
+ save_vrefresh = pScrn->monitor->vrefresh[0];
+ save_n_hsync = pScrn->monitor->nHsync;
+ save_n_vrefresh = pScrn->monitor->nVrefresh;
+
+ pScrn->monitor->DDC = NULL;
+ pScrn->monitor->nHsync = 0;
+ pScrn->monitor->nVrefresh = 0;
+
+ if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_HSYNC))) {
+ if (sscanf(s, "%f-%f", &pScrn->monitor->hsync[0].lo,
+ &pScrn->monitor->hsync[0].hi) == 2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "HSync for CloneMode from config file: %s\n", s);
+ pScrn->monitor->nHsync = 1;
+ } else {
+ pScrn->monitor->nHsync = 0;
+ }
+ }
+
+ if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_VREFRESH))) {
+ if (sscanf(s, "%f-%f", &pScrn->monitor->vrefresh[0].lo,
+ &pScrn->monitor->vrefresh[0].hi) == 2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "VRefresh for CloneMode from config file: %s\n", s);
+ pScrn->monitor->nVrefresh = 1;
+ } else {
+ pScrn->monitor->nVrefresh = 0;
+ }
+ }
+
+ if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0) ||
+ (info->CloneType != MT_CRT) || info->ddc_mode) {
+ unsigned int save_ddc_reg;
+ save_ddc_reg = info->DDCReg;
+ switch (info->CloneDDCType) {
+ case DDC_MONID: info->DDCReg = RADEON_GPIO_MONID; break;
+ case DDC_DVI: info->DDCReg = RADEON_GPIO_DVI_DDC; break;
+ case DDC_VGA: info->DDCReg = RADEON_GPIO_VGA_DDC; break;
+ case DDC_CRT2: info->DDCReg = RADEON_GPIO_CRT2_DDC; break;
+ default: info->DDCReg = 0; break;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "DDC detection (type %d) for clone modes\n",
+ info->CloneDDCType);
+
+ /* When primary head has an invalid DDC type, I2C is not
+ * initialized, so we do it here.
+ */
+ if (!info->ddc2) info->ddc2 = xf86I2CBusInit(info->pI2CBus);
+
+ pScrn->monitor->DDC = RADEONDoDDC(pScrn, NULL);
+ if (pScrn->monitor->DDC) {
+ if (info->CloneType == MT_CRT) {
+ if (pScrn->monitor->nHsync == 0)
+ RADEONSetSyncRangeFromEdid(pScrn, 1);
+ if (pScrn->monitor->nVrefresh == 0)
+ RADEONSetSyncRangeFromEdid(pScrn, 0);
+ }
+ } else if (info->ddc_mode) {
+ ddc_mode = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No DDC data available for clone mode, "
+ "DDCMode option is dismissed\n");
+ }
+ info->DDCReg = save_ddc_reg;
+ }
+
+ if (info->CloneType == MT_CRT && !ddc_mode) {
+ modesFound =
+ xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ clone_mode_names,
+ clockRanges,
+ NULL, /* linePitches */
+ 8 * 64, /* minPitch */
+ 8 * 1024, /* maxPitch */
+ 64 * pScrn->bitsPerPixel, /* pitchInc */
+ 128, /* minHeight */
+ 2048, /* maxHeight */
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ info->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+ } else {
+ /* Try to add DDC modes */
+ info->IsSecondary = TRUE; /* Fake it */
+ modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names,
+ info->CloneType);
+ info->IsSecondary = FALSE; /* Restore it!!! */
+
+ /* If that fails and we're connect to a flat panel, then try to
+ * add the flat panel modes
+ */
+ if (modesFound < 1 && info->DisplayType != MT_CRT)
+ modesFound = RADEONValidateFPModes(pScrn, clone_mode_names);
+ }
+
+ if (modesFound > 0) {
+ xf86SetCrtcForModes(pScrn, 0);
+ xf86PrintModes(pScrn);
+ for (i = 0; i < modesFound; i++) {
+ while (pScrn->modes->status != MODE_OK) {
+ pScrn->modes = pScrn->modes->next;
+ }
+ if (!pScrn->modes) break;
+
+ clone_mode = xnfcalloc (1, sizeof (DisplayModeRec));
+ if (!clone_mode || !pScrn->modes) break;
+ memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec));
+ clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1);
+ strcpy(clone_mode->name, pScrn->modes->name);
+
+ if (i == 0) {
+ info->CloneModes = clone_mode;
+ info->CurCloneMode = clone_mode;
+ } else {
+ clone_mode->prev = tmp_mode;
+ clone_mode->prev->next = clone_mode;
+ }
+
+ tmp_mode = clone_mode;
+ clone_mode->next = NULL;
+ pScrn->modes = pScrn->modes->next;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid Clone Mode: %s\n", clone_mode->name);
+ }
+ }
+
+ /* Clone_mode_names list is no longer needed, free it. */
+ if (clone_mode_names) {
+ for (i = 0; clone_mode_names[i]; i++) {
+ free(clone_mode_names[i]);
+ clone_mode_names[i] = NULL;
+ }
+
+ free(clone_mode_names);
+ clone_mode_names = NULL;
+ }
+
+ /* We need to restore all changed info for the primary head */
+ pScrn->modes = save_mode;
+
+ pScrn->monitor->hsync[0] = save_hsync;
+ pScrn->monitor->vrefresh[0] = save_vrefresh;
+ pScrn->monitor->nHsync = save_n_hsync;
+ pScrn->monitor->nVrefresh = save_n_vrefresh;
+
+ /*
+ * Also delete the clockRanges (if it was setup) since it will be
+ * set up during the primary head initialization.
+ */
+ while (pScrn->clockRanges) {
+ ClockRangesPtr CRtmp = pScrn->clockRanges;
+ pScrn->clockRanges = pScrn->clockRanges->next;
+ xfree(CRtmp);
+ }
+
+ /* modePool is no longer needed, free it */
+ while (pScrn->modePool)
+ xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
+ pScrn->modePool = NULL;
+
+ return modesFound;
+}
+
+/* This is called by RADEONPreInit to validate modes and compute
+ * parameters for all of the valid modes.
+ */
+static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ClockRangePtr clockRanges;
+ int modesFound;
+ char *mod = NULL;
+#ifndef USE_FB
+ const char *Sym = NULL;
+#endif
+
+ /* This option has two purposes:
+ *
+ * 1. For CRT, if this option is on, xf86ValidateModes (to
+ * LOOKUP_BEST_REFRESH) is not going to be used for mode
+ * validation. Instead, we'll validate modes by matching exactly
+ * the modes supported from the DDC data. This option can be
+ * used (a) to enable non-standard modes listed in the Detailed
+ * Timings block of EDID, like 2048x1536 (not included in
+ * xf86DefModes), (b) to avoid unstable modes for some flat
+ * panels working in analog mode (some modes validated by
+ * xf86ValidateModes don't really work with these panels).
+ *
+ * 2. For DFP on primary head, with this option on, the validation
+ * routine will try to use supported modes from DDC data first
+ * before trying on-chip RMX streching. By default, native mode
+ * + RMX streching is used for all non-native modes, it appears
+ * more reliable. Some non-native modes listed in the DDC data
+ * may not work properly if they are used directly. This seems to
+ * only happen to a few panels (haven't nailed this down yet, it
+ * may related to the incorrect setting in TMDS_PLL_CNTL when
+ * pixel clock is changed). Use this option may give you better
+ * refresh rate for some non-native modes. The 2nd DVI port will
+ * always use DDC modes directly (only have one on-chip RMX
+ * unit).
+ *
+ * Note: This option will be dismissed if no DDC data is available.
+ */
+ info->ddc_mode =
+ xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE);
+
+ /* Here is a hack for cloning first display on the second head. If
+ * we don't do this, when both heads are connected, the same CRTC
+ * will be used to drive them according to the capability of the
+ * primary head. This can cause an unstable or blank screen, or
+ * even worse it can damage a monitor. This feature is also
+ * important for laptops (using M6, M7), where the panel can't be
+ * disconnect when one wants to use the CRT port. Although 2
+ * Screens can be set up in the config file for displaying same
+ * content on two monitors, it has problems with cursor, overlay,
+ * DRI.
+ */
+ if (info->HasCRTC2) {
+ if (info->Clone) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+
+ /* If we have 2 screens from the config file, we don't need
+ * to do clone thing, let each screen handles one head.
+ */
+ if (!pRADEONEnt->HasSecondary) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Clone modes validation ------------ \n");
+
+ modesFound = RADEONValidateCloneModes(pScrn);
+ if (modesFound < 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid mode found for CRTC2 clone\n");
+ info->Clone = FALSE;
+ info->CurCloneMode = NULL;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Total of %d clone modes found ------------ \n\n",
+ modesFound);
+ }
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Validating modes on %s head (DDCType: %d) ---------\n",
+ info->IsSecondary ? "Secondary" : "Primary",
+ info->DDCType);
+
+ pScrn->monitor->DDC = RADEONDoDDC(pScrn, pInt10);
+ if (!pScrn->monitor->DDC && info->ddc_mode) {
+ info->ddc_mode = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No DDC data available, DDCMode option is dismissed\n");
+ }
+
+ if (pScrn->monitor->DDC) {
+ /* If we still don't know sync range yet, let's try EDID.
+ *
+ * Note that, since we can have dual heads, Xconfigurator
+ * may not be able to probe both monitors correctly through
+ * vbe probe function (RADEONProbeDDC). Here we provide an
+ * additional way to auto-detect sync ranges if they haven't
+ * been added to XF86Config manually.
+ */
+ if (pScrn->monitor->nHsync <= 0)
+ RADEONSetSyncRangeFromEdid(pScrn, 1);
+ if (pScrn->monitor->nVrefresh <= 0)
+ RADEONSetSyncRangeFromEdid(pScrn, 0);
+ }
+
+ pScrn->progClock = TRUE;
+
+ clockRanges = xnfcalloc(sizeof(*clockRanges), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = info->pll.min_pll_freq;
+ clockRanges->maxClock = info->pll.max_pll_freq * 10;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = (info->DisplayType == MT_CRT);
+ clockRanges->doubleScanAllowed = (info->DisplayType == MT_CRT);
+
+ /* We'll use our own mode validation routine for DFP/LCD, since
+ * xf86ValidateModes does not work correctly with the DFP/LCD modes
+ * 'stretched' from their native mode.
+ */
+ if (info->DisplayType == MT_CRT && !info->ddc_mode) {
+ modesFound =
+ xf86ValidateModes(pScrn,
+ pScrn->monitor->Modes,
+ pScrn->display->modes,
+ clockRanges,
+ NULL, /* linePitches */
+ 8 * 64, /* minPitch */
+ 8 * 1024, /* maxPitch */
+ 64 * pScrn->bitsPerPixel, /* pitchInc */
+ 128, /* minHeight */
+ 2048, /* maxHeight */
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ info->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+
+ if (modesFound < 1 && info->FBDev) {
+ fbdevHWUseBuildinMode(pScrn);
+ pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
+ modesFound = 1;
+ }
+
+ if (modesFound == -1) return FALSE;
+
+ xf86PruneDriverModes(pScrn);
+ if (!modesFound || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ return FALSE;
+ }
+ } else {
+ /* First, free any allocated modes during configuration, since
+ * we don't need them
+ */
+ while (pScrn->modes)
+ xf86DeleteMode(&pScrn->modes, pScrn->modes);
+ while (pScrn->modePool)
+ xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
+
+ /* Next try to add DDC modes */
+ modesFound = RADEONValidateDDCModes(pScrn, pScrn->display->modes,
+ info->DisplayType);
+
+ /* If that fails and we're connect to a flat panel, then try to
+ * add the flat panel modes
+ */
+ if (modesFound < 1 && info->DisplayType != MT_CRT)
+ modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes);
+
+ /* Fail if we still don't have any valid modes */
+ if (modesFound < 1) {
+ if (info->DisplayType == MT_CRT) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid DDC modes found for this CRT\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Try turning off the \"DDCMode\" option\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid mode found for this DFP/LCD\n");
+ }
+ return FALSE;
+ }
+
+ /* Setup the screen's clockRanges for the VidMode extension */
+ pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1);
+ memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges));
+ pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH;
+ }
+
+ xf86SetCrtcForModes(pScrn, 0);
+
+ /* We need to adjust virtual size if the clone modes have larger
+ * display size.
+ */
+ if (info->Clone && info->CloneModes) {
+ DisplayModePtr clone_mode = info->CloneModes;
+ while (1) {
+ if ((clone_mode->HDisplay > pScrn->virtualX) ||
+ (clone_mode->VDisplay > pScrn->virtualY)) {
+ pScrn->virtualX =
+ pScrn->display->virtualX = clone_mode->HDisplay;
+ pScrn->virtualY =
+ pScrn->display->virtualY = clone_mode->VDisplay;
+ RADEONSetPitch(pScrn);
+ }
+ if (!clone_mode->next) break;
+ clone_mode = clone_mode->next;
+ }
+ }
+
+ pScrn->currentMode = pScrn->modes;
+ xf86PrintModes(pScrn);
+
+ /* Set DPI */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Get ScreenInit function */
+#ifdef USE_FB
+ mod = "fb";
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8: mod = "cfb"; Sym = "cfbScreenInit"; break;
+ case 16: mod = "cfb16"; Sym = "cfb16ScreenInit"; break;
+ case 32: mod = "cfb32"; Sym = "cfb32ScreenInit"; break;
+ }
+#endif
+
+ if (mod && !xf86LoadSubModule(pScrn, mod)) return FALSE;
+
+#ifdef USE_FB
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+#else
+ xf86LoaderReqSymbols(Sym, NULL);
+#endif
+
+ info->CurrentLayout.displayWidth = pScrn->displayWidth;
+ info->CurrentLayout.mode = pScrn->currentMode;
+
+ return TRUE;
+}
+
+/* This is called by RADEONPreInit to initialize the hardware cursor */
+static Bool RADEONPreInitCursor(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+ return TRUE;
+}
+
+/* This is called by RADEONPreInit to initialize hardware acceleration */
+static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
+{
+#ifdef XFree86LOADER
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ int errmaj = 0, errmin = 0;
+
+ info->xaaReq.majorversion = 1;
+ info->xaaReq.minorversion = 1;
+
+ if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL,
+ &info->xaaReq, &errmaj, &errmin)) {
+ info->xaaReq.minorversion = 0;
+
+ if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL,
+ &info->xaaReq, &errmaj, &errmin)) {
+ LoaderErrorMsg(NULL, "xaa", errmaj, errmin);
+ return FALSE;
+ }
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+#endif
+
+ return TRUE;
+}
+
+static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#if !defined(__powerpc__)
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
+ *ppInt10 = xf86InitInt10(info->pEnt->index);
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef XF86DRI
+static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n");
+ info->CPMode = RADEON_DEFAULT_CP_PIO_MODE;
+ } else {
+ info->CPMode = RADEON_DEFAULT_CP_BM_MODE;
+ }
+
+ info->agpMode = RADEON_DEFAULT_AGP_MODE;
+ info->agpSize = RADEON_DEFAULT_AGP_SIZE;
+ info->ringSize = RADEON_DEFAULT_RING_SIZE;
+ info->bufSize = RADEON_DEFAULT_BUFFER_SIZE;
+ info->agpTexSize = RADEON_DEFAULT_AGP_TEX_SIZE;
+ info->agpFastWrite = RADEON_DEFAULT_AGP_FAST_WRITE;
+
+ info->CPusecTimeout = RADEON_DEFAULT_CP_TIMEOUT;
+
+ if (!info->IsPCI) {
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_AGP_MODE, &(info->agpMode))) {
+ if (info->agpMode < 1 || info->agpMode > RADEON_AGP_MAX_MODE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP Mode: %d\n", info->agpMode);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using AGP %dx mode\n", info->agpMode);
+ }
+
+ if ((info->agpFastWrite = xf86ReturnOptValBool(info->Options,
+ OPTION_AGP_FW,
+ FALSE))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Enabling AGP Fast Write\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "AGP Fast Write disabled by default\n");
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
+ switch (info->agpSize) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ break;
+
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal AGP size: %d MB\n", info->agpSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_RING_SIZE, &(info->ringSize))) {
+ if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal ring buffer size: %d MB\n",
+ info->ringSize);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger(info->Options,
+ OPTION_BUFFER_SIZE, &(info->bufSize))) {
+ if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal vertex/indirect buffers size: %d MB\n",
+ info->bufSize);
+ return FALSE;
+ }
+ if (info->bufSize > 2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Illegal vertex/indirect buffers size: %d MB\n",
+ info->bufSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Clamping vertex/indirect buffers size to 2 MB\n");
+ info->bufSize = 2;
+ }
+ }
+
+ if (info->ringSize + info->bufSize + info->agpTexSize >
+ (int)info->agpSize) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Buffers are too big for requested AGP space\n");
+ return FALSE;
+ }
+
+ info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
+ }
+
+ if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
+ &(info->CPusecTimeout))) {
+ /* This option checked by the RADEON DRM kernel module */
+ }
+
+ /* Depth moves are disabled by default since they are extremely slow */
+ if ((info->depthMoves = xf86ReturnOptValBool(info->Options,
+ OPTION_DEPTH_MOVE, FALSE))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Depth moves disabled by default\n");
+ }
+
+ /* Two options to try and squeeze as much texture memory as possible
+ * for dedicated 3d rendering boxes
+ */
+ info->noBackBuffer = xf86ReturnOptValBool(info->Options,
+ OPTION_NO_BACKBUFFER,
+ FALSE);
+
+ if (info->noBackBuffer) {
+ info->allowPageFlip = 0;
+ } else if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ info->allowPageFlip = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't load shadowfb module:\n");
+ } else {
+ xf86LoaderReqSymLists(driShadowFBSymbols, NULL);
+
+ info->allowPageFlip = xf86ReturnOptValBool(info->Options,
+ OPTION_PAGE_FLIP,
+ FALSE);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
+ info->allowPageFlip ? "en" : "dis");
+
+ return TRUE;
+}
+#endif
+
+static void
+RADEONProbeDDC(ScrnInfoPtr pScrn, int indx)
+{
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,indx);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ }
+}
+
+/* RADEONPreInit is called once at server startup */
+Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ RADEONInfoPtr info;
+ xf86Int10InfoPtr pInt10 = NULL;
+ void *int10_save = NULL;
+
+ RADEONTRACE(("RADEONPreInit\n"));
+ if (pScrn->numEntities != 1) return FALSE;
+
+ if (!RADEONGetRec(pScrn)) return FALSE;
+
+ info = RADEONPTR(pScrn);
+ info->IsSecondary = FALSE;
+ info->Clone = FALSE;
+ info->CurCloneMode = NULL;
+ info->CloneModes = NULL;
+ info->IsSwitching = FALSE;
+
+ info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (info->pEnt->location.type != BUS_PCI) goto fail;
+
+ info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
+ info->PciTag = pciTag(info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+
+#if !defined(__alpha__)
+ if (xf86GetPciDomain(info->PciTag) ||
+ !xf86IsPrimaryPci(info->PciInfo))
+ RADEONPreInt10Save(pScrn, &int10_save);
+#else
+ /* [Alpha] On the primary, the console already ran the BIOS and we're
+ * going to run it again - so make sure to "fix up" the card
+ * so that (1) we can read the BIOS ROM and (2) the BIOS will
+ * get the memory config right.
+ */
+ RADEONPreInt10Save(pScrn, &int10_save);
+#endif
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (xf86IsPrimInitDone(pScrn->entityList[0])) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+
+ info->IsSecondary = TRUE;
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+ if (pRADEONEnt->BypassSecondary) {
+ pRADEONEnt->HasSecondary = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Only one monitor detected, Second screen "
+ "will NOT be created\n");
+ return FALSE;
+ }
+ pRADEONEnt->pSecondaryScrn = pScrn;
+ } else {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+
+ pRADEONEnt = pPriv->ptr;
+ pRADEONEnt->pPrimaryScrn = pScrn;
+ pRADEONEnt->IsDRIEnabled = FALSE;
+ pRADEONEnt->BypassSecondary = FALSE;
+ pRADEONEnt->RestorePrimary = FALSE;
+ pRADEONEnt->IsSecondaryRestored = FALSE;
+ }
+ }
+
+ if (flags & PROBE_DETECT) {
+ RADEONProbeDDC(pScrn, info->pEnt->index);
+ RADEONPostInt10Check(pScrn, int10_save);
+ return TRUE;
+ }
+
+ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+ if (!vgaHWGetHWRec(pScrn)) {
+ RADEONFreeRec(pScrn);
+ return FALSE;
+ }
+
+ vgaHWGetIOBase(VGAHWPTR(pScrn));
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "PCI bus %d card %d func %d\n",
+ info->PciInfo->bus,
+ info->PciInfo->device,
+ info->PciInfo->func);
+
+ if (xf86RegisterResources(info->pEnt->index, 0, ResExclusive))
+ goto fail;
+
+ if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr))
+ goto fail;
+
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ if (!RADEONPreInitVisual(pScrn))
+ goto fail;
+
+ /* We can't do this until we have a
+ pScrn->display. */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(info->Options = xalloc(sizeof(RADEONOptions))))
+ goto fail;
+
+ memcpy(info->Options, RADEONOptions, sizeof(RADEONOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
+
+ if (!RADEONPreInitWeight(pScrn))
+ goto fail;
+
+ if (xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY,
+ &(info->videoKey))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
+ info->videoKey);
+ } else {
+ info->videoKey = 0x1E;
+ }
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) {
+ /* check for Linux framebuffer device */
+
+ if (xf86LoadSubModule(pScrn, "fbdevhw")) {
+ xf86LoaderReqSymLists(fbdevHWSymbols, NULL);
+
+ if (fbdevHWInit(pScrn, info->PciInfo, NULL)) {
+ pScrn->ValidMode = fbdevHWValidMode;
+ info->FBDev = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using framebuffer device\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "fbdevHWInit failed, not using framebuffer device\n");
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Couldn't load fbdevhw module, not using framebuffer device\n");
+ }
+ }
+
+ if (!info->FBDev)
+ if (!RADEONPreInitInt10(pScrn, &pInt10))
+ goto fail;
+
+ RADEONPostInt10Check(pScrn, int10_save);
+
+ if (!RADEONPreInitConfig(pScrn))
+ goto fail;
+
+#if !defined(__powerpc__)
+ if (!RADEONGetBIOSParameters(pScrn, pInt10))
+ goto fail;
+#else
+ /* Force type to CRT since we currently can't read BIOS to tell us
+ * what kind of heads we have.
+ */
+ info->DisplayType = MT_CRT;
+#endif
+
+ RADEONPreInitDDC(pScrn);
+
+ if (!RADEONGetPLLParameters(pScrn)) goto fail;
+
+ if (!RADEONPreInitGamma(pScrn)) goto fail;
+
+ if (!RADEONPreInitModes(pScrn, pInt10)) goto fail;
+
+ if (!RADEONPreInitCursor(pScrn)) goto fail;
+
+ if (!RADEONPreInitAccel(pScrn)) goto fail;
+
+#ifdef XF86DRI
+ if (!RADEONPreInitDRI(pScrn)) goto fail;
+#endif
+
+ /* Free the video bios (if applicable) */
+ if (info->VBIOS) {
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ }
+
+ /* Free int10 info */
+ if (pInt10)
+ xf86FreeInt10(pInt10);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
+ "For information on using the multimedia capabilities\n of this"
+ " adapter, please see http://gatos.sf.net.\n");
+
+ return TRUE;
+
+fail:
+ /* Pre-init failed. */
+
+ /* Free the video bios (if applicable) */
+ if (info->VBIOS) {
+ xfree(info->VBIOS);
+ info->VBIOS = NULL;
+ }
+
+ /* Free int10 info */
+ if (pInt10)
+ xf86FreeInt10(pInt10);
+
+ vgaHWFreeHWRec(pScrn);
+ RADEONFreeRec(pScrn);
+ return FALSE;
+}
+
+/* Load a palette */
+static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors,
+ int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+ int idx, j;
+ unsigned char r, g, b;
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRILock(pScrn->pScreen, 0);
+#endif
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ if (info->FBDev) {
+ fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual);
+ } else {
+ /* If the second monitor is connected, we also need to deal with
+ * the secondary palette
+ */
+ if (info->IsSecondary) j = 1;
+ else j = 0;
+
+ PAL_SELECT(j);
+
+ if (info->CurrentLayout.depth == 15) {
+ /* 15bpp mode. This sends 32 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ g = colors[idx].green;
+ b = colors[idx].blue;
+ OUTPAL(idx * 8, r, g, b);
+ }
+ } else if (info->CurrentLayout.depth == 16) {
+ /* 16bpp mode. This sends 64 values.
+ *
+ * There are twice as many green values as there are values
+ * for red and blue. So, we take each red and blue pair,
+ * and combine it with each of the two green values.
+ */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx / 2].red;
+ g = colors[idx].green;
+ b = colors[idx / 2].blue;
+ RADEONWaitForFifo(pScrn, 32); /* delay */
+ OUTPAL(idx * 4, r, g, b);
+
+ /* AH - Added to write extra green data - How come this isn't
+ * needed on R128? We didn't load the extra green data in the
+ * other routine
+ */
+ if (idx <= 31) {
+ r = colors[idx].red;
+ g = colors[(idx * 2) + 1].green;
+ b = colors[idx].blue;
+ RADEONWaitForFifo(pScrn, 32); /* delay */
+ OUTPAL(idx * 8, r, g, b);
+ }
+ }
+ } else {
+ /* 8bpp mode. This sends 256 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ b = colors[idx].blue;
+ g = colors[idx].green;
+ RADEONWaitForFifo(pScrn, 32); /* delay */
+ OUTPAL(idx, r, g, b);
+ }
+ }
+
+ if (info->Clone) {
+ PAL_SELECT(1);
+ if (info->CurrentLayout.depth == 15) {
+ /* 15bpp mode. This sends 32 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ g = colors[idx].green;
+ b = colors[idx].blue;
+ OUTPAL(idx * 8, r, g, b);
+ }
+ } else if (info->CurrentLayout.depth == 16) {
+ /* 16bpp mode. This sends 64 values.
+ *
+ * There are twice as many green values as there are values
+ * for red and blue. So, we take each red and blue pair,
+ * and combine it with each of the two green values.
+ */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx / 2].red;
+ g = colors[idx].green;
+ b = colors[idx / 2].blue;
+ OUTPAL(idx * 4, r, g, b);
+
+ /* AH - Added to write extra green data - How come
+ * this isn't needed on R128? We didn't load the
+ * extra green data in the other routine.
+ */
+ if (idx <= 31) {
+ r = colors[idx].red;
+ g = colors[(idx * 2) + 1].green;
+ b = colors[idx].blue;
+ OUTPAL(idx * 8, r, g, b);
+ }
+ }
+ } else {
+ /* 8bpp mode. This sends 256 values. */
+ for (i = 0; i < numColors; i++) {
+ idx = indices[i];
+ r = colors[idx].red;
+ b = colors[idx].blue;
+ g = colors[idx].green;
+ OUTPAL(idx, r, g, b);
+ }
+ }
+ }
+ }
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRIUnlock(pScrn->pScreen);
+#endif
+}
+
+static void RADEONBlockHandler(int i, pointer blockData,
+ pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled)
+ FLUSH_RING();
+#endif
+
+ pScreen->BlockHandler = info->BlockHandler;
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = RADEONBlockHandler;
+
+ if (info->VideoTimerCallback)
+ (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+}
+
+/* Called at the start of each server generation. */
+Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ BoxRec MemBox;
+ int y2;
+
+ RADEONTRACE(("RADEONScreenInit %x %d\n",
+ pScrn->memPhysBase, pScrn->fbOffset));
+
+#ifdef XF86DRI
+ /* Turn off the CP for now. */
+ info->CPInUse = FALSE;
+ info->CPStarted = FALSE;
+ info->directRenderingEnabled = FALSE;
+#endif
+ info->accelOn = FALSE;
+ pScrn->fbOffset = 0;
+ if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
+ if (!RADEONMapMem(pScrn)) return FALSE;
+
+#ifdef XF86DRI
+ info->fbX = 0;
+ info->fbY = 0;
+#endif
+
+ info->PaletteSavedOnVT = FALSE;
+
+ RADEONSave(pScrn);
+ if (info->FBDev) {
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
+ } else {
+ if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ }
+
+ RADEONSaveScreen(pScreen, SCREEN_SAVER_ON);
+
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ if (info->CurCloneMode) {
+ info->CloneFrameX0 =
+ (pScrn->virtualX - info->CurCloneMode->HDisplay) / 2;
+ info->CloneFrameY0 =
+ (pScrn->virtualY - info->CurCloneMode->VDisplay) / 2;
+ RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE);
+ }
+
+ /* Visual setup */
+ miClearVisualTypes();
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits,
+ pScrn->defaultVisual)) return FALSE;
+ miSetPixmapDepths ();
+
+#ifdef XF86DRI
+ /* Setup DRI after visuals have been
+ established, but before cfbScreenInit is
+ called. cfbScreenInit will eventually
+ call the driver's InitGLXVisuals call
+ back. */
+ {
+ /* FIXME: When we move to dynamic allocation of back and depth
+ * buffers, we will want to revisit the following check for 3
+ * times the virtual size of the screen below.
+ */
+ int width_bytes = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ int maxy = info->FbMapSize / width_bytes;
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Acceleration disabled, not initializing the DRI\n");
+ info->directRenderingEnabled = FALSE;
+ } else if (maxy <= pScrn->virtualY * 3) {
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Static buffer allocation failed -- "
+ "need at least %d kB video memory\n",
+ (pScrn->displayWidth * pScrn->virtualY *
+ info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
+ info->directRenderingEnabled = FALSE;
+ } else if (info->ChipFamily >= CHIP_FAMILY_R300) {
+ info->directRenderingEnabled = FALSE;
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Direct rendering not yet supported on "
+ "Radeon 9500/9700 and newer cards\n");
+ } else {
+ if (info->IsSecondary)
+ info->directRenderingEnabled = FALSE;
+ else {
+ /* Xinerama has sync problem with DRI, disable it for now */
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ info->directRenderingEnabled = FALSE;
+ xf86DrvMsg(scrnIndex, X_WARNING,
+ "Direct Rendering Disabled -- "
+ "Dual-head configuration is not working with "
+ "DRI at present.\n"
+ "Please use only one Device/Screen "
+ "section in your XFConfig file.\n");
+ } else {
+ info->directRenderingEnabled =
+ RADEONDRIScreenInit(pScreen);
+ }
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+ pRADEONEnt->IsDRIEnabled = info->directRenderingEnabled;
+ }
+ }
+ }
+ }
+#endif
+
+#ifdef USE_FB
+ if (!fbScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+ pScrn->bitsPerPixel))
+ return FALSE;
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ if (!cfbScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 16:
+ if (!cfb16ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 32:
+ if (!cfb32ScreenInit(pScreen, info->FB,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+ return FALSE;
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Invalid bpp (%d)\n", pScrn->bitsPerPixel);
+ return FALSE;
+ }
+#endif
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+#ifdef USE_FB
+ /* Must be after RGB order fixed */
+ fbPictureInit (pScreen, 0, 0);
+#endif
+
+#ifdef RENDER
+ if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown)
+ {
+ int subPixelOrder;
+
+ switch (info->DisplayType) {
+ case MT_NONE: subPixelOrder = SubPixelUnknown; break;
+ case MT_LCD: subPixelOrder = SubPixelHorizontalRGB; break;
+ case MT_DFP: subPixelOrder = SubPixelHorizontalRGB; break;
+ default: subPixelOrder = SubPixelNone; break;
+ }
+ PictureSetSubpixelOrder (pScreen, subPixelOrder);
+ }
+#endif
+ /* Memory manager setup */
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ FBAreaPtr fbarea;
+ int width_bytes = (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes);
+ int cpp = info->CurrentLayout.pixel_bytes;
+ int bufferSize = ((pScrn->virtualY * width_bytes
+ + RADEON_BUFFER_ALIGN)
+ & ~RADEON_BUFFER_ALIGN);
+ int depthSize = ((((pScrn->virtualY+15) & ~15) * width_bytes
+ + RADEON_BUFFER_ALIGN)
+ & ~RADEON_BUFFER_ALIGN);
+ int l;
+ int scanlines;
+
+ info->frontOffset = 0;
+ info->frontPitch = pScrn->displayWidth;
+
+ switch (info->CPMode) {
+ case RADEON_DEFAULT_CP_PIO_MODE:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
+ break;
+ case RADEON_DEFAULT_CP_BM_MODE:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n");
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n");
+ break;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB AGP aperture\n", info->agpSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for the ring buffer\n", info->ringSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for vertex/indirect buffers\n", info->bufSize);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using %d MB for AGP textures\n", info->agpTexSize);
+
+ /* Try for front, back, depth, and three framebuffers worth of
+ * pixmap cache. Should be enough for a fullscreen background
+ * image plus some leftovers.
+ */
+ info->textureSize = info->FbMapSize - 5 * bufferSize - depthSize;
+
+ /* If that gives us less than half the available memory, let's
+ * be greedy and grab some more. Sorry, I care more about 3D
+ * performance than playing nicely, and you'll get around a full
+ * framebuffer's worth of pixmap cache anyway.
+ */
+ if (info->textureSize < (int)info->FbMapSize / 2) {
+ info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize;
+ }
+ if (info->textureSize < (int)info->FbMapSize / 2) {
+ info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize;
+ }
+ /* If there's still no space for textures, try without pixmap cache */
+ if (info->textureSize < 0) {
+ info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize
+ - 64/4*64;
+ }
+
+ /* Check to see if there is more room available after the 8192nd
+ scanline for textures */
+ if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize
+ > info->textureSize) {
+ info->textureSize =
+ info->FbMapSize - 8192*width_bytes - bufferSize - depthSize;
+ }
+
+ /* If backbuffer is disabled, don't allocate memory for it */
+ if (info->noBackBuffer) {
+ info->textureSize += bufferSize;
+ }
+
+ if (info->textureSize > 0) {
+ l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);
+ if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
+
+ /* Round the texture size up to the nearest whole number of
+ * texture regions. Again, be greedy about this, don't
+ * round down.
+ */
+ info->log2TexGran = l;
+ info->textureSize = (info->textureSize >> l) << l;
+ } else {
+ info->textureSize = 0;
+ }
+
+ /* Set a minimum usable local texture heap size. This will fit
+ * two 256x256x32bpp textures.
+ */
+ if (info->textureSize < 512 * 1024) {
+ info->textureOffset = 0;
+ info->textureSize = 0;
+ }
+
+ /* Reserve space for textures */
+ info->textureOffset = ((info->FbMapSize - info->textureSize +
+ RADEON_BUFFER_ALIGN) &
+ ~(CARD32)RADEON_BUFFER_ALIGN);
+
+ /* Reserve space for the shared depth
+ * buffer.
+ */
+ info->depthOffset = ((info->textureOffset - depthSize +
+ RADEON_BUFFER_ALIGN) &
+ ~(CARD32)RADEON_BUFFER_ALIGN);
+ info->depthPitch = pScrn->displayWidth;
+
+ /* Reserve space for the shared back buffer */
+ if (info->noBackBuffer) {
+ info->backOffset = info->depthOffset;
+ info->backPitch = pScrn->displayWidth;
+ } else {
+ info->backOffset = ((info->depthOffset - bufferSize +
+ RADEON_BUFFER_ALIGN) &
+ ~(CARD32)RADEON_BUFFER_ALIGN);
+ info->backPitch = pScrn->displayWidth;
+ }
+
+ info->backY = info->backOffset / width_bytes;
+ info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp;
+
+ scanlines = info->FbMapSize / width_bytes;
+ if (scanlines > 8191) scanlines = 8191;
+
+ MemBox.x1 = 0;
+ MemBox.y1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ MemBox.y2 = scanlines;
+
+ if (!xf86InitFBManager(pScreen, &MemBox)) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Memory manager initialization to "
+ "(%d,%d) (%d,%d) failed\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ return FALSE;
+ } else {
+ int width, height;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Memory manager initialized to (%d,%d) (%d,%d)\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth,
+ 2, 0, NULL, NULL,
+ NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved area from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+ }
+ if (xf86QueryLargestOffscreenArea(pScreen, &width,
+ &height, 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+
+ /* Lines in offscreen area needed for depth buffer and
+ * textures
+ */
+ info->depthTexLines = (scanlines
+ - info->depthOffset / width_bytes);
+ info->backLines = (scanlines
+ - info->backOffset / width_bytes
+ - info->depthTexLines);
+ info->backArea = NULL;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Unable to determine largest offscreen area "
+ "available\n");
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Will use back buffer at offset 0x%x\n",
+ info->backOffset);
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Will use depth buffer at offset 0x%x\n",
+ info->depthOffset);
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Will use %d kb for textures at offset 0x%x\n",
+ info->textureSize/1024, info->textureOffset);
+
+ info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
+ (info->frontOffset >> 10));
+
+ info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
+ (info->backOffset >> 10));
+
+ info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) |
+ (info->depthOffset >> 10));
+ } else
+#endif
+ {
+ MemBox.x1 = 0;
+ MemBox.y1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ y2 = (info->FbMapSize
+ / (pScrn->displayWidth *
+ info->CurrentLayout.pixel_bytes));
+ if (y2 >= 32768) y2 = 32767; /* because MemBox.y2 is signed short */
+ MemBox.y2 = y2;
+
+ /* The acceleration engine uses 14 bit
+ signed coordinates, so we can't have any
+ drawable caches beyond this region. */
+ if (MemBox.y2 > 8191) MemBox.y2 = 8191;
+
+ if (!xf86InitFBManager(pScreen, &MemBox)) {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Memory manager initialization to "
+ "(%d,%d) (%d,%d) failed\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ return FALSE;
+ } else {
+ int width, height;
+ FBAreaPtr fbarea;
+
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Memory manager initialized to (%d,%d) (%d,%d)\n",
+ MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
+ if ((fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth,
+ 2, 0, NULL, NULL,
+ NULL))) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Reserved area from (%d,%d) to (%d,%d)\n",
+ fbarea->box.x1, fbarea->box.y1,
+ fbarea->box.x2, fbarea->box.y2);
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
+ }
+ if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
+ 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+ }
+ }
+ }
+
+ /* Acceleration setup */
+ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ if (RADEONAccelInit(pScreen)) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
+ info->accelOn = TRUE;
+
+ /* FIXME: Figure out why this was added because it shouldn't be! */
+ /* This is needed by the DRI and XAA code for shared entities */
+ pScrn->pScreen = pScreen;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Acceleration initialization failed\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+
+ /* DGA setup */
+ RADEONDGAInit(pScreen);
+
+ /* Backing store setup */
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+
+ /* Set Silken Mouse */
+ xf86SetSilkenMouse(pScreen);
+
+ /* Cursor setup */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Hardware cursor setup */
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (RADEONCursorInit(pScreen)) {
+ int width, height;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using hardware cursor (scanline %d)\n",
+ info->cursor_start / pScrn->displayWidth
+ / info->CurrentLayout.pixel_bytes);
+ if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
+ 0, 0, 0)) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
+ }
+ } else {
+ info->cursor_start = 0;
+ xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
+ }
+
+ /* Colormap setup */
+ if (!miCreateDefColormap(pScreen)) return FALSE;
+ if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
+ RADEONLoadPalette, NULL,
+ CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich@suse.de) */
+ | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+ | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE;
+
+ /* DPMS setup */
+#ifdef DPMSExtension
+ xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0);
+#endif
+
+ RADEONInitVideo(pScreen);
+
+ /* Provide SaveScreen */
+ pScreen->SaveScreen = RADEONSaveScreen;
+
+ /* Wrap CloseScreen */
+ info->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = RADEONCloseScreen;
+
+ /* Note unused options */
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+#ifdef XF86DRI
+ /* DRI finalization */
+ if (info->directRenderingEnabled) {
+ /* Now that mi, cfb, drm and others have
+ done their thing, complete the DRI
+ setup. */
+ info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen);
+ }
+ if (info->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n");
+ }
+#endif
+
+ info->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = RADEONBlockHandler;
+
+ return TRUE;
+}
+
+/* Write common registers (initialized to 0) */
+static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREG(RADEON_OVR_CLR, restore->ovr_clr);
+ OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right);
+ OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
+ OUTREG(RADEON_OV0_SCALE_CNTL, restore->ov0_scale_cntl);
+ OUTREG(RADEON_SUBPIC_CNTL, restore->subpic_cntl);
+ OUTREG(RADEON_VIPH_CONTROL, restore->viph_control);
+ OUTREG(RADEON_I2C_CNTL_1, restore->i2c_cntl_1);
+ OUTREG(RADEON_GEN_INT_CNTL, restore->gen_int_cntl);
+ OUTREG(RADEON_CAP0_TRIG_CNTL, restore->cap0_trig_cntl);
+ OUTREG(RADEON_CAP1_TRIG_CNTL, restore->cap1_trig_cntl);
+ OUTREG(RADEON_BUS_CNTL, restore->bus_cntl);
+ OUTREG(RADEON_SURFACE_CNTL, restore->surface_cntl);
+
+ /* Workaround for the VT switching problem in dual-head mode. This
+ * problem only occurs on RV style chips, typically when a FP and
+ * CRT are connected.
+ */
+ if (info->HasCRTC2 &&
+ !info->IsSwitching &&
+ info->ChipFamily != CHIP_FAMILY_R200 &&
+ info->ChipFamily != CHIP_FAMILY_R300) {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+ CARD32 tmp;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+
+ if (pRADEONEnt->HasSecondary || info->Clone) {
+ tmp = INREG(RADEON_DAC_CNTL2);
+ OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL);
+ usleep(100000);
+ }
+ }
+}
+
+/* Write miscellaneous registers which might have been destroyed by an fbdevHW
+ * call
+ */
+static void RADEONRestoreFBDevRegisters(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+#ifdef XF86DRI
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ /* Restore register for vertical blank interrupts */
+ if (info->irq) {
+ OUTREG(RADEON_GEN_INT_CNTL, restore->gen_int_cntl);
+ }
+
+ /* Restore registers for page flipping */
+ if (info->allowPageFlip) {
+ OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl);
+ if (info->HasCRTC2) {
+ OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl);
+ }
+ }
+#endif
+}
+
+/* Write CRTC registers */
+static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
+
+ OUTREGP(RADEON_CRTC_EXT_CNTL,
+ restore->crtc_ext_cntl,
+ RADEON_CRTC_VSYNC_DIS |
+ RADEON_CRTC_HSYNC_DIS |
+ RADEON_CRTC_DISPLAY_DIS);
+
+ OUTREGP(RADEON_DAC_CNTL,
+ restore->dac_cntl,
+ RADEON_DAC_RANGE_CNTL |
+ RADEON_DAC_BLANKING);
+
+ OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp);
+ OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
+ OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp);
+ OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
+ OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset);
+ OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl);
+ OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch);
+}
+
+/* Write CRTC2 registers */
+static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ restore->crtc2_gen_cntl,
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS |
+ RADEON_CRTC2_DISP_DIS);
+
+ OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
+
+ if (info->ChipFamily == CHIP_FAMILY_R200 ||
+ info->ChipFamily == CHIP_FAMILY_R300) {
+ OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
+ } else {
+ OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
+ if (info->IsDell) {
+ /* Workaround for DELL card. BIOS doesn't initialize
+ * TV_DAC_CNTL to a correct value which causes too high
+ * contrast for the second CRT (using TV_DAC).
+ */
+ OUTREG(RADEON_TV_DAC_CNTL, 0x00280203);
+ }
+ }
+
+ OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp);
+ OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
+ OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp);
+ OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
+ OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset);
+ OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl);
+ OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch);
+
+ if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) {
+ OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid);
+ OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid);
+ OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl);
+ }
+
+#if 0
+ /* Hack for restoring text mode -- fixed elsewhere */
+ usleep(100000);
+#endif
+}
+
+/* Write flat panel registers */
+static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ unsigned long tmp;
+
+ OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
+ OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
+ OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid);
+ OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid);
+ OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl);
+ OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch);
+ OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch);
+ OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl);
+
+ if (info->DisplayType == MT_LCD) {
+ tmp = INREG(RADEON_LVDS_GEN_CNTL);
+ if ((tmp & (RADEON_LVDS_ON | RADEON_LVDS_BLON)) ==
+ (restore->lvds_gen_cntl & (RADEON_LVDS_ON | RADEON_LVDS_BLON))) {
+ OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ } else {
+ if (restore->lvds_gen_cntl & (RADEON_LVDS_ON | RADEON_LVDS_BLON)) {
+ usleep(RADEONPTR(pScrn)->PanelPwrDly * 1000);
+ OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ } else {
+ OUTREG(RADEON_LVDS_GEN_CNTL,
+ restore->lvds_gen_cntl | RADEON_LVDS_BLON);
+ usleep(RADEONPTR(pScrn)->PanelPwrDly * 1000);
+ OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
+ }
+ }
+ }
+}
+
+static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
+{
+ int i = 0;
+
+ /* FIXME: Certain revisions of R300 can't recover here. Not sure of
+ the cause yet, but this workaround will mask the problem for now.
+ Other chips usually will pass at the very first test, so the
+ workaround shouldn't have any effect on them. */
+ for (i = 0;
+ (i < 10000 &&
+ INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+ i++);
+}
+
+static void RADEONPLLWriteUpdate(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+
+ OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+ RADEON_PPLL_ATOMIC_UPDATE_W,
+ ~(RADEON_PPLL_ATOMIC_UPDATE_W));
+}
+
+static void RADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
+{
+ int i = 0;
+
+ /* FIXME: Certain revisions of R300 can't recover here. Not sure of
+ the cause yet, but this workaround will mask the problem for now.
+ Other chips usually will pass at the very first test, so the
+ workaround shouldn't have any effect on them. */
+ for (i = 0;
+ (i < 10000 &&
+ INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+ i++);
+}
+
+static void RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+
+ OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
+ RADEON_P2PLL_ATOMIC_UPDATE_W,
+ ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
+}
+
+/* Write PLL registers */
+static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
+ RADEON_VCLK_SRC_SEL_CPUCLK,
+ ~(RADEON_VCLK_SRC_SEL_MASK));
+
+ OUTPLLP(pScrn,
+ RADEON_PPLL_CNTL,
+ RADEON_PPLL_RESET
+ | RADEON_PPLL_ATOMIC_UPDATE_EN
+ | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN,
+ ~(RADEON_PPLL_RESET
+ | RADEON_PPLL_ATOMIC_UPDATE_EN
+ | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ OUTREGP(RADEON_CLOCK_CNTL_INDEX,
+ RADEON_PLL_DIV_SEL,
+ ~(RADEON_PLL_DIV_SEL));
+
+ if (info->ChipFamily == CHIP_FAMILY_R300) {
+ if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+ /* When restoring console mode, use saved PPLL_REF_DIV
+ * setting.
+ */
+ OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+ restore->ppll_ref_div,
+ 0);
+ } else {
+ /* R300 uses ref_div_acc field as real ref divider */
+ OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+ (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+ ~R300_PPLL_REF_DIV_ACC_MASK);
+ }
+ } else {
+ OUTPLLP(pScrn, RADEON_PPLL_REF_DIV,
+ restore->ppll_ref_div,
+ ~RADEON_PPLL_REF_DIV_MASK);
+ }
+
+ OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
+ restore->ppll_div_3,
+ ~RADEON_PPLL_FB3_DIV_MASK);
+
+ OUTPLLP(pScrn, RADEON_PPLL_DIV_3,
+ restore->ppll_div_3,
+ ~RADEON_PPLL_POST3_DIV_MASK);
+
+ RADEONPLLWriteUpdate(pScrn);
+ RADEONPLLWaitForReadUpdateComplete(pScrn);
+
+ OUTPLL(RADEON_HTOTAL_CNTL, restore->htotal_cntl);
+
+ OUTPLLP(pScrn, RADEON_PPLL_CNTL,
+ 0,
+ ~(RADEON_PPLL_RESET
+ | RADEON_PPLL_SLEEP
+ | RADEON_PPLL_ATOMIC_UPDATE_EN
+ | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+ restore->ppll_ref_div,
+ restore->ppll_div_3,
+ restore->htotal_cntl,
+ INPLL(pScrn, RADEON_PPLL_CNTL)));
+ RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
+ restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+ restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
+ (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16));
+
+ usleep(5000); /* Let the clock to lock */
+
+ OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
+ RADEON_VCLK_SRC_SEL_PPLLCLK,
+ ~(RADEON_VCLK_SRC_SEL_MASK));
+}
+
+
+/* Write PLL2 registers */
+static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn,
+ RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
+ RADEON_PIX2CLK_SRC_SEL_CPUCLK,
+ ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+
+ OUTPLLP(pScrn,
+ RADEON_P2PLL_CNTL,
+ RADEON_P2PLL_RESET
+ | RADEON_P2PLL_ATOMIC_UPDATE_EN
+ | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN,
+ ~(RADEON_P2PLL_RESET
+ | RADEON_P2PLL_ATOMIC_UPDATE_EN
+ | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN));
+
+ OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV,
+ restore->p2pll_ref_div,
+ ~RADEON_P2PLL_REF_DIV_MASK);
+
+ OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
+ restore->p2pll_div_0,
+ ~RADEON_P2PLL_FB0_DIV_MASK);
+
+ OUTPLLP(pScrn, RADEON_P2PLL_DIV_0,
+ restore->p2pll_div_0,
+ ~RADEON_P2PLL_POST0_DIV_MASK);
+
+ RADEONPLL2WriteUpdate(pScrn);
+ RADEONPLL2WaitForReadUpdateComplete(pScrn);
+
+ OUTPLL(RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
+
+ OUTPLLP(pScrn, RADEON_P2PLL_CNTL,
+ 0,
+ ~(RADEON_P2PLL_RESET
+ | RADEON_P2PLL_SLEEP
+ | RADEON_P2PLL_ATOMIC_UPDATE_EN
+ | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN));
+
+ RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+ restore->p2pll_ref_div,
+ restore->p2pll_div_0,
+ restore->htotal_cntl2,
+ INPLL(pScrn, RADEON_P2PLL_CNTL)));
+ RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
+ restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
+ restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK,
+ (restore->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >>16));
+
+ usleep(5000); /* Let the clock to lock */
+
+ OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL,
+ RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
+ ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+}
+
+#if 0
+/* Write palette data */
+static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+ if (!restore->palette_valid) return;
+
+ PAL_SELECT(1);
+ OUTPAL_START(0);
+ for (i = 0; i < 256; i++) {
+ RADEONWaitForFifo(pScrn, 32); /* delay */
+ OUTPAL_NEXT_CARD32(restore->palette2[i]);
+ }
+
+ PAL_SELECT(0);
+ OUTPAL_START(0);
+ for (i = 0; i < 256; i++) {
+ RADEONWaitForFifo(pScrn, 32); /* delay */
+ OUTPAL_NEXT_CARD32(restore->palette[i]);
+ }
+}
+#endif
+
+/* Write out state to define a new video mode */
+static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+ static RADEONSaveRec restore0;
+
+ /* For Non-dual head card, we don't have private field in the Entity */
+ if (!info->HasCRTC2) {
+ RADEONRestoreCommonRegisters(pScrn, restore);
+ RADEONRestoreCrtcRegisters(pScrn, restore);
+ if ((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD)) {
+ RADEONRestoreFPRegisters(pScrn, restore);
+ }
+ RADEONRestorePLLRegisters(pScrn, restore);
+ return;
+ }
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+
+ RADEONTRACE(("RADEONRestoreMode(%p)\n", restore));
+
+ /* When changing mode with Dual-head card, care must be taken for
+ * the special order in setting registers. CRTC2 has to be set
+ * before changing CRTC_EXT register. In the dual-head setup, X
+ * server calls this routine twice with primary and secondary pScrn
+ * pointers respectively. The calls can come with different
+ * order. Regardless the order of X server issuing the calls, we
+ * have to ensure we set registers in the right order!!! Otherwise
+ * we may get a blank screen.
+ */
+ if (info->IsSecondary) {
+ if (!pRADEONEnt->RestorePrimary)
+ RADEONRestoreCommonRegisters(pScrn, restore);
+ RADEONRestoreCrtc2Registers(pScrn, restore);
+ RADEONRestorePLL2Registers(pScrn, restore);
+
+ if(info->IsSwitching) return;
+
+ pRADEONEnt->IsSecondaryRestored = TRUE;
+
+ if (pRADEONEnt->RestorePrimary) {
+ RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn);
+ pRADEONEnt->RestorePrimary = FALSE;
+
+ RADEONRestoreCrtcRegisters(pScrn, &restore0);
+ if ((info0->DisplayType == MT_DFP) ||
+ (info0->DisplayType == MT_LCD)) {
+ RADEONRestoreFPRegisters(pScrn, &restore0);
+ }
+
+ RADEONRestorePLLRegisters(pScrn, &restore0);
+ pRADEONEnt->IsSecondaryRestored = FALSE;
+ }
+ } else {
+ if (!pRADEONEnt->IsSecondaryRestored)
+ RADEONRestoreCommonRegisters(pScrn, restore);
+
+ if (info->Clone) {
+ RADEONRestoreCrtc2Registers(pScrn, restore);
+ RADEONRestorePLL2Registers(pScrn, restore);
+ }
+
+ if (!pRADEONEnt->HasSecondary || pRADEONEnt->IsSecondaryRestored ||
+ info->IsSwitching) {
+ pRADEONEnt->IsSecondaryRestored = FALSE;
+
+ RADEONRestoreCrtcRegisters(pScrn, restore);
+ if ((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD)) {
+ RADEONRestoreFPRegisters(pScrn, restore);
+ }
+ RADEONRestorePLLRegisters(pScrn, restore);
+ } else {
+ memcpy(&restore0, restore, sizeof(restore0));
+ pRADEONEnt->RestorePrimary = TRUE;
+ }
+ }
+
+#if 0
+ RADEONRestorePalette(pScrn, &info->SavedReg);
+#endif
+}
+
+/* Read common registers */
+static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ save->ovr_clr = INREG(RADEON_OVR_CLR);
+ save->ovr_wid_left_right = INREG(RADEON_OVR_WID_LEFT_RIGHT);
+ save->ovr_wid_top_bottom = INREG(RADEON_OVR_WID_TOP_BOTTOM);
+ save->ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL);
+ save->subpic_cntl = INREG(RADEON_SUBPIC_CNTL);
+ save->viph_control = INREG(RADEON_VIPH_CONTROL);
+ save->i2c_cntl_1 = INREG(RADEON_I2C_CNTL_1);
+ save->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL);
+ save->cap0_trig_cntl = INREG(RADEON_CAP0_TRIG_CNTL);
+ save->cap1_trig_cntl = INREG(RADEON_CAP1_TRIG_CNTL);
+ save->bus_cntl = INREG(RADEON_BUS_CNTL);
+ save->surface_cntl = INREG(RADEON_SURFACE_CNTL);
+}
+
+/* Read miscellaneous registers which might be destroyed by an fbdevHW call */
+static void RADEONSaveFBDevRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+#ifdef XF86DRI
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ /* Save register for vertical blank interrupts */
+ if (info->irq) {
+ save->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL);
+ }
+
+ /* Save registers for page flipping */
+ if (info->allowPageFlip) {
+ save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);
+ if (info->HasCRTC2) {
+ save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL);
+ }
+ }
+#endif
+}
+
+/* Read CRTC registers */
+static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL);
+ save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
+ save->dac_cntl = INREG(RADEON_DAC_CNTL);
+ save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP);
+ save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID);
+ save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP);
+ save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
+ save->crtc_offset = INREG(RADEON_CRTC_OFFSET);
+ save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);
+ save->crtc_pitch = INREG(RADEON_CRTC_PITCH);
+}
+
+/* Read flat panel registers */
+static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP);
+ save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP);
+ save->fp_gen_cntl = INREG(RADEON_FP_GEN_CNTL);
+ save->fp_h_sync_strt_wid = INREG(RADEON_FP_H_SYNC_STRT_WID);
+ save->fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH);
+ save->fp_v_sync_strt_wid = INREG(RADEON_FP_V_SYNC_STRT_WID);
+ save->fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH);
+ save->lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL);
+ save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL);
+ save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL);
+}
+
+/* Read CRTC2 registers */
+static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ save->dac2_cntl = INREG(RADEON_DAC_CNTL2);
+ save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+ save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG);
+
+ save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+ save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP);
+ save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+ save->crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
+ save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+ save->crtc2_offset = INREG(RADEON_CRTC2_OFFSET);
+ save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL);
+ save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH);
+
+ save->fp2_h_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID);
+ save->fp2_v_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID);
+ save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL);
+
+}
+
+/* Read PLL registers */
+static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV);
+ save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3);
+ save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL);
+
+ RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
+ save->ppll_ref_div,
+ save->ppll_div_3,
+ save->htotal_cntl));
+ RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n",
+ save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+ save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
+ (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16));
+}
+
+/* Read PLL registers */
+static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ save->p2pll_ref_div = INPLL(pScrn, RADEON_P2PLL_REF_DIV);
+ save->p2pll_div_0 = INPLL(pScrn, RADEON_P2PLL_DIV_0);
+ save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL);
+
+ RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
+ save->p2pll_ref_div,
+ save->p2pll_div_0,
+ save->htotal_cntl2));
+ RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n",
+ save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
+ save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK,
+ (save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >> 16));
+}
+
+/* Read palette data */
+static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int i;
+
+#ifdef ENABLE_FLAT_PANEL
+ /* Select palette 0 (main CRTC) if using FP-enabled chip */
+ /* if (info->Port1 == MT_DFP) PAL_SELECT(1); */
+#endif
+ PAL_SELECT(1);
+ INPAL_START(0);
+ for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
+ PAL_SELECT(0);
+ INPAL_START(0);
+ for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
+ save->palette_valid = TRUE;
+}
+
+/* Save state that defines current video mode */
+static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ RADEONTRACE(("RADEONSaveMode(%p)\n", save));
+ if (info->IsSecondary) {
+ RADEONSaveCrtc2Registers(pScrn, save);
+ RADEONSavePLL2Registers(pScrn, save);
+ } else {
+ RADEONSavePLLRegisters(pScrn, save);
+ RADEONSaveCommonRegisters(pScrn, save);
+ RADEONSaveCrtcRegisters(pScrn, save);
+
+ if ((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD)) {
+ RADEONSaveFPRegisters(pScrn, save);
+ }
+
+ if (info->Clone) {
+ RADEONSaveCrtc2Registers(pScrn, save);
+ RADEONSavePLL2Registers(pScrn, save);
+ }
+ /* RADEONSavePalette(pScrn, save); */
+ }
+
+ RADEONTRACE(("RADEONSaveMode returns %p\n", save));
+}
+
+/* Save everything needed to restore the original VC state */
+static void RADEONSave(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONSavePtr save = &info->SavedReg;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ RADEONTRACE(("RADEONSave\n"));
+ if (info->FBDev) {
+ fbdevHWSave(pScrn);
+ return;
+ }
+
+ if (!info->IsSecondary) {
+ vgaHWUnlock(hwp);
+#if defined(__powerpc__)
+ /* temporary hack to prevent crashing on PowerMacs when trying to
+ * read VGA fonts and colormap, will find a better solution
+ * in the future
+ */
+ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
+#else
+ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* Save mode
+ * & fonts & cmap
+ */
+#endif
+ vgaHWLock(hwp);
+ save->dp_datatype = INREG(RADEON_DP_DATATYPE);
+ save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
+ save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
+ if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ }
+
+ RADEONSaveMode(pScrn, save);
+}
+
+/* Restore the original (text) mode */
+static void RADEONRestore(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONSavePtr restore = &info->SavedReg;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ RADEONTRACE(("RADEONRestore\n"));
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ RADEONWaitForFifo(pScrn, 1);
+ OUTREG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE);
+#endif
+
+ if (info->FBDev) {
+ fbdevHWRestore(pScrn);
+ return;
+ }
+ RADEONBlank(pScrn);
+
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
+ if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset);
+ OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype);
+
+#if 0
+ /* M6 card has trouble restoring text mode for its CRT.
+ * This is fixed elsewhere and will be removed in the future.
+ */
+ if ((xf86IsEntityShared(pScrn->entityList[0]) || info->Clone)
+ && info->IsM6)
+ OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
+#endif
+
+ RADEONRestoreMode(pScrn, restore);
+
+#if 0
+ /* Temp fix to "solve" VT switch problems. When switching VTs on
+ * some systems, the console can either hang or the fonts can be
+ * corrupted. This hack solves the problem 99% of the time. A
+ * correct fix is being worked on.
+ */
+ usleep(100000);
+#endif
+
+ if (!info->IsSecondary) {
+ vgaHWUnlock(hwp);
+#if defined(__powerpc__)
+ /* Temporary hack to prevent crashing on PowerMacs when trying to
+ * write VGA fonts, will find a better solution in the future
+ */
+ vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
+#else
+ vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+#endif
+ vgaHWLock(hwp);
+ } else {
+ DevUnion *pPriv;
+ RADEONEntPtr pRADEONEnt;
+ ScrnInfoPtr pScrn0;
+ vgaHWPtr hwp0;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+
+ pScrn0 = pRADEONEnt->pPrimaryScrn;
+ hwp0 = VGAHWPTR(pScrn0);
+ vgaHWUnlock(hwp0);
+ vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+ vgaHWLock(hwp0);
+ }
+ RADEONUnblank(pScrn);
+
+#if 0
+ RADEONWaitForVerticalSync(pScrn);
+#endif
+}
+
+/* Define common registers for requested video mode */
+static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info)
+{
+ save->ovr_clr = 0;
+ save->ovr_wid_left_right = 0;
+ save->ovr_wid_top_bottom = 0;
+ save->ov0_scale_cntl = 0;
+ save->subpic_cntl = 0;
+ save->viph_control = 0;
+ save->i2c_cntl_1 = 0;
+ save->rbbm_soft_reset = 0;
+ save->cap0_trig_cntl = 0;
+ save->cap1_trig_cntl = 0;
+ save->bus_cntl = info->BusCntl;
+ /*
+ * If bursts are enabled, turn on discards
+ * Radeon doesn't have write bursts
+ */
+ if (save->bus_cntl & (RADEON_BUS_READ_BURST))
+ save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN;
+}
+
+/* Define CRTC registers for requested video mode */
+static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+ DisplayModePtr mode, RADEONInfoPtr info)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ int format;
+ int hsync_start;
+ int hsync_wid;
+ int hsync_fudge;
+ int vsync_wid;
+ int bytpp;
+ int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
+ int hsync_fudge_fp[] = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 };
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 4: format = 1; bytpp = 0; break;
+ case 8: format = 2; bytpp = 1; break;
+ case 15: format = 3; bytpp = 2; break; /* 555 */
+ case 16: format = 4; bytpp = 2; break; /* 565 */
+ case 24: format = 5; bytpp = 3; break; /* RGB */
+ case 32: format = 6; bytpp = 4; break; /* xRGB */
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unsupported pixel depth (%d)\n",
+ info->CurrentLayout.bitsPerPixel);
+ return FALSE;
+ }
+ RADEONTRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp));
+
+ if ((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD)) {
+ hsync_fudge = hsync_fudge_fp[format-1];
+ if (mode->Flags & RADEON_USE_RMX) {
+#if 0
+ mode->CrtcHDisplay = info->PanelXRes;
+ mode->CrtcVDisplay = info->PanelYRes;
+#endif
+ mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank;
+ mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus;
+ mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth;
+ mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank;
+ mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus;
+ mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth;
+ mode->Clock = info->DotClock;
+ mode->Flags = info->Flags | RADEON_USE_RMX;
+ }
+ } else {
+ hsync_fudge = hsync_fudge_default[format-1];
+ }
+
+ save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
+ | RADEON_CRTC_EN
+ | (format << 8)
+ | ((mode->Flags & V_DBLSCAN)
+ ? RADEON_CRTC_DBL_SCAN_EN
+ : 0)
+ | ((mode->Flags & V_CSYNC)
+ ? RADEON_CRTC_CSYNC_EN
+ : 0)
+ | ((mode->Flags & V_INTERLACE)
+ ? RADEON_CRTC_INTERLACE_EN
+ : 0));
+
+ if ((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD)) {
+ save->crtc_ext_cntl = RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN;
+ save->crtc_gen_cntl &= ~(RADEON_CRTC_DBL_SCAN_EN |
+ RADEON_CRTC_CSYNC_EN |
+ RADEON_CRTC_INTERLACE_EN);
+ } else {
+ save->crtc_ext_cntl = (RADEON_VGA_ATI_LINEAR |
+ RADEON_XCRT_CNT_EN |
+ RADEON_CRTC_CRT_ON);
+ }
+
+ save->dac_cntl = (RADEON_DAC_MASK_ALL
+ | RADEON_DAC_VGA_ADR_EN
+ | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
+
+ save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
+ | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
+ << 16));
+
+ hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
+ if (!hsync_wid) hsync_wid = 1;
+ hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
+
+ save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
+ | ((hsync_wid & 0x3f) << 16)
+ | ((mode->Flags & V_NHSYNC)
+ ? RADEON_CRTC_H_SYNC_POL
+ : 0));
+
+#if 1
+ /* This works for double scan mode. */
+ save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay - 1) << 16));
+#else
+ /* This is what cce/nbmode.c example code
+ * does -- is this correct?
+ */
+ save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay
+ * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
+ << 16));
+#endif
+
+ vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+ if (!vsync_wid) vsync_wid = 1;
+
+ save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
+ | ((vsync_wid & 0x1f) << 16)
+ | ((mode->Flags & V_NVSYNC)
+ ? RADEON_CRTC_V_SYNC_POL
+ : 0));
+
+ save->crtc_offset = 0;
+ save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);
+
+ save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
+ ((pScrn->bitsPerPixel * 8) -1)) /
+ (pScrn->bitsPerPixel * 8));
+ save->crtc_pitch |= save->crtc_pitch << 16;
+
+ save->surface_cntl = 0;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ switch (pScrn->bitsPerPixel) {
+ case 16:
+ save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP;
+ break;
+
+ case 32:
+ save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
+ break;
+ }
+#endif
+
+ RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
+ save->crtc_pitch, pScrn->virtualX,
+ info->CurrentLayout.displayWidth));
+ return TRUE;
+}
+
+/* Define CRTC2 registers for requested video mode */
+static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
+ DisplayModePtr mode, RADEONInfoPtr info)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ int format;
+ int hsync_start;
+ int hsync_wid;
+ int hsync_fudge;
+ int vsync_wid;
+ int bytpp;
+ int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 4: format = 1; bytpp = 0; break;
+ case 8: format = 2; bytpp = 1; break;
+ case 15: format = 3; bytpp = 2; break; /* 555 */
+ case 16: format = 4; bytpp = 2; break; /* 565 */
+ case 24: format = 5; bytpp = 3; break; /* RGB */
+ case 32: format = 6; bytpp = 4; break; /* xRGB */
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unsupported pixel depth (%d)\n",
+ info->CurrentLayout.bitsPerPixel);
+ return FALSE;
+ }
+ RADEONTRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp));
+
+ hsync_fudge = hsync_fudge_default[format-1];
+
+ save->crtc2_gen_cntl = (RADEON_CRTC2_EN
+ | RADEON_CRTC2_CRT2_ON
+ | (format << 8)
+ | ((mode->Flags & V_DBLSCAN)
+ ? RADEON_CRTC2_DBL_SCAN_EN
+ : 0)
+ | ((mode->Flags & V_CSYNC)
+ ? RADEON_CRTC2_CSYNC_EN
+ : 0)
+ | ((mode->Flags & V_INTERLACE)
+ ? RADEON_CRTC2_INTERLACE_EN
+ : 0));
+
+ /* Turn CRT on in case the first head is a DFP */
+ save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
+ save->dac2_cntl = info->SavedReg.dac2_cntl;
+ if (info->ChipFamily == CHIP_FAMILY_R200 ||
+ info->ChipFamily == CHIP_FAMILY_R300) {
+ save->disp_output_cntl =
+ ((info->SavedReg.disp_output_cntl
+ & ~(CARD32)RADEON_DISP_DAC_SOURCE_MASK)
+ | RADEON_DISP_DAC_SOURCE_CRTC2);
+ } else {
+ save->disp_hw_debug = info->SavedReg.disp_hw_debug;
+ if (info->IsDell && info->DellType == 2) {
+ if (info->DisplayType == MT_CRT || info->CloneType == MT_CRT) {
+ /* Turn on 2nd CRT */
+ save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+ save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+ save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
+
+ /* This will make 2nd CRT stay on in console */
+ info->SavedReg.dac2_cntl = save->dac2_cntl;
+ info->SavedReg.disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+ info->SavedReg.crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
+ }
+ } else save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL;
+ }
+
+ save->crtc2_h_total_disp =
+ ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
+ | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16));
+
+ hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
+ if (!hsync_wid) hsync_wid = 1;
+ hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
+
+ save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff)
+ | ((hsync_wid & 0x3f) << 16)
+ | ((mode->Flags & V_NHSYNC)
+ ? RADEON_CRTC_H_SYNC_POL
+ : 0));
+
+#if 1
+ /* This works for double scan mode. */
+ save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay - 1) << 16));
+#else
+ /* This is what cce/nbmode.c example code
+ * does -- is this correct?
+ */
+ save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
+ | ((mode->CrtcVDisplay
+ * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
+ << 16));
+#endif
+
+ vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+ if (!vsync_wid) vsync_wid = 1;
+
+ save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
+ | ((vsync_wid & 0x1f) << 16)
+ | ((mode->Flags & V_NVSYNC)
+ ? RADEON_CRTC2_V_SYNC_POL
+ : 0));
+
+ save->crtc2_offset = 0;
+ save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL);
+
+ save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) +
+ ((pScrn->bitsPerPixel * 8) -1)) /
+ (pScrn->bitsPerPixel * 8));
+ save->crtc2_pitch |= save->crtc2_pitch << 16;
+
+ if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) {
+ save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8));
+ save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid;
+ save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid;
+ save->fp2_gen_cntl = (RADEON_FP2_SEL_CRTC2 |
+ RADEON_FP2_PANEL_FORMAT |
+ RADEON_FP2_ON);
+
+ if (pScrn->rgbBits == 8)
+ save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format */
+ else
+ save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */
+
+ /* FIXME: When there are two DFPs, the 2nd DFP is driven by the
+ * external TMDS transmitter. It may have a problem at
+ * high dot clock for certain panels. Since we don't
+ * know how to control the external TMDS transmitter, not
+ * much we can do here.
+ */
+#if 0
+ if (save->dot_clock_freq > 15000)
+ save->tmds_pll_cntl = 0xA3F;
+ else if(save->tmds_pll_cntl != 0xA3F)
+ save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl;
+#endif
+
+ /* If BIOS has not turned it on, we'll keep it on so that we'll
+ * have a valid VGA screen even after X quits or VT is switched
+ * to the console mode.
+ */
+ info->SavedReg.fp2_gen_cntl = RADEON_FP2_ON;
+ }
+
+ RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
+ save->crtc2_pitch, pScrn->virtualX,
+ info->CurrentLayout.displayWidth));
+
+ return TRUE;
+}
+
+/* Define CRTC registers for requested video mode */
+static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
+ RADEONSavePtr save, DisplayModePtr mode,
+ RADEONInfoPtr info)
+{
+ int xres = mode->HDisplay;
+ int yres = mode->VDisplay;
+ float Hratio, Vratio;
+
+ if (info->PanelXRes == 0 || info->PanelYRes == 0) {
+ Hratio = 1.0;
+ Vratio = 1.0;
+ } else {
+ if (xres > info->PanelXRes) xres = info->PanelXRes;
+ if (yres > info->PanelYRes) yres = info->PanelYRes;
+
+ Hratio = (float)xres/(float)info->PanelXRes;
+ Vratio = (float)yres/(float)info->PanelYRes;
+ }
+
+ if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
+ save->fp_horz_stretch = orig->fp_horz_stretch;
+ save->fp_horz_stretch &= ~(RADEON_HORZ_STRETCH_BLEND |
+ RADEON_HORZ_STRETCH_ENABLE);
+ save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO |
+ RADEON_HORZ_PANEL_SIZE);
+ save->fp_horz_stretch |= ((xres/8-1)<<16);
+
+ } else {
+ save->fp_horz_stretch =
+ ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX +
+ 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK)) |
+ (orig->fp_horz_stretch & (RADEON_HORZ_PANEL_SIZE |
+ RADEON_HORZ_FP_LOOP_STRETCH |
+ RADEON_HORZ_AUTO_RATIO_INC));
+ save->fp_horz_stretch |= (RADEON_HORZ_STRETCH_BLEND |
+ RADEON_HORZ_STRETCH_ENABLE);
+
+ save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO |
+ RADEON_HORZ_PANEL_SIZE);
+ save->fp_horz_stretch |= ((info->PanelXRes / 8 - 1) << 16);
+
+ }
+
+ if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
+ save->fp_vert_stretch = orig->fp_vert_stretch;
+ save->fp_vert_stretch &= ~(RADEON_VERT_STRETCH_ENABLE|
+ RADEON_VERT_STRETCH_BLEND);
+ save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN |
+ RADEON_VERT_PANEL_SIZE);
+ save->fp_vert_stretch |= ((yres-1) << 12);
+ } else {
+ save->fp_vert_stretch =
+ (((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX +
+ 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK)) |
+ (orig->fp_vert_stretch & (RADEON_VERT_PANEL_SIZE |
+ RADEON_VERT_STRETCH_RESERVED)));
+ save->fp_vert_stretch |= (RADEON_VERT_STRETCH_ENABLE |
+ RADEON_VERT_STRETCH_BLEND);
+
+ save->fp_vert_stretch &= ~(RADEON_VERT_AUTO_RATIO_EN |
+ RADEON_VERT_PANEL_SIZE);
+ save->fp_vert_stretch |= ((info->PanelYRes-1) << 12);
+
+ }
+
+ save->fp_gen_cntl = (orig->fp_gen_cntl & (CARD32)
+ ~(RADEON_FP_SEL_CRTC2 |
+ RADEON_FP_RMX_HVSYNC_CONTROL_EN |
+ RADEON_FP_DFP_SYNC_SEL |
+ RADEON_FP_CRT_SYNC_SEL |
+ RADEON_FP_CRTC_LOCK_8DOT |
+ RADEON_FP_USE_SHADOW_EN |
+ RADEON_FP_CRTC_USE_SHADOW_VEND |
+ RADEON_FP_CRT_SYNC_ALT));
+ save->fp_gen_cntl |= (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
+ RADEON_FP_CRTC_DONT_SHADOW_HEND );
+
+ if (pScrn->rgbBits == 8)
+ save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */
+ else
+ save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
+
+ save->lvds_gen_cntl = orig->lvds_gen_cntl;
+ save->lvds_pll_cntl = orig->lvds_pll_cntl;
+
+ /* This is needed for some panel at high resolution (>=1600x1200)
+ */
+ if ((save->dot_clock_freq > 15000) &&
+ (info->ChipFamily != CHIP_FAMILY_R300))
+ save->tmds_pll_cntl = 0xA3F;
+ else
+ save->tmds_pll_cntl = orig->tmds_pll_cntl;
+
+ info->PanelOff = FALSE;
+ /* This option is used to force the ONLY DEVICE in XFConfig to use
+ * CRT port, instead of default DVI port.
+ */
+ if (xf86ReturnOptValBool(info->Options, OPTION_PANEL_OFF, FALSE)) {
+ info->PanelOff = TRUE;
+ }
+
+ if (info->PanelOff && info->Clone) {
+ info->OverlayOnCRTC2 = TRUE;
+ if (info->DisplayType == MT_LCD) {
+ /* Turning off LVDS_ON seems to make panel white blooming.
+ * For now we just turn off display data ???
+ */
+ save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS);
+ save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON);
+
+ } else if (info->DisplayType == MT_DFP)
+ save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+ } else {
+ if (info->DisplayType == MT_LCD) {
+ save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
+ save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+ } else if (info->DisplayType == MT_DFP)
+ save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+ }
+
+ save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
+ save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
+ save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid;
+ save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid;
+}
+
+/* Define PLL registers for requested video mode */
+static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONPLLPtr pll,
+ double dot_clock)
+{
+ unsigned long freq = dot_clock * 100;
+
+ struct {
+ int divider;
+ int bitvalue;
+ } *post_div, post_divs[] = {
+ /* From RAGE 128 VR/RAGE 128 GL Register
+ * Reference Manual (Technical Reference
+ * Manual P/N RRG-G04100-C Rev. 0.04), page
+ * 3-17 (PLL_DIV_[3:0]).
+ */
+ { 1, 0 }, /* VCLK_SRC */
+ { 2, 1 }, /* VCLK_SRC/2 */
+ { 4, 2 }, /* VCLK_SRC/4 */
+ { 8, 3 }, /* VCLK_SRC/8 */
+ { 3, 4 }, /* VCLK_SRC/3 */
+ { 16, 5 }, /* VCLK_SRC/16 */
+ { 6, 6 }, /* VCLK_SRC/6 */
+ { 12, 7 }, /* VCLK_SRC/12 */
+ { 0, 0 }
+ };
+
+ if (freq > pll->max_pll_freq) freq = pll->max_pll_freq;
+ if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ save->pll_output_freq = post_div->divider * freq;
+ if (save->pll_output_freq >= pll->min_pll_freq
+ && save->pll_output_freq <= pll->max_pll_freq) break;
+ }
+
+ save->dot_clock_freq = freq;
+ save->feedback_div = RADEONDiv(pll->reference_div
+ * save->pll_output_freq,
+ pll->reference_freq);
+ save->post_div = post_div->divider;
+
+ RADEONTRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
+ save->dot_clock_freq,
+ save->pll_output_freq,
+ save->feedback_div,
+ save->post_div));
+
+ save->ppll_ref_div = pll->reference_div;
+ save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16));
+ save->htotal_cntl = 0;
+}
+
+/* Define PLL2 registers for requested video mode */
+static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll,
+ double dot_clock)
+{
+ unsigned long freq = dot_clock * 100;
+
+ struct {
+ int divider;
+ int bitvalue;
+ } *post_div, post_divs[] = {
+ /* From RAGE 128 VR/RAGE 128 GL Register
+ * Reference Manual (Technical Reference
+ * Manual P/N RRG-G04100-C Rev. 0.04), page
+ * 3-17 (PLL_DIV_[3:0]).
+ */
+ { 1, 0 }, /* VCLK_SRC */
+ { 2, 1 }, /* VCLK_SRC/2 */
+ { 4, 2 }, /* VCLK_SRC/4 */
+ { 8, 3 }, /* VCLK_SRC/8 */
+ { 3, 4 }, /* VCLK_SRC/3 */
+ { 6, 6 }, /* VCLK_SRC/6 */
+ { 12, 7 }, /* VCLK_SRC/12 */
+ { 0, 0 }
+ };
+
+ if (freq > pll->max_pll_freq) freq = pll->max_pll_freq;
+ if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ save->pll_output_freq_2 = post_div->divider * freq;
+ if (save->pll_output_freq_2 >= pll->min_pll_freq
+ && save->pll_output_freq_2 <= pll->max_pll_freq) break;
+ }
+
+ save->dot_clock_freq_2 = freq;
+ save->feedback_div_2 = RADEONDiv(pll->reference_div
+ * save->pll_output_freq_2,
+ pll->reference_freq);
+ save->post_div_2 = post_div->divider;
+
+ RADEONTRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
+ save->dot_clock_freq_2,
+ save->pll_output_freq_2,
+ save->feedback_div_2,
+ save->post_div_2));
+
+ save->p2pll_ref_div = pll->reference_div;
+ save->p2pll_div_0 = (save->feedback_div_2 |
+ (post_div->bitvalue << 16));
+ save->htotal_cntl2 = 0;
+}
+
+#if 0
+/* Define initial palette for requested video mode. This doesn't do
+ * anything for XFree86 4.0.
+ */
+static void RADEONInitPalette(RADEONSavePtr save)
+{
+ save->palette_valid = FALSE;
+}
+#endif
+
+/* Define registers for a requested video mode */
+static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode,
+ RADEONSavePtr save)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ double dot_clock = mode->Clock/1000.0;
+
+#if RADEON_DEBUG
+ ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)",
+ mode->name,
+ dot_clock,
+
+ mode->HDisplay,
+ mode->HSyncStart,
+ mode->HSyncEnd,
+ mode->HTotal,
+
+ mode->VDisplay,
+ mode->VSyncStart,
+ mode->VSyncEnd,
+ mode->VTotal,
+ pScrn->depth,
+ pScrn->bitsPerPixel);
+ if (mode->Flags & V_DBLSCAN) ErrorF(" D");
+ if (mode->Flags & V_CSYNC) ErrorF(" C");
+ if (mode->Flags & V_INTERLACE) ErrorF(" I");
+ if (mode->Flags & V_PHSYNC) ErrorF(" +H");
+ if (mode->Flags & V_NHSYNC) ErrorF(" -H");
+ if (mode->Flags & V_PVSYNC) ErrorF(" +V");
+ if (mode->Flags & V_NVSYNC) ErrorF(" -V");
+ ErrorF("\n");
+ ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)",
+ mode->name,
+ dot_clock,
+
+ mode->CrtcHDisplay,
+ mode->CrtcHSyncStart,
+ mode->CrtcHSyncEnd,
+ mode->CrtcHTotal,
+
+ mode->CrtcVDisplay,
+ mode->CrtcVSyncStart,
+ mode->CrtcVSyncEnd,
+ mode->CrtcVTotal,
+ pScrn->depth,
+ pScrn->bitsPerPixel);
+ if (mode->Flags & V_DBLSCAN) ErrorF(" D");
+ if (mode->Flags & V_CSYNC) ErrorF(" C");
+ if (mode->Flags & V_INTERLACE) ErrorF(" I");
+ if (mode->Flags & V_PHSYNC) ErrorF(" +H");
+ if (mode->Flags & V_NHSYNC) ErrorF(" -H");
+ if (mode->Flags & V_PVSYNC) ErrorF(" +V");
+ if (mode->Flags & V_NVSYNC) ErrorF(" -V");
+ ErrorF("\n");
+#endif
+
+ info->Flags = mode->Flags;
+
+ if (info->IsSecondary) {
+ if (!RADEONInitCrtc2Registers(pScrn, save, mode, info))
+ return FALSE;
+ RADEONInitPLL2Registers(save, &info->pll, dot_clock);
+ } else {
+ RADEONInitCommonRegisters(save, info);
+ if (!RADEONInitCrtcRegisters(pScrn, save, mode, info))
+ return FALSE;
+ dot_clock = mode->Clock/1000.0;
+ if (dot_clock) {
+ RADEONInitPLLRegisters(save, &info->pll, dot_clock);
+ } else {
+ save->ppll_ref_div = info->SavedReg.ppll_ref_div;
+ save->ppll_div_3 = info->SavedReg.ppll_div_3;
+ save->htotal_cntl = info->SavedReg.htotal_cntl;
+ }
+
+ if (info->Clone && info->CurCloneMode) {
+ RADEONInitCrtc2Registers(pScrn, save, info->CurCloneMode, info);
+ dot_clock = info->CurCloneMode->Clock / 1000.0;
+ RADEONInitPLL2Registers(save, &info->pll, dot_clock);
+ }
+ /* Not used for now: */
+ /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */
+ }
+
+ if (((info->DisplayType == MT_DFP) ||
+ (info->DisplayType == MT_LCD))) {
+ RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info);
+ }
+
+ RADEONTRACE(("RADEONInit returns %p\n", save));
+ return TRUE;
+}
+
+/* Initialize a new mode */
+static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE;
+
+ pScrn->vtSema = TRUE;
+ RADEONBlank(pScrn);
+ RADEONRestoreMode(pScrn, &info->ModeReg);
+ RADEONUnblank(pScrn);
+
+ info->CurrentLayout.mode = mode;
+ return TRUE;
+}
+
+static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool unblank;
+
+ unblank = xf86IsUnblank(mode);
+ if (unblank) SetTimeSinceLastInputEvent();
+
+ if ((pScrn != NULL) && pScrn->vtSema) {
+ if (unblank) RADEONUnblank(pScrn);
+ else RADEONBlank(pScrn);
+ }
+ return TRUE;
+}
+
+Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ Bool ret;
+#ifdef XF86DRI
+ Bool CPStarted = info->CPStarted;
+
+ if (CPStarted) {
+ DRILock(pScrn->pScreen, 0);
+ RADEONCP_STOP(pScrn, info);
+ }
+#endif
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ if (info->FBDev) {
+ RADEONSaveFBDevRegisters(pScrn, &info->ModeReg);
+
+ ret = fbdevHWSwitchMode(scrnIndex, mode, flags);
+
+ RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg);
+ } else {
+ info->IsSwitching = TRUE;
+ if (info->Clone && info->CloneModes) {
+ DisplayModePtr clone_mode = info->CloneModes;
+
+ /* Try to match a mode on primary head
+ * FIXME: This may not be good if both heads don't have
+ * exactly the same list of mode.
+ */
+ while (1) {
+ if ((clone_mode->HDisplay == mode->HDisplay) &&
+ (clone_mode->VDisplay == mode->VDisplay) &&
+ (!info->PanelOff)) {
+ info->CloneFrameX0 = (info->CurCloneMode->HDisplay +
+ info->CloneFrameX0 -
+ clone_mode->HDisplay - 1) / 2;
+ info->CloneFrameY0 =
+ (info->CurCloneMode->VDisplay + info->CloneFrameY0 -
+ clone_mode->VDisplay - 1) / 2;
+ info->CurCloneMode = clone_mode;
+ break;
+ }
+
+ if (!clone_mode->next) {
+ info->CurCloneMode = info->CloneModes;
+ break;
+ }
+
+ clone_mode = clone_mode->next;
+ }
+ }
+ ret = RADEONModeInit(xf86Screens[scrnIndex], mode);
+
+ if (info->CurCloneMode) {
+ if (info->CloneFrameX0 + info->CurCloneMode->HDisplay >=
+ pScrn->virtualX)
+ info->CloneFrameX0 =
+ pScrn->virtualX - info->CurCloneMode->HDisplay;
+ else if (info->CloneFrameX0 < 0)
+ info->CloneFrameX0 = 0;
+
+ if (info->CloneFrameY0 + info->CurCloneMode->VDisplay >=
+ pScrn->virtualY)
+ info->CloneFrameY0 =
+ pScrn->virtualY - info->CurCloneMode->VDisplay;
+ else if (info->CloneFrameY0 < 0)
+ info->CloneFrameY0 = 0;
+
+ RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0,
+ TRUE);
+ }
+
+ info->IsSwitching = FALSE;
+ }
+
+ if (info->accelOn) {
+ info->accel->Sync(pScrn);
+ RADEONEngineRestore(pScrn);
+ }
+
+#ifdef XF86DRI
+ if (CPStarted) {
+ RADEONCP_START(pScrn, info);
+ DRIUnlock(pScrn->pScreen);
+ }
+#endif
+
+ return ret;
+}
+
+/* Used to disallow modes that are not supported by the hardware */
+int RADEONValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flag)
+{
+ /* Searching for native mode timing table embedded in BIOS image.
+ * Not working yet. Currently we calculate from FP registers
+ */
+
+ return MODE_OK;
+}
+
+/* Adjust viewport into virtual desktop such that (0,0) in viewport
+ * space is (x,y) in virtual space.
+ */
+void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int reg, Base = y * info->CurrentLayout.displayWidth + x;
+#ifdef XF86DRI
+ RADEONSAREAPrivPtr pSAREAPriv;
+#endif
+
+ switch (info->CurrentLayout.pixel_code) {
+ case 15:
+ case 16: Base *= 2; break;
+ case 24: Base *= 3; break;
+ case 32: Base *= 4; break;
+ }
+
+ Base &= ~7; /* 3 lower bits are always 0 */
+
+ if (clone || info->IsSecondary) {
+ Base += pScrn->fbOffset;
+ reg = RADEON_CRTC2_OFFSET;
+ } else {
+ reg = RADEON_CRTC_OFFSET;
+ }
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+
+ pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+ if (pSAREAPriv->pfCurrentPage == 1) {
+ Base += info->backOffset;
+ }
+
+ if (clone || info->IsSecondary) {
+ pSAREAPriv->crtc2_base = Base;
+ }
+ }
+#endif
+
+ OUTREG(reg, Base);
+}
+
+void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRILock(pScrn->pScreen, 0);
+#endif
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ if (info->FBDev) {
+ fbdevHWAdjustFrame(scrnIndex, x, y, flags);
+ } else {
+ RADEONDoAdjustFrame(pScrn, x, y, FALSE);
+ }
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRIUnlock(pScrn->pScreen);
+#endif
+}
+
+/* Called when VT switching back to the X server. Reinitialize the
+ * video mode.
+ */
+Bool RADEONEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ RADEONTRACE(("RADEONEnterVT\n"));
+
+ if (info->FBDev) {
+ unsigned char *RADEONMMIO = info->MMIO;
+ if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
+ info->PaletteSavedOnVT = FALSE;
+ info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
+
+ RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg);
+ } else
+ if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
+
+ if (info->accelOn)
+ RADEONEngineRestore(pScrn);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONCP_START(pScrn, info);
+ DRIUnlock(pScrn->pScreen);
+ }
+#endif
+
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ if (info->CurCloneMode) {
+ RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE);
+ }
+
+ return TRUE;
+}
+
+/* Called when VT switching away from the X server. Restore the
+ * original text mode.
+ */
+void RADEONLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONSavePtr save = &info->ModeReg;
+
+ RADEONTRACE(("RADEONLeaveVT\n"));
+#ifdef XF86DRI
+ if (RADEONPTR(pScrn)->directRenderingEnabled) {
+ DRILock(pScrn->pScreen, 0);
+ RADEONCP_STOP(pScrn, info);
+ }
+#endif
+
+ if (info->FBDev) {
+ RADEONSavePalette(pScrn, save);
+ info->PaletteSavedOnVT = TRUE;
+
+ RADEONSaveFBDevRegisters(pScrn, &info->ModeReg);
+
+ fbdevHWLeaveVT(scrnIndex,flags);
+ }
+
+ RADEONRestore(pScrn);
+}
+
+/* Called at the end of each server generation. Restore the original
+ * text mode, unmap video memory, and unwrap and call the saved
+ * CloseScreen function.
+ */
+static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ RADEONTRACE(("RADEONCloseScreen\n"));
+
+#ifdef XF86DRI
+ /* Disable direct rendering */
+ if (info->directRenderingEnabled) {
+ RADEONDRICloseScreen(pScreen);
+ info->directRenderingEnabled = FALSE;
+ }
+#endif
+
+ if (pScrn->vtSema) {
+ RADEONRestore(pScrn);
+ RADEONUnmapMem(pScrn);
+ }
+
+ if (info->accel) XAADestroyInfoRec(info->accel);
+ info->accel = NULL;
+
+ if (info->scratch_save) xfree(info->scratch_save);
+ info->scratch_save = NULL;
+
+ if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
+ info->cursor = NULL;
+
+ if (info->DGAModes) xfree(info->DGAModes);
+ info->DGAModes = NULL;
+
+ if (info->CloneModes)
+ while (info->CloneModes)
+ xf86DeleteMode(&info->CloneModes, info->CloneModes);
+
+ pScrn->vtSema = FALSE;
+
+ xf86ClearPrimInitDone(pScrn->entityList[0]);
+
+ pScreen->BlockHandler = info->BlockHandler;
+ pScreen->CloseScreen = info->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+void RADEONFreeScreen(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ RADEONTRACE(("RADEONFreeScreen\n"));
+
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(pScrn);
+ RADEONFreeRec(pScrn);
+}
+
+/* Sets VESA Display Power Management Signaling (DPMS) Mode */
+static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode,
+ int flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRILock(pScrn->pScreen, 0);
+#endif
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ if (info->FBDev) {
+ fbdevHWDPMSSet(pScrn, PowerManagementMode, flags);
+ } else {
+ int mask1 = (RADEON_CRTC_DISPLAY_DIS |
+ RADEON_CRTC_HSYNC_DIS |
+ RADEON_CRTC_VSYNC_DIS);
+ int mask2 = (RADEON_CRTC2_DISP_DIS |
+ RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS);
+
+ /* TODO: additional handling for LCD ? */
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ if (info->IsSecondary)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2);
+ else {
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2);
+ OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1);
+ }
+ break;
+
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ if (info->IsSecondary)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS,
+ ~mask2);
+ else {
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS,
+ ~mask2);
+ OUTREGP(RADEON_CRTC_EXT_CNTL,
+ RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS,
+ ~mask1);
+ }
+ break;
+
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ if (info->IsSecondary)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS,
+ ~mask2);
+ else {
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL,
+ RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS,
+ ~mask2);
+ OUTREGP(RADEON_CRTC_EXT_CNTL,
+ RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS,
+ ~mask1);
+ }
+ break;
+
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ if (info->IsSecondary)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2);
+ else {
+ if (info->Clone)
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2);
+ OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1);
+ }
+ break;
+ }
+ }
+
+#ifdef XF86DRI
+ if (info->CPStarted) DRIUnlock(pScrn->pScreen);
+#endif
+}
diff --git a/src/radeon_macros.h b/src/radeon_macros.h
new file mode 100644
index 0000000..a271933
--- /dev/null
+++ b/src/radeon_macros.h
@@ -0,0 +1,134 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h,v 1.1 2002/12/16 16:19:14 dawes Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+
+#ifndef _RADEON_MACROS_H_
+#define _RADEON_MACROS_H_
+
+#ifdef XFree86Module
+#include "xf86_ansic.h"
+#endif
+#include "compiler.h"
+
+ /* Memory mapped register access macros */
+#define INREG8(addr) MMIO_IN8(RADEONMMIO, addr)
+#define INREG16(addr) MMIO_IN16(RADEONMMIO, addr)
+#define INREG(addr) MMIO_IN32(RADEONMMIO, addr)
+#define OUTREG8(addr, val) MMIO_OUT8(RADEONMMIO, addr, val)
+#define OUTREG16(addr, val) MMIO_OUT16(RADEONMMIO, addr, val)
+#define OUTREG(addr, val) MMIO_OUT32(RADEONMMIO, addr, val)
+
+#define ADDRREG(addr) ((volatile CARD32 *)(pointer)(RADEONMMIO + (addr)))
+
+
+#define OUTREGP(addr, val, mask) \
+do { \
+ CARD32 tmp = INREG(addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTREG(addr, tmp); \
+} while (0)
+
+#define INPLL(pScrn, addr) RADEONINPLL(pScrn, addr)
+
+#define OUTPLL(addr, val) \
+do { \
+ OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \
+ RADEON_PLL_WR_EN)); \
+ OUTREG(RADEON_CLOCK_CNTL_DATA, val); \
+} while (0)
+
+#define OUTPLLP(pScrn, addr, val, mask) \
+do { \
+ CARD32 tmp = INPLL(pScrn, addr); \
+ tmp &= (mask); \
+ tmp |= (val); \
+ OUTPLL(addr, tmp); \
+} while (0)
+
+#define OUTPAL_START(idx) \
+do { \
+ OUTREG8(RADEON_PALETTE_INDEX, (idx)); \
+} while (0)
+
+#define OUTPAL_NEXT(r, g, b) \
+do { \
+ OUTREG(RADEON_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
+} while (0)
+
+#define OUTPAL_NEXT_CARD32(v) \
+do { \
+ OUTREG(RADEON_PALETTE_DATA, (v & 0x00ffffff)); \
+} while (0)
+
+#define OUTPAL(idx, r, g, b) \
+do { \
+ OUTPAL_START((idx)); \
+ OUTPAL_NEXT((r), (g), (b)); \
+} while (0)
+
+#define INPAL_START(idx) \
+do { \
+ OUTREG(RADEON_PALETTE_INDEX, (idx) << 16); \
+} while (0)
+
+#define INPAL_NEXT() INREG(RADEON_PALETTE_DATA)
+
+#define PAL_SELECT(idx) \
+do { \
+ if (!idx) { \
+ OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) & \
+ (CARD32)~RADEON_DAC2_PALETTE_ACC_CTL); \
+ } else { \
+ OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) | \
+ RADEON_DAC2_PALETTE_ACC_CTL); \
+ } \
+} while (0)
+
+
+#endif
diff --git a/src/radeon_misc.c b/src/radeon_misc.c
new file mode 100644
index 0000000..d9c978f
--- /dev/null
+++ b/src/radeon_misc.c
@@ -0,0 +1,86 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_misc.c,v 1.7 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef XFree86LOADER
+
+#include "ativersion.h"
+
+#include "radeon_probe.h"
+#include "radeon_version.h"
+
+#include "xf86.h"
+
+/* Module loader interface for subsidiary driver module */
+
+static XF86ModuleVersionInfo RADEONVersionRec =
+{
+ RADEON_DRIVER_NAME,
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ RADEON_VERSION_MAJOR, RADEON_VERSION_MINOR, RADEON_VERSION_PATCH,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * RADEONSetup --
+ *
+ * This function is called every time the module is loaded.
+ */
+static pointer
+RADEONSetup
+(
+ pointer Module,
+ pointer Options,
+ int *ErrorMajor,
+ int *ErrorMinor
+)
+{
+ static Bool Inited = FALSE;
+
+ if (!Inited) {
+ /* Ensure main driver module is loaded, but not as a submodule */
+ if (!xf86ServerIsOnlyDetecting() && !LoaderSymbol(ATI_NAME))
+ xf86LoadOneModule(ATI_DRIVER_NAME, Options);
+
+ RADEONLoaderRefSymLists();
+
+ Inited = TRUE;
+ }
+
+ return (pointer)TRUE;
+}
+
+/* The following record must be called radeonModuleData */
+XF86ModuleData radeonModuleData =
+{
+ &RADEONVersionRec,
+ RADEONSetup,
+ NULL
+};
+
+#endif /* XFree86LOADER */
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
new file mode 100644
index 0000000..bcf80c1
--- /dev/null
+++ b/src/radeon_probe.c
@@ -0,0 +1,333 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.24 2003/02/07 20:41:15 martin Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ *
+ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
+ */
+
+#include "atimodule.h"
+#include "ativersion.h"
+
+#include "radeon_probe.h"
+#include "radeon_version.h"
+
+#include "xf86PciInfo.h"
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86Resources.h"
+
+#ifdef XFree86LOADER
+
+/*
+ * The following exists to prevent the compiler from considering entry points
+ * defined in a separate module from being constants.
+ */
+static xf86PreInitProc *const volatile PreInitProc = RADEONPreInit;
+static xf86ScreenInitProc *const volatile ScreenInitProc = RADEONScreenInit;
+static xf86SwitchModeProc *const volatile SwitchModeProc = RADEONSwitchMode;
+static xf86AdjustFrameProc *const volatile AdjustFrameProc = RADEONAdjustFrame;
+static xf86EnterVTProc *const volatile EnterVTProc = RADEONEnterVT;
+static xf86LeaveVTProc *const volatile LeaveVTProc = RADEONLeaveVT;
+static xf86FreeScreenProc *const volatile FreeScreenProc = RADEONFreeScreen;
+static xf86ValidModeProc *const volatile ValidModeProc = RADEONValidMode;
+
+#define RADEONPreInit PreInitProc
+#define RADEONScreenInit ScreenInitProc
+#define RADEONSwitchMode SwitchModeProc
+#define RADEONAdjustFrame AdjustFrameProc
+#define RADEONEnterVT EnterVTProc
+#define RADEONLeaveVT LeaveVTProc
+#define RADEONFreeScreen FreeScreenProc
+#define RADEONValidMode ValidModeProc
+
+#endif
+
+SymTabRec RADEONChipsets[] = {
+ { PCI_CHIP_RADEON_QD, "ATI Radeon QD (AGP)" },
+ { PCI_CHIP_RADEON_QE, "ATI Radeon QE (AGP)" },
+ { PCI_CHIP_RADEON_QF, "ATI Radeon QF (AGP)" },
+ { PCI_CHIP_RADEON_QG, "ATI Radeon QG (AGP)" },
+ { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP)" },
+ { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP)" },
+ { PCI_CHIP_RADEON_LW, "ATI Radeon Mobility M7 LW (AGP)" },
+ { PCI_CHIP_RADEON_LX, "ATI Mobility FireGL 7800 M7 LX (AGP)" },
+ { PCI_CHIP_RADEON_LY, "ATI Radeon Mobility M6 LY (AGP)" },
+ { PCI_CHIP_RADEON_LZ, "ATI Radeon Mobility M6 LZ (AGP)" },
+ { PCI_CHIP_R200_QH, "ATI FireGL 8700/8800 QH (AGP)" },
+ { PCI_CHIP_R200_QI, "ATI Radeon 8500 QI (AGP)" },
+ { PCI_CHIP_R200_QJ, "ATI Radeon 8500 QJ (AGP)" },
+ { PCI_CHIP_R200_QK, "ATI Radeon 8500 QK (AGP)" },
+ { PCI_CHIP_R200_QL, "ATI Radeon 8500 QL (AGP)" },
+ { PCI_CHIP_R200_QM, "ATI Radeon 9100 QM (AGP)" },
+ { PCI_CHIP_R200_QN, "ATI Radeon 8500 QN (AGP)" },
+ { PCI_CHIP_R200_QO, "ATI Radeon 8500 QO (AGP)" },
+ { PCI_CHIP_R200_Qh, "ATI Radeon 8500 Qh (AGP)" },
+ { PCI_CHIP_R200_Qi, "ATI Radeon 8500 Qi (AGP)" },
+ { PCI_CHIP_R200_Qj, "ATI Radeon 8500 Qj (AGP)" },
+ { PCI_CHIP_R200_Qk, "ATI Radeon 8500 Qk (AGP)" },
+ { PCI_CHIP_R200_Ql, "ATI Radeon 8500 Ql (AGP)" },
+ { PCI_CHIP_R200_BB, "ATI Radeon 8500 BB (AGP)" },
+ { PCI_CHIP_RV200_QW, "ATI Radeon 7500 QW (AGP)" },
+ { PCI_CHIP_RV200_QX, "ATI Radeon 7500 QX (AGP)" },
+ { PCI_CHIP_RV250_Id, "ATI Radeon 9000 Id (AGP)" },
+ { PCI_CHIP_RV250_Ie, "ATI Radeon 9000 Ie (AGP)" },
+ { PCI_CHIP_RV250_If, "ATI Radeon 9000 If (AGP)" },
+ { PCI_CHIP_RV250_Ig, "ATI Radeon 9000 Ig (AGP)" },
+ { PCI_CHIP_RV250_Ld, "ATI Radeon Mobility M9 Ld (AGP)" },
+ { PCI_CHIP_RV250_Le, "ATI Radeon Mobility M9 Le (AGP)" },
+ { PCI_CHIP_RV250_Lf, "ATI Radeon Mobility M9 Lf (AGP)" },
+ { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility M9 Lg (AGP)" },
+ { PCI_CHIP_R300_AD, "ATI Radeon 9500 AD (AGP)" },
+ { PCI_CHIP_R300_AE, "ATI Radeon 9500 AE (AGP)" },
+ { PCI_CHIP_R300_AF, "ATI Radeon 9500 AF (AGP)" },
+ { PCI_CHIP_R300_AG, "ATI FireGL Z1/X1 AG (AGP)" },
+ { PCI_CHIP_R300_ND, "ATI Radeon 9700 Pro ND (AGP)" },
+ { PCI_CHIP_R300_NE, "ATI Radeon 9700/9500Pro NE (AGP)" },
+ { PCI_CHIP_R300_NF, "ATI Radeon 9700 NF (AGP)" },
+ { PCI_CHIP_R300_NG, "ATI FireGL X1 NG (AGP)" },
+ { -1, NULL }
+};
+
+PciChipsets RADEONPciChipsets[] = {
+ { PCI_CHIP_RADEON_QD, PCI_CHIP_RADEON_QD, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_QE, PCI_CHIP_RADEON_QE, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_QF, PCI_CHIP_RADEON_QF, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_QG, PCI_CHIP_RADEON_QG, RES_SHARED_VGA },
+ { PCI_CHIP_RV100_QY, PCI_CHIP_RV100_QY, RES_SHARED_VGA },
+ { PCI_CHIP_RV100_QZ, PCI_CHIP_RV100_QZ, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_LW, PCI_CHIP_RADEON_LW, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_LX, PCI_CHIP_RADEON_LX, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_LY, PCI_CHIP_RADEON_LY, RES_SHARED_VGA },
+ { PCI_CHIP_RADEON_LZ, PCI_CHIP_RADEON_LZ, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QH, PCI_CHIP_R200_QH, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QI, PCI_CHIP_R200_QI, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QJ, PCI_CHIP_R200_QJ, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QK, PCI_CHIP_R200_QK, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QL, PCI_CHIP_R200_QL, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QM, PCI_CHIP_R200_QM, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QN, PCI_CHIP_R200_QN, RES_SHARED_VGA },
+ { PCI_CHIP_R200_QO, PCI_CHIP_R200_QO, RES_SHARED_VGA },
+ { PCI_CHIP_R200_Qh, PCI_CHIP_R200_Qh, RES_SHARED_VGA },
+ { PCI_CHIP_R200_Qi, PCI_CHIP_R200_Qi, RES_SHARED_VGA },
+ { PCI_CHIP_R200_Qj, PCI_CHIP_R200_Qj, RES_SHARED_VGA },
+ { PCI_CHIP_R200_Qk, PCI_CHIP_R200_Qk, RES_SHARED_VGA },
+ { PCI_CHIP_R200_Ql, PCI_CHIP_R200_Ql, RES_SHARED_VGA },
+ { PCI_CHIP_R200_BB, PCI_CHIP_R200_BB, RES_SHARED_VGA },
+ { PCI_CHIP_RV200_QW, PCI_CHIP_RV200_QW, RES_SHARED_VGA },
+ { PCI_CHIP_RV200_QX, PCI_CHIP_RV200_QX, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Id, PCI_CHIP_RV250_Id, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Ie, PCI_CHIP_RV250_Ie, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_If, PCI_CHIP_RV250_If, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Ig, PCI_CHIP_RV250_Ig, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Ld, PCI_CHIP_RV250_Ld, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Le, PCI_CHIP_RV250_Le, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Lf, PCI_CHIP_RV250_Lf, RES_SHARED_VGA },
+ { PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA },
+ { PCI_CHIP_R300_AD, PCI_CHIP_R300_AD, RES_SHARED_VGA },
+ { PCI_CHIP_R300_AE, PCI_CHIP_R300_AE, RES_SHARED_VGA },
+ { PCI_CHIP_R300_AF, PCI_CHIP_R300_AF, RES_SHARED_VGA },
+ { PCI_CHIP_R300_AG, PCI_CHIP_R300_AG, RES_SHARED_VGA },
+ { PCI_CHIP_R300_ND, PCI_CHIP_R300_ND, RES_SHARED_VGA },
+ { PCI_CHIP_R300_NE, PCI_CHIP_R300_NE, RES_SHARED_VGA },
+ { PCI_CHIP_R300_NF, PCI_CHIP_R300_NF, RES_SHARED_VGA },
+ { PCI_CHIP_R300_NG, PCI_CHIP_R300_NG, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+int gRADEONEntityIndex = -1;
+
+/* Return the options for supported chipset 'n'; NULL otherwise */
+const OptionInfoRec *
+RADEONAvailableOptions(int chipid, int busid)
+{
+ int i;
+
+ /*
+ * Return options defined in the radeon submodule which will have been
+ * loaded by this point.
+ */
+ if ((chipid >> 16) == PCI_VENDOR_ATI)
+ chipid -= PCI_VENDOR_ATI << 16;
+ for (i = 0; RADEONPciChipsets[i].PCIid > 0; i++) {
+ if (chipid == RADEONPciChipsets[i].PCIid)
+ return RADEONOptions;
+ }
+ return NULL;
+}
+
+/* Return the string name for supported chipset 'n'; NULL otherwise. */
+void
+RADEONIdentify(int flags)
+{
+ xf86PrintChipsets(RADEON_NAME,
+ "Driver for ATI Radeon chipsets",
+ RADEONChipsets);
+}
+
+/* Return TRUE if chipset is present; FALSE otherwise. */
+Bool
+RADEONProbe(DriverPtr drv, int flags)
+{
+ int numUsed;
+ int numDevSections, nATIGDev, nRadeonGDev;
+ int *usedChips;
+ GDevPtr *devSections, *ATIGDevs, *RadeonGDevs;
+ Bool foundScreen = FALSE;
+ int i;
+
+ if (!xf86GetPciVideoInfo()) return FALSE;
+
+ /* Collect unclaimed device sections for both driver names */
+ nATIGDev = xf86MatchDevice(ATI_NAME, &ATIGDevs);
+ nRadeonGDev = xf86MatchDevice(RADEON_NAME, &RadeonGDevs);
+
+ if (!(numDevSections = nATIGDev + nRadeonGDev)) return FALSE;
+
+ if (!ATIGDevs) {
+ if (!(devSections = RadeonGDevs)) numDevSections = 1;
+ else numDevSections = nRadeonGDev;
+ } if (!RadeonGDevs) {
+ devSections = ATIGDevs;
+ numDevSections = nATIGDev;
+ } else {
+ /* Combine into one list */
+ devSections = xnfalloc((numDevSections + 1) * sizeof(GDevPtr));
+ (void)memcpy(devSections,
+ ATIGDevs, nATIGDev * sizeof(GDevPtr));
+ (void)memcpy(devSections + nATIGDev,
+ RadeonGDevs, nRadeonGDev * sizeof(GDevPtr));
+ devSections[numDevSections] = NULL;
+ xfree(ATIGDevs);
+ xfree(RadeonGDevs);
+ }
+
+ numUsed = xf86MatchPciInstances(RADEON_NAME,
+ PCI_VENDOR_ATI,
+ RADEONChipsets,
+ RADEONPciChipsets,
+ devSections,
+ numDevSections,
+ drv,
+ &usedChips);
+
+ if (numUsed <= 0) return FALSE;
+
+ if (flags & PROBE_DETECT) {
+ foundScreen = TRUE;
+ } else {
+ for (i = 0; i < numUsed; i++) {
+ ScrnInfoPtr pScrn = NULL;
+ EntityInfoPtr pEnt;
+
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ RADEONPciChipsets, 0, 0, 0,
+ 0, 0))) {
+#ifdef XFree86LOADER
+ if (!xf86LoadSubModule(pScrn, "radeon")) {
+ xf86Msg(X_ERROR, RADEON_NAME
+ ": Failed to load \"radeon\" module.\n");
+ xf86DeleteScreen(pScrn->scrnIndex, 0);
+ continue;
+ }
+
+ xf86LoaderReqSymLists(RADEONSymbols, NULL);
+#endif
+
+ pScrn->driverVersion = RADEON_VERSION_CURRENT;
+ pScrn->driverName = RADEON_DRIVER_NAME;
+ pScrn->name = RADEON_NAME;
+ pScrn->Probe = RADEONProbe;
+ pScrn->PreInit = RADEONPreInit;
+ pScrn->ScreenInit = RADEONScreenInit;
+ pScrn->SwitchMode = RADEONSwitchMode;
+ pScrn->AdjustFrame = RADEONAdjustFrame;
+ pScrn->EnterVT = RADEONEnterVT;
+ pScrn->LeaveVT = RADEONLeaveVT;
+ pScrn->FreeScreen = RADEONFreeScreen;
+ pScrn->ValidMode = RADEONValidMode;
+ foundScreen = TRUE;
+ }
+
+ pEnt = xf86GetEntityInfo(usedChips[i]);
+
+ /* All Radeon chips except the original ones support
+ * Dual-Head, mark the entity as sharable.
+ */
+ if (pEnt->chipset != PCI_CHIP_RADEON_QD &&
+ pEnt->chipset != PCI_CHIP_RADEON_QE &&
+ pEnt->chipset != PCI_CHIP_RADEON_QF &&
+ pEnt->chipset != PCI_CHIP_RADEON_QG) {
+ static int instance = 0;
+ DevUnion *pPriv;
+
+ xf86SetEntitySharable(usedChips[i]);
+ xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
+ instance);
+
+ if (gRADEONEntityIndex < 0) {
+ gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+
+ if (!pPriv->ptr) {
+ RADEONEntPtr pRADEONEnt;
+
+ pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
+ pRADEONEnt = pPriv->ptr;
+ pRADEONEnt->IsDRIEnabled = FALSE;
+ pRADEONEnt->BypassSecondary = FALSE;
+ pRADEONEnt->HasSecondary = FALSE;
+ pRADEONEnt->IsSecondaryRestored = FALSE;
+ }
+ }
+ instance++;
+ if (instance == 2) {
+ RADEONEntPtr pRADEONEnt;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gRADEONEntityIndex);
+ pRADEONEnt = pPriv->ptr;
+ pRADEONEnt->HasSecondary = TRUE;
+ }
+
+ }
+ xfree(pEnt);
+ }
+ }
+
+ xfree(usedChips);
+ xfree(devSections);
+
+ return foundScreen;
+}
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
new file mode 100644
index 0000000..34e5e86
--- /dev/null
+++ b/src/radeon_probe.h
@@ -0,0 +1,96 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h,v 1.8 2002/04/24 16:20:40 martin Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ *
+ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
+ */
+
+#ifndef _RADEON_PROBE_H_
+#define _RADEON_PROBE_H_ 1
+
+#include "atiproto.h"
+
+#include "xf86str.h"
+
+typedef struct
+{
+ Bool IsDRIEnabled;
+
+ Bool HasSecondary;
+ Bool BypassSecondary;
+
+ /*
+ * The next two are used to make sure CRTC2 is restored before CRTC_EXT,
+ * otherwise it could lead to blank screens.
+ */
+ Bool IsSecondaryRestored;
+ Bool RestorePrimary;
+
+ ScrnInfoPtr pSecondaryScrn;
+ ScrnInfoPtr pPrimaryScrn;
+} RADEONEntRec, *RADEONEntPtr;
+
+/* radeon_probe.c */
+extern const OptionInfoRec *RADEONAvailableOptions
+ FunctionPrototype((int, int));
+extern void RADEONIdentify
+ FunctionPrototype((int));
+extern Bool RADEONProbe
+ FunctionPrototype((DriverPtr, int));
+
+extern SymTabRec RADEONChipsets[];
+extern PciChipsets RADEONPciChipsets[];
+
+/* radeon_driver.c */
+extern void RADEONLoaderRefSymLists
+ FunctionPrototype((void));
+extern Bool RADEONPreInit
+ FunctionPrototype((ScrnInfoPtr, int));
+extern Bool RADEONScreenInit
+ FunctionPrototype((int, ScreenPtr, int, char **));
+extern Bool RADEONSwitchMode
+ FunctionPrototype((int, DisplayModePtr, int));
+extern void RADEONAdjustFrame
+ FunctionPrototype((int, int, int, int));
+extern Bool RADEONEnterVT
+ FunctionPrototype((int, int));
+extern void RADEONLeaveVT
+ FunctionPrototype((int, int));
+extern void RADEONFreeScreen
+ FunctionPrototype((int, int));
+extern int RADEONValidMode
+ FunctionPrototype((int, DisplayModePtr, Bool,
+ int));
+
+extern const OptionInfoRec RADEONOptions[];
+
+#endif /* _RADEON_PROBE_H_ */
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
new file mode 100644
index 0000000..a5c44f8
--- /dev/null
+++ b/src/radeon_reg.h
@@ -0,0 +1,1998 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.25.2.1 2003/03/07 12:13:59 alanh Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ * 1999.
+ *
+ * !!!! FIXME !!!!
+ * RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+/* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
+ * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
+ * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */
+
+#ifndef _RADEON_REG_H_
+#define _RADEON_REG_H_
+
+ /* Registers for 2D/Video/Overlay */
+#define RADEON_ADAPTER_ID 0x0f2c /* PCI */
+#define RADEON_AGP_BASE 0x0170
+#define RADEON_AGP_CNTL 0x0174
+# define RADEON_AGP_APER_SIZE_256MB (0x00 << 0)
+# define RADEON_AGP_APER_SIZE_128MB (0x20 << 0)
+# define RADEON_AGP_APER_SIZE_64MB (0x30 << 0)
+# define RADEON_AGP_APER_SIZE_32MB (0x38 << 0)
+# define RADEON_AGP_APER_SIZE_16MB (0x3c << 0)
+# define RADEON_AGP_APER_SIZE_8MB (0x3e << 0)
+# define RADEON_AGP_APER_SIZE_4MB (0x3f << 0)
+# define RADEON_AGP_APER_SIZE_MASK (0x3f << 0)
+#define RADEON_AGP_COMMAND 0x0f60 /* PCI */
+#define RADEON_AGP_PLL_CNTL 0x000b /* PLL */
+#define RADEON_AGP_STATUS 0x0f5c /* PCI */
+# define RADEON_AGP_1X_MODE 0x01
+# define RADEON_AGP_2X_MODE 0x02
+# define RADEON_AGP_4X_MODE 0x04
+# define RADEON_AGP_FW_MODE 0x10
+# define RADEON_AGP_MODE_MASK 0x17
+#define RADEON_ATTRDR 0x03c1 /* VGA */
+#define RADEON_ATTRDW 0x03c0 /* VGA */
+#define RADEON_ATTRX 0x03c0 /* VGA */
+#define RADEON_AUX_SC_CNTL 0x1660
+# define RADEON_AUX1_SC_EN (1 << 0)
+# define RADEON_AUX1_SC_MODE_OR (0 << 1)
+# define RADEON_AUX1_SC_MODE_NAND (1 << 1)
+# define RADEON_AUX2_SC_EN (1 << 2)
+# define RADEON_AUX2_SC_MODE_OR (0 << 3)
+# define RADEON_AUX2_SC_MODE_NAND (1 << 3)
+# define RADEON_AUX3_SC_EN (1 << 4)
+# define RADEON_AUX3_SC_MODE_OR (0 << 5)
+# define RADEON_AUX3_SC_MODE_NAND (1 << 5)
+#define RADEON_AUX1_SC_BOTTOM 0x1670
+#define RADEON_AUX1_SC_LEFT 0x1664
+#define RADEON_AUX1_SC_RIGHT 0x1668
+#define RADEON_AUX1_SC_TOP 0x166c
+#define RADEON_AUX2_SC_BOTTOM 0x1680
+#define RADEON_AUX2_SC_LEFT 0x1674
+#define RADEON_AUX2_SC_RIGHT 0x1678
+#define RADEON_AUX2_SC_TOP 0x167c
+#define RADEON_AUX3_SC_BOTTOM 0x1690
+#define RADEON_AUX3_SC_LEFT 0x1684
+#define RADEON_AUX3_SC_RIGHT 0x1688
+#define RADEON_AUX3_SC_TOP 0x168c
+#define RADEON_AUX_WINDOW_HORZ_CNTL 0x02d8
+#define RADEON_AUX_WINDOW_VERT_CNTL 0x02dc
+
+#define RADEON_BASE_CODE 0x0f0b
+#define RADEON_BIOS_0_SCRATCH 0x0010
+#define RADEON_BIOS_1_SCRATCH 0x0014
+#define RADEON_BIOS_2_SCRATCH 0x0018
+#define RADEON_BIOS_3_SCRATCH 0x001c
+#define RADEON_BIOS_4_SCRATCH 0x0020
+#define RADEON_BIOS_5_SCRATCH 0x0024
+#define RADEON_BIOS_6_SCRATCH 0x0028
+#define RADEON_BIOS_7_SCRATCH 0x002c
+#define RADEON_BIOS_ROM 0x0f30 /* PCI */
+#define RADEON_BIST 0x0f0f /* PCI */
+#define RADEON_BRUSH_DATA0 0x1480
+#define RADEON_BRUSH_DATA1 0x1484
+#define RADEON_BRUSH_DATA10 0x14a8
+#define RADEON_BRUSH_DATA11 0x14ac
+#define RADEON_BRUSH_DATA12 0x14b0
+#define RADEON_BRUSH_DATA13 0x14b4
+#define RADEON_BRUSH_DATA14 0x14b8
+#define RADEON_BRUSH_DATA15 0x14bc
+#define RADEON_BRUSH_DATA16 0x14c0
+#define RADEON_BRUSH_DATA17 0x14c4
+#define RADEON_BRUSH_DATA18 0x14c8
+#define RADEON_BRUSH_DATA19 0x14cc
+#define RADEON_BRUSH_DATA2 0x1488
+#define RADEON_BRUSH_DATA20 0x14d0
+#define RADEON_BRUSH_DATA21 0x14d4
+#define RADEON_BRUSH_DATA22 0x14d8
+#define RADEON_BRUSH_DATA23 0x14dc
+#define RADEON_BRUSH_DATA24 0x14e0
+#define RADEON_BRUSH_DATA25 0x14e4
+#define RADEON_BRUSH_DATA26 0x14e8
+#define RADEON_BRUSH_DATA27 0x14ec
+#define RADEON_BRUSH_DATA28 0x14f0
+#define RADEON_BRUSH_DATA29 0x14f4
+#define RADEON_BRUSH_DATA3 0x148c
+#define RADEON_BRUSH_DATA30 0x14f8
+#define RADEON_BRUSH_DATA31 0x14fc
+#define RADEON_BRUSH_DATA32 0x1500
+#define RADEON_BRUSH_DATA33 0x1504
+#define RADEON_BRUSH_DATA34 0x1508
+#define RADEON_BRUSH_DATA35 0x150c
+#define RADEON_BRUSH_DATA36 0x1510
+#define RADEON_BRUSH_DATA37 0x1514
+#define RADEON_BRUSH_DATA38 0x1518
+#define RADEON_BRUSH_DATA39 0x151c
+#define RADEON_BRUSH_DATA4 0x1490
+#define RADEON_BRUSH_DATA40 0x1520
+#define RADEON_BRUSH_DATA41 0x1524
+#define RADEON_BRUSH_DATA42 0x1528
+#define RADEON_BRUSH_DATA43 0x152c
+#define RADEON_BRUSH_DATA44 0x1530
+#define RADEON_BRUSH_DATA45 0x1534
+#define RADEON_BRUSH_DATA46 0x1538
+#define RADEON_BRUSH_DATA47 0x153c
+#define RADEON_BRUSH_DATA48 0x1540
+#define RADEON_BRUSH_DATA49 0x1544
+#define RADEON_BRUSH_DATA5 0x1494
+#define RADEON_BRUSH_DATA50 0x1548
+#define RADEON_BRUSH_DATA51 0x154c
+#define RADEON_BRUSH_DATA52 0x1550
+#define RADEON_BRUSH_DATA53 0x1554
+#define RADEON_BRUSH_DATA54 0x1558
+#define RADEON_BRUSH_DATA55 0x155c
+#define RADEON_BRUSH_DATA56 0x1560
+#define RADEON_BRUSH_DATA57 0x1564
+#define RADEON_BRUSH_DATA58 0x1568
+#define RADEON_BRUSH_DATA59 0x156c
+#define RADEON_BRUSH_DATA6 0x1498
+#define RADEON_BRUSH_DATA60 0x1570
+#define RADEON_BRUSH_DATA61 0x1574
+#define RADEON_BRUSH_DATA62 0x1578
+#define RADEON_BRUSH_DATA63 0x157c
+#define RADEON_BRUSH_DATA7 0x149c
+#define RADEON_BRUSH_DATA8 0x14a0
+#define RADEON_BRUSH_DATA9 0x14a4
+#define RADEON_BRUSH_SCALE 0x1470
+#define RADEON_BRUSH_Y_X 0x1474
+#define RADEON_BUS_CNTL 0x0030
+# define RADEON_BUS_MASTER_DIS (1 << 6)
+# define RADEON_BUS_RD_DISCARD_EN (1 << 24)
+# define RADEON_BUS_RD_ABORT_EN (1 << 25)
+# define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28)
+# define RADEON_BUS_WRT_BURST (1 << 29)
+# define RADEON_BUS_READ_BURST (1 << 30)
+#define RADEON_BUS_CNTL1 0x0034
+# define RADEON_BUS_WAIT_ON_LOCK_EN (1 << 4)
+
+#define RADEON_CACHE_CNTL 0x1724
+#define RADEON_CACHE_LINE 0x0f0c /* PCI */
+#define RADEON_CAP0_TRIG_CNTL 0x0950 /* ? */
+#define RADEON_CAP1_TRIG_CNTL 0x09c0 /* ? */
+#define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */
+#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */
+#define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */
+#define RADEON_CLOCK_CNTL_DATA 0x000c
+#define RADEON_CLOCK_CNTL_INDEX 0x0008
+# define RADEON_PLL_WR_EN (1 << 7)
+# define RADEON_PLL_DIV_SEL (3 << 8)
+# define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8)
+#define RADEON_CLR_CMP_CLR_3D 0x1a24
+#define RADEON_CLR_CMP_CLR_DST 0x15c8
+#define RADEON_CLR_CMP_CLR_SRC 0x15c4
+#define RADEON_CLR_CMP_CNTL 0x15c0
+# define RADEON_SRC_CMP_EQ_COLOR (4 << 0)
+# define RADEON_SRC_CMP_NEQ_COLOR (5 << 0)
+# define RADEON_CLR_CMP_SRC_SOURCE (1 << 24)
+#define RADEON_CLR_CMP_MASK 0x15cc
+# define RADEON_CLR_CMP_MSK 0xffffffff
+#define RADEON_CLR_CMP_MASK_3D 0x1A28
+#define RADEON_COMMAND 0x0f04 /* PCI */
+#define RADEON_COMPOSITE_SHADOW_ID 0x1a0c
+#define RADEON_CONFIG_APER_0_BASE 0x0100
+#define RADEON_CONFIG_APER_1_BASE 0x0104
+#define RADEON_CONFIG_APER_SIZE 0x0108
+#define RADEON_CONFIG_BONDS 0x00e8
+#define RADEON_CONFIG_CNTL 0x00e0
+# define RADEON_CFG_ATI_REV_A11 (0 << 16)
+# define RADEON_CFG_ATI_REV_A12 (1 << 16)
+# define RADEON_CFG_ATI_REV_A13 (2 << 16)
+# define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16)
+#define RADEON_CONFIG_MEMSIZE 0x00f8
+#define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114
+#define RADEON_CONFIG_REG_1_BASE 0x010c
+#define RADEON_CONFIG_REG_APER_SIZE 0x0110
+#define RADEON_CONFIG_XSTRAP 0x00e4
+#define RADEON_CONSTANT_COLOR_C 0x1d34
+# define RADEON_CONSTANT_COLOR_MASK 0x00ffffff
+# define RADEON_CONSTANT_COLOR_ONE 0x00ffffff
+# define RADEON_CONSTANT_COLOR_ZERO 0x00000000
+#define RADEON_CRC_CMDFIFO_ADDR 0x0740
+#define RADEON_CRC_CMDFIFO_DOUT 0x0744
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC_EXT_CNTL 0x0054
+# define RADEON_CRTC_VGA_XOVERSCAN (1 << 0)
+# define RADEON_VGA_ATI_LINEAR (1 << 3)
+# define RADEON_XCRT_CNT_EN (1 << 6)
+# define RADEON_CRTC_HSYNC_DIS (1 << 8)
+# define RADEON_CRTC_VSYNC_DIS (1 << 9)
+# define RADEON_CRTC_DISPLAY_DIS (1 << 10)
+# define RADEON_CRTC_SYNC_TRISTAT (1 << 11)
+# define RADEON_CRTC_CRT_ON (1 << 15)
+#define RADEON_CRTC_EXT_CNTL_DPMS_BYTE 0x0055
+# define RADEON_CRTC_HSYNC_DIS_BYTE (1 << 0)
+# define RADEON_CRTC_VSYNC_DIS_BYTE (1 << 1)
+# define RADEON_CRTC_DISPLAY_DIS_BYTE (1 << 2)
+#define RADEON_CRTC_GEN_CNTL 0x0050
+# define RADEON_CRTC_DBL_SCAN_EN (1 << 0)
+# define RADEON_CRTC_INTERLACE_EN (1 << 1)
+# define RADEON_CRTC_CSYNC_EN (1 << 4)
+# define RADEON_CRTC_CUR_EN (1 << 16)
+# define RADEON_CRTC_CUR_MODE_MASK (7 << 17)
+# define RADEON_CRTC_ICON_EN (1 << 20)
+# define RADEON_CRTC_EXT_DISP_EN (1 << 24)
+# define RADEON_CRTC_EN (1 << 25)
+# define RADEON_CRTC_DISP_REQ_EN_B (1 << 26)
+#define RADEON_CRTC2_GEN_CNTL 0x03f8
+# define RADEON_CRTC2_DBL_SCAN_EN (1 << 0)
+# define RADEON_CRTC2_INTERLACE_EN (1 << 1)
+# define RADEON_CRTC2_SYNC_TRISTAT (1 << 4)
+# define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5)
+# define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6)
+# define RADEON_CRTC2_CRT2_ON (1 << 7)
+# define RADEON_CRTC2_ICON_EN (1 << 15)
+# define RADEON_CRTC2_CUR_EN (1 << 16)
+# define RADEON_CRTC2_CUR_MODE_MASK (7 << 20)
+# define RADEON_CRTC2_DISP_DIS (1 << 23)
+# define RADEON_CRTC2_EN (1 << 25)
+# define RADEON_CRTC2_DISP_REQ_EN_B (1 << 26)
+# define RADEON_CRTC2_CSYNC_EN (1 << 27)
+# define RADEON_CRTC2_HSYNC_DIS (1 << 28)
+# define RADEON_CRTC2_VSYNC_DIS (1 << 29)
+#define RADEON_CRTC_GUI_TRIG_VLINE 0x0218
+#define RADEON_CRTC_H_SYNC_STRT_WID 0x0204
+# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0)
+# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3)
+# define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3
+# define RADEON_CRTC_H_SYNC_WID (0x3f << 16)
+# define RADEON_CRTC_H_SYNC_WID_SHIFT 16
+# define RADEON_CRTC_H_SYNC_POL (1 << 23)
+#define RADEON_CRTC2_H_SYNC_STRT_WID 0x0304
+# define RADEON_CRTC2_H_SYNC_STRT_PIX (0x07 << 0)
+# define RADEON_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3)
+# define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3
+# define RADEON_CRTC2_H_SYNC_WID (0x3f << 16)
+# define RADEON_CRTC2_H_SYNC_WID_SHIFT 16
+# define RADEON_CRTC2_H_SYNC_POL (1 << 23)
+#define RADEON_CRTC_H_TOTAL_DISP 0x0200
+# define RADEON_CRTC_H_TOTAL (0x03ff << 0)
+# define RADEON_CRTC_H_TOTAL_SHIFT 0
+# define RADEON_CRTC_H_DISP (0x01ff << 16)
+# define RADEON_CRTC_H_DISP_SHIFT 16
+#define RADEON_CRTC2_H_TOTAL_DISP 0x0300
+# define RADEON_CRTC2_H_TOTAL (0x03ff << 0)
+# define RADEON_CRTC2_H_TOTAL_SHIFT 0
+# define RADEON_CRTC2_H_DISP (0x01ff << 16)
+# define RADEON_CRTC2_H_DISP_SHIFT 16
+#define RADEON_CRTC_OFFSET 0x0224
+#define RADEON_CRTC2_OFFSET 0x0324
+#define RADEON_CRTC_OFFSET_CNTL 0x0228
+# define RADEON_CRTC_TILE_EN (1 << 15)
+#define RADEON_CRTC2_OFFSET_CNTL 0x0328
+# define RADEON_CRTC2_TILE_EN (1 << 15)
+#define RADEON_CRTC_PITCH 0x022c
+#define RADEON_CRTC2_PITCH 0x032c
+#define RADEON_CRTC_STATUS 0x005c
+# define RADEON_CRTC_VBLANK_SAVE (1 << 1)
+# define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1)
+#define RADEON_CRTC2_STATUS 0x03fc
+# define RADEON_CRTC2_VBLANK_SAVE (1 << 1)
+# define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1)
+#define RADEON_CRTC_V_SYNC_STRT_WID 0x020c
+# define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0)
+# define RADEON_CRTC_V_SYNC_STRT_SHIFT 0
+# define RADEON_CRTC_V_SYNC_WID (0x1f << 16)
+# define RADEON_CRTC_V_SYNC_WID_SHIFT 16
+# define RADEON_CRTC_V_SYNC_POL (1 << 23)
+#define RADEON_CRTC2_V_SYNC_STRT_WID 0x030c
+# define RADEON_CRTC2_V_SYNC_STRT (0x7ff << 0)
+# define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0
+# define RADEON_CRTC2_V_SYNC_WID (0x1f << 16)
+# define RADEON_CRTC2_V_SYNC_WID_SHIFT 16
+# define RADEON_CRTC2_V_SYNC_POL (1 << 23)
+#define RADEON_CRTC_V_TOTAL_DISP 0x0208
+# define RADEON_CRTC_V_TOTAL (0x07ff << 0)
+# define RADEON_CRTC_V_TOTAL_SHIFT 0
+# define RADEON_CRTC_V_DISP (0x07ff << 16)
+# define RADEON_CRTC_V_DISP_SHIFT 16
+#define RADEON_CRTC2_V_TOTAL_DISP 0x0308
+# define RADEON_CRTC2_V_TOTAL (0x07ff << 0)
+# define RADEON_CRTC2_V_TOTAL_SHIFT 0
+# define RADEON_CRTC2_V_DISP (0x07ff << 16)
+# define RADEON_CRTC2_V_DISP_SHIFT 16
+#define RADEON_CRTC_VLINE_CRNT_VLINE 0x0210
+# define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16)
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+#define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318
+#define RADEON_CRTC2_STATUS 0x03fc
+#define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310
+#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */
+#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */
+#define RADEON_CUR_CLR0 0x026c
+#define RADEON_CUR_CLR1 0x0270
+#define RADEON_CUR_HORZ_VERT_OFF 0x0268
+#define RADEON_CUR_HORZ_VERT_POSN 0x0264
+#define RADEON_CUR_OFFSET 0x0260
+# define RADEON_CUR_LOCK (1 << 31)
+#define RADEON_CUR2_CLR0 0x036c
+#define RADEON_CUR2_CLR1 0x0370
+#define RADEON_CUR2_HORZ_VERT_OFF 0x0368
+#define RADEON_CUR2_HORZ_VERT_POSN 0x0364
+#define RADEON_CUR2_OFFSET 0x0360
+# define RADEON_CUR2_LOCK (1 << 31)
+
+#define RADEON_DAC_CNTL 0x0058
+# define RADEON_DAC_RANGE_CNTL (3 << 0)
+# define RADEON_DAC_BLANKING (1 << 2)
+# define RADEON_DAC_8BIT_EN (1 << 8)
+# define RADEON_DAC_VGA_ADR_EN (1 << 13)
+# define RADEON_DAC_PDWN (1 << 15)
+# define RADEON_DAC_MASK_ALL (0xff << 24)
+#define RADEON_DAC_CNTL2 0x007c
+# define RADEON_DAC2_DAC_CLK_SEL (1 << 0)
+# define RADEON_DAC2_DAC2_CLK_SEL (1 << 1)
+# define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5)
+#define RADEON_TV_DAC_CNTL 0x088c
+# define RADEON_TV_DAC_STD_MASK 0x0300
+# define RADEON_TV_DAC_RDACPD (1 << 24)
+# define RADEON_TV_DAC_GDACPD (1 << 25)
+# define RADEON_TV_DAC_BDACPD (1 << 26)
+#define RADEON_DISP_HW_DEBUG 0x0d14
+# define RADEON_CRT2_DISP1_SEL (1 << 5)
+#define RADEON_DISP_OUTPUT_CNTL 0x0d64
+# define RADEON_DISP_DAC_SOURCE_MASK 0x03
+# define RADEON_DISP_DAC_SOURCE_CRTC2 0x01
+#define RADEON_DAC_CRC_SIG 0x02cc
+#define RADEON_DAC_DATA 0x03c9 /* VGA */
+#define RADEON_DAC_MASK 0x03c6 /* VGA */
+#define RADEON_DAC_R_INDEX 0x03c7 /* VGA */
+#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */
+#define RADEON_DDA_CONFIG 0x02e0
+#define RADEON_DDA_ON_OFF 0x02e4
+#define RADEON_DEFAULT_OFFSET 0x16e0
+#define RADEON_DEFAULT_PITCH 0x16e4
+#define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
+# define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0)
+# define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
+#define RADEON_DESTINATION_3D_CLR_CMP_VAL 0x1820
+#define RADEON_DESTINATION_3D_CLR_CMP_MSK 0x1824
+#define RADEON_DEVICE_ID 0x0f02 /* PCI */
+#define RADEON_DISP_MISC_CNTL 0x0d00
+# define RADEON_SOFT_RESET_GRPH_PP (1 << 0)
+#define RADEON_DP_BRUSH_BKGD_CLR 0x1478
+#define RADEON_DP_BRUSH_FRGD_CLR 0x147c
+#define RADEON_DP_CNTL 0x16c0
+# define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0)
+# define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1)
+#define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0
+# define RADEON_DST_Y_MAJOR (1 << 2)
+# define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
+# define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
+#define RADEON_DP_DATATYPE 0x16c4
+# define RADEON_HOST_BIG_ENDIAN_EN (1 << 29)
+#define RADEON_DP_GUI_MASTER_CNTL 0x146c
+# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define RADEON_GMC_SRC_CLIPPING (1 << 2)
+# define RADEON_GMC_DST_CLIPPING (1 << 3)
+# define RADEON_GMC_BRUSH_DATATYPE_MASK (0x0f << 4)
+# define RADEON_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4)
+# define RADEON_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4)
+# define RADEON_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4)
+# define RADEON_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4)
+# define RADEON_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4)
+# define RADEON_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4)
+# define RADEON_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4)
+# define RADEON_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4)
+# define RADEON_GMC_BRUSH_8x8_COLOR (10 << 4)
+# define RADEON_GMC_BRUSH_1X8_COLOR (12 << 4)
+# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define RADEON_GMC_BRUSH_NONE (15 << 4)
+# define RADEON_GMC_DST_8BPP_CI (2 << 8)
+# define RADEON_GMC_DST_15BPP (3 << 8)
+# define RADEON_GMC_DST_16BPP (4 << 8)
+# define RADEON_GMC_DST_24BPP (5 << 8)
+# define RADEON_GMC_DST_32BPP (6 << 8)
+# define RADEON_GMC_DST_8BPP_RGB (7 << 8)
+# define RADEON_GMC_DST_Y8 (8 << 8)
+# define RADEON_GMC_DST_RGB8 (9 << 8)
+# define RADEON_GMC_DST_VYUY (11 << 8)
+# define RADEON_GMC_DST_YVYU (12 << 8)
+# define RADEON_GMC_DST_AYUV444 (14 << 8)
+# define RADEON_GMC_DST_ARGB4444 (15 << 8)
+# define RADEON_GMC_DST_DATATYPE_MASK (0x0f << 8)
+# define RADEON_GMC_DST_DATATYPE_SHIFT 8
+# define RADEON_GMC_SRC_DATATYPE_MASK (3 << 12)
+# define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12)
+# define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12)
+# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define RADEON_GMC_BYTE_PIX_ORDER (1 << 14)
+# define RADEON_GMC_BYTE_MSB_TO_LSB (0 << 14)
+# define RADEON_GMC_BYTE_LSB_TO_MSB (1 << 14)
+# define RADEON_GMC_CONVERSION_TEMP (1 << 15)
+# define RADEON_GMC_CONVERSION_TEMP_6500 (0 << 15)
+# define RADEON_GMC_CONVERSION_TEMP_9300 (1 << 15)
+# define RADEON_GMC_ROP3_MASK (0xff << 16)
+# define RADEON_DP_SRC_SOURCE_MASK (7 << 24)
+# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24)
+# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24)
+# define RADEON_GMC_3D_FCN_EN (1 << 27)
+# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define RADEON_GMC_AUX_CLIP_DIS (1 << 29)
+# define RADEON_GMC_WR_MSK_DIS (1 << 30)
+# define RADEON_GMC_LD_BRUSH_Y_X (1 << 31)
+# define RADEON_ROP3_ZERO 0x00000000
+# define RADEON_ROP3_DSa 0x00880000
+# define RADEON_ROP3_SDna 0x00440000
+# define RADEON_ROP3_S 0x00cc0000
+# define RADEON_ROP3_DSna 0x00220000
+# define RADEON_ROP3_D 0x00aa0000
+# define RADEON_ROP3_DSx 0x00660000
+# define RADEON_ROP3_DSo 0x00ee0000
+# define RADEON_ROP3_DSon 0x00110000
+# define RADEON_ROP3_DSxn 0x00990000
+# define RADEON_ROP3_Dn 0x00550000
+# define RADEON_ROP3_SDno 0x00dd0000
+# define RADEON_ROP3_Sn 0x00330000
+# define RADEON_ROP3_DSno 0x00bb0000
+# define RADEON_ROP3_DSan 0x00770000
+# define RADEON_ROP3_ONE 0x00ff0000
+# define RADEON_ROP3_DPa 0x00a00000
+# define RADEON_ROP3_PDna 0x00500000
+# define RADEON_ROP3_P 0x00f00000
+# define RADEON_ROP3_DPna 0x000a0000
+# define RADEON_ROP3_D 0x00aa0000
+# define RADEON_ROP3_DPx 0x005a0000
+# define RADEON_ROP3_DPo 0x00fa0000
+# define RADEON_ROP3_DPon 0x00050000
+# define RADEON_ROP3_PDxn 0x00a50000
+# define RADEON_ROP3_PDno 0x00f50000
+# define RADEON_ROP3_Pn 0x000f0000
+# define RADEON_ROP3_DPno 0x00af0000
+# define RADEON_ROP3_DPan 0x005f0000
+#define RADEON_DP_GUI_MASTER_CNTL_C 0x1c84
+#define RADEON_DP_MIX 0x16c8
+#define RADEON_DP_SRC_BKGD_CLR 0x15dc
+#define RADEON_DP_SRC_FRGD_CLR 0x15d8
+#define RADEON_DP_WRITE_MASK 0x16cc
+#define RADEON_DST_BRES_DEC 0x1630
+#define RADEON_DST_BRES_ERR 0x1628
+#define RADEON_DST_BRES_INC 0x162c
+#define RADEON_DST_BRES_LNTH 0x1634
+#define RADEON_DST_BRES_LNTH_SUB 0x1638
+#define RADEON_DST_HEIGHT 0x1410
+#define RADEON_DST_HEIGHT_WIDTH 0x143c
+#define RADEON_DST_HEIGHT_WIDTH_8 0x158c
+#define RADEON_DST_HEIGHT_WIDTH_BW 0x15b4
+#define RADEON_DST_HEIGHT_Y 0x15a0
+#define RADEON_DST_LINE_START 0x1600
+#define RADEON_DST_LINE_END 0x1604
+#define RADEON_DST_LINE_PATCOUNT 0x1608
+# define RADEON_BRES_CNTL_SHIFT 8
+#define RADEON_DST_OFFSET 0x1404
+#define RADEON_DST_PITCH 0x1408
+#define RADEON_DST_PITCH_OFFSET 0x142c
+#define RADEON_DST_PITCH_OFFSET_C 0x1c80
+# define RADEON_PITCH_SHIFT 21
+# define RADEON_DST_TILE_LINEAR (0 << 30)
+# define RADEON_DST_TILE_MACRO (1 << 30)
+# define RADEON_DST_TILE_MICRO (2 << 30)
+# define RADEON_DST_TILE_BOTH (3 << 30)
+#define RADEON_DST_WIDTH 0x140c
+#define RADEON_DST_WIDTH_HEIGHT 0x1598
+#define RADEON_DST_WIDTH_X 0x1588
+#define RADEON_DST_WIDTH_X_INCY 0x159c
+#define RADEON_DST_X 0x141c
+#define RADEON_DST_X_SUB 0x15a4
+#define RADEON_DST_X_Y 0x1594
+#define RADEON_DST_Y 0x1420
+#define RADEON_DST_Y_SUB 0x15a8
+#define RADEON_DST_Y_X 0x1438
+
+#define RADEON_FCP_CNTL 0x0910
+# define RADEON_FCP0_SRC_PCICLK 0
+# define RADEON_FCP0_SRC_PCLK 1
+# define RADEON_FCP0_SRC_PCLKb 2
+# define RADEON_FCP0_SRC_HREF 3
+# define RADEON_FCP0_SRC_GND 4
+# define RADEON_FCP0_SRC_HREFb 5
+#define RADEON_FLUSH_1 0x1704
+#define RADEON_FLUSH_2 0x1708
+#define RADEON_FLUSH_3 0x170c
+#define RADEON_FLUSH_4 0x1710
+#define RADEON_FLUSH_5 0x1714
+#define RADEON_FLUSH_6 0x1718
+#define RADEON_FLUSH_7 0x171c
+#define RADEON_FOG_3D_TABLE_START 0x1810
+#define RADEON_FOG_3D_TABLE_END 0x1814
+#define RADEON_FOG_3D_TABLE_DENSITY 0x181c
+#define RADEON_FOG_TABLE_INDEX 0x1a14
+#define RADEON_FOG_TABLE_DATA 0x1a18
+#define RADEON_FP_CRTC_H_TOTAL_DISP 0x0250
+#define RADEON_FP_CRTC_V_TOTAL_DISP 0x0254
+#define RADEON_FP_CRTC2_H_TOTAL_DISP 0x0350
+#define RADEON_FP_CRTC2_V_TOTAL_DISP 0x0354
+# define RADEON_FP_CRTC_H_TOTAL_MASK 0x000003ff
+# define RADEON_FP_CRTC_H_DISP_MASK 0x01ff0000
+# define RADEON_FP_CRTC_V_TOTAL_MASK 0x00000fff
+# define RADEON_FP_CRTC_V_DISP_MASK 0x0fff0000
+# define RADEON_FP_H_SYNC_STRT_CHAR_MASK 0x00001ff8
+# define RADEON_FP_H_SYNC_WID_MASK 0x003f0000
+# define RADEON_FP_V_SYNC_STRT_MASK 0x00000fff
+# define RADEON_FP_V_SYNC_WID_MASK 0x001f0000
+# define RADEON_FP_CRTC_H_TOTAL_SHIFT 0x00000000
+# define RADEON_FP_CRTC_H_DISP_SHIFT 0x00000010
+# define RADEON_FP_CRTC_V_TOTAL_SHIFT 0x00000000
+# define RADEON_FP_CRTC_V_DISP_SHIFT 0x00000010
+# define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003
+# define RADEON_FP_H_SYNC_WID_SHIFT 0x00000010
+# define RADEON_FP_V_SYNC_STRT_SHIFT 0x00000000
+# define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010
+#define RADEON_FP_GEN_CNTL 0x0284
+# define RADEON_FP_FPON (1 << 0)
+# define RADEON_FP_TMDS_EN (1 << 2)
+# define RADEON_FP_PANEL_FORMAT (1 << 3)
+# define RADEON_FP_EN_TMDS (1 << 7)
+# define RADEON_FP_DETECT_SENSE (1 << 8)
+# define RADEON_FP_SEL_CRTC2 (1 << 13)
+# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15)
+# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
+# define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
+# define RADEON_FP_CRTC_USE_SHADOW_VEND (1 << 18)
+# define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20)
+# define RADEON_FP_DFP_SYNC_SEL (1 << 21)
+# define RADEON_FP_CRTC_LOCK_8DOT (1 << 22)
+# define RADEON_FP_CRT_SYNC_SEL (1 << 23)
+# define RADEON_FP_USE_SHADOW_EN (1 << 24)
+# define RADEON_FP_CRT_SYNC_ALT (1 << 26)
+#define RADEON_FP2_GEN_CNTL 0x0288
+# define RADEON_FP2_BLANK_EN (1 << 1)
+# define RADEON_FP2_ON (1 << 2)
+# define RADEON_FP2_PANEL_FORMAT (1 << 3)
+# define RADEON_FP2_SEL_CRTC2 (1 << 13)
+# define RADEON_FP2_FP_POL (1 << 16)
+# define RADEON_FP2_LP_POL (1 << 17)
+# define RADEON_FP2_SCK_POL (1 << 18)
+# define RADEON_FP2_LCD_CNTL_MASK (7 << 19)
+# define RADEON_FP2_PAD_FLOP_EN (1 << 22)
+# define RADEON_FP2_CRC_EN (1 << 23)
+# define RADEON_FP2_CRC_READ_EN (1 << 24)
+#define RADEON_FP_H_SYNC_STRT_WID 0x02c4
+#define RADEON_FP_H2_SYNC_STRT_WID 0x03c4
+#define RADEON_FP_HORZ_STRETCH 0x028c
+#define RADEON_FP_HORZ2_STRETCH 0x038c
+# define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff
+# define RADEON_HORZ_STRETCH_RATIO_MAX 4096
+# define RADEON_HORZ_PANEL_SIZE (0x1ff << 16)
+# define RADEON_HORZ_PANEL_SHIFT 16
+# define RADEON_HORZ_STRETCH_PIXREP (0 << 25)
+# define RADEON_HORZ_STRETCH_BLEND (1 << 26)
+# define RADEON_HORZ_STRETCH_ENABLE (1 << 25)
+# define RADEON_HORZ_AUTO_RATIO (1 << 27)
+# define RADEON_HORZ_FP_LOOP_STRETCH (0x7 << 28)
+# define RADEON_HORZ_AUTO_RATIO_INC (1 << 31)
+#define RADEON_FP_V_SYNC_STRT_WID 0x02c8
+#define RADEON_FP_VERT_STRETCH 0x0290
+#define RADEON_FP_V2_SYNC_STRT_WID 0x03c8
+#define RADEON_FP_VERT2_STRETCH 0x0390
+# define RADEON_VERT_PANEL_SIZE (0xfff << 12)
+# define RADEON_VERT_PANEL_SHIFT 12
+# define RADEON_VERT_STRETCH_RATIO_MASK 0xfff
+# define RADEON_VERT_STRETCH_RATIO_SHIFT 0
+# define RADEON_VERT_STRETCH_RATIO_MAX 4096
+# define RADEON_VERT_STRETCH_ENABLE (1 << 25)
+# define RADEON_VERT_STRETCH_LINEREP (0 << 26)
+# define RADEON_VERT_STRETCH_BLEND (1 << 26)
+# define RADEON_VERT_AUTO_RATIO_EN (1 << 27)
+# define RADEON_VERT_STRETCH_RESERVED 0xf1000000
+
+#define RADEON_GEN_INT_CNTL 0x0040
+#define RADEON_GEN_INT_STATUS 0x0044
+# define RADEON_VSYNC_INT_AK (1 << 2)
+# define RADEON_VSYNC_INT (1 << 2)
+# define RADEON_VSYNC2_INT_AK (1 << 6)
+# define RADEON_VSYNC2_INT (1 << 6)
+#define RADEON_GENENB 0x03c3 /* VGA */
+#define RADEON_GENFC_RD 0x03ca /* VGA */
+#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */
+#define RADEON_GENMO_RD 0x03cc /* VGA */
+#define RADEON_GENMO_WT 0x03c2 /* VGA */
+#define RADEON_GENS0 0x03c2 /* VGA */
+#define RADEON_GENS1 0x03da /* VGA, 0x03ba */
+#define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */
+#define RADEON_GPIO_MONIDB 0x006c
+#define RADEON_GPIO_CRT2_DDC 0x006c
+#define RADEON_GPIO_DVI_DDC 0x0064
+#define RADEON_GPIO_VGA_DDC 0x0060
+# define RADEON_GPIO_A_0 (1 << 0)
+# define RADEON_GPIO_A_1 (1 << 1)
+# define RADEON_GPIO_Y_0 (1 << 8)
+# define RADEON_GPIO_Y_1 (1 << 9)
+# define RADEON_GPIO_Y_SHIFT_0 8
+# define RADEON_GPIO_Y_SHIFT_1 9
+# define RADEON_GPIO_EN_0 (1 << 16)
+# define RADEON_GPIO_EN_1 (1 << 17)
+# define RADEON_GPIO_MASK_0 (1 << 24) /*??*/
+# define RADEON_GPIO_MASK_1 (1 << 25) /*??*/
+#define RADEON_GRPH8_DATA 0x03cf /* VGA */
+#define RADEON_GRPH8_IDX 0x03ce /* VGA */
+#define RADEON_GUI_SCRATCH_REG0 0x15e0
+#define RADEON_GUI_SCRATCH_REG1 0x15e4
+#define RADEON_GUI_SCRATCH_REG2 0x15e8
+#define RADEON_GUI_SCRATCH_REG3 0x15ec
+#define RADEON_GUI_SCRATCH_REG4 0x15f0
+#define RADEON_GUI_SCRATCH_REG5 0x15f4
+
+#define RADEON_HEADER 0x0f0e /* PCI */
+#define RADEON_HOST_DATA0 0x17c0
+#define RADEON_HOST_DATA1 0x17c4
+#define RADEON_HOST_DATA2 0x17c8
+#define RADEON_HOST_DATA3 0x17cc
+#define RADEON_HOST_DATA4 0x17d0
+#define RADEON_HOST_DATA5 0x17d4
+#define RADEON_HOST_DATA6 0x17d8
+#define RADEON_HOST_DATA7 0x17dc
+#define RADEON_HOST_DATA_LAST 0x17e0
+#define RADEON_HOST_PATH_CNTL 0x0130
+# define RADEON_HDP_SOFT_RESET (1 << 26)
+#define RADEON_HTOTAL_CNTL 0x0009 /* PLL */
+#define RADEON_HTOTAL2_CNTL 0x002e /* PLL */
+
+#define RADEON_I2C_CNTL_1 0x0094 /* ? */
+#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */
+#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */
+#define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */
+#define RADEON_IO_BASE 0x0f14 /* PCI */
+
+#define RADEON_LATENCY 0x0f0d /* PCI */
+#define RADEON_LEAD_BRES_DEC 0x1608
+#define RADEON_LEAD_BRES_LNTH 0x161c
+#define RADEON_LEAD_BRES_LNTH_SUB 0x1624
+#define RADEON_LVDS_GEN_CNTL 0x02d0
+# define RADEON_LVDS_ON (1 << 0)
+# define RADEON_LVDS_DISPLAY_DIS (1 << 1)
+# define RADEON_LVDS_PANEL_TYPE (1 << 2)
+# define RADEON_LVDS_PANEL_FORMAT (1 << 3)
+# define RADEON_LVDS_EN (1 << 7)
+# define RADEON_LVDS_DIGON (1 << 18)
+# define RADEON_LVDS_BLON (1 << 19)
+# define RADEON_LVDS_SEL_CRTC2 (1 << 23)
+#define RADEON_LVDS_PLL_CNTL 0x02d4
+# define RADEON_HSYNC_DELAY_SHIFT 28
+# define RADEON_HSYNC_DELAY_MASK (0xf << 28)
+
+#define RADEON_MAX_LATENCY 0x0f3f /* PCI */
+#define RADEON_MC_AGP_LOCATION 0x014c
+#define RADEON_MC_FB_LOCATION 0x0148
+#define RADEON_MCLK_CNTL 0x0012 /* PLL */
+# define RADEON_FORCEON_MCLKA (1 << 16)
+# define RADEON_FORCEON_MCLKB (1 << 17)
+# define RADEON_FORCEON_YCLKA (1 << 18)
+# define RADEON_FORCEON_YCLKB (1 << 19)
+# define RADEON_FORCEON_MC (1 << 20)
+# define RADEON_FORCEON_AIC (1 << 21)
+#define RADEON_MDGPIO_A_REG 0x01ac
+#define RADEON_MDGPIO_EN_REG 0x01b0
+#define RADEON_MDGPIO_MASK 0x0198
+#define RADEON_MDGPIO_Y_REG 0x01b4
+#define RADEON_MEM_ADDR_CONFIG 0x0148
+#define RADEON_MEM_BASE 0x0f10 /* PCI */
+#define RADEON_MEM_CNTL 0x0140
+#define RADEON_MEM_INIT_LAT_TIMER 0x0154
+#define RADEON_MEM_INTF_CNTL 0x014c
+#define RADEON_MEM_SDRAM_MODE_REG 0x0158
+#define RADEON_MEM_STR_CNTL 0x0150
+#define RADEON_MEM_VGA_RP_SEL 0x003c
+#define RADEON_MEM_VGA_WP_SEL 0x0038
+#define RADEON_MIN_GRANT 0x0f3e /* PCI */
+#define RADEON_MM_DATA 0x0004
+#define RADEON_MM_INDEX 0x0000
+#define RADEON_MPLL_CNTL 0x000e /* PLL */
+#define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */
+#define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */
+
+
+#define RADEON_N_VIF_COUNT 0x0248
+
+#define RADEON_OV0_AUTO_FLIP_CNTL 0x0470
+#define RADEON_OV0_COLOUR_CNTL 0x04E0
+#define RADEON_OV0_DEINTERLACE_PATTERN 0x0474
+#define RADEON_OV0_EXCLUSIVE_HORZ 0x0408
+# define RADEON_EXCL_HORZ_START_MASK 0x000000ff
+# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00
+# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000
+# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000
+#define RADEON_OV0_EXCLUSIVE_VERT 0x040C
+# define RADEON_EXCL_VERT_START_MASK 0x000003ff
+# define RADEON_EXCL_VERT_END_MASK 0x03ff0000
+#define RADEON_OV0_FILTER_CNTL 0x04A0
+#define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0
+#define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4
+#define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8
+#define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC
+#define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0
+#define RADEON_OV0_GAMMA_000_00F 0x0d40
+#define RADEON_OV0_GAMMA_010_01F 0x0d44
+#define RADEON_OV0_GAMMA_020_03F 0x0d48
+#define RADEON_OV0_GAMMA_040_07F 0x0d4c
+#define RADEON_OV0_GAMMA_080_0BF 0x0e00
+#define RADEON_OV0_GAMMA_0C0_0FF 0x0e04
+#define RADEON_OV0_GAMMA_100_13F 0x0e08
+#define RADEON_OV0_GAMMA_140_17F 0x0e0c
+#define RADEON_OV0_GAMMA_180_1BF 0x0e10
+#define RADEON_OV0_GAMMA_1C0_1FF 0x0e14
+#define RADEON_OV0_GAMMA_200_23F 0x0e18
+#define RADEON_OV0_GAMMA_240_27F 0x0e1c
+#define RADEON_OV0_GAMMA_280_2BF 0x0e20
+#define RADEON_OV0_GAMMA_2C0_2FF 0x0e24
+#define RADEON_OV0_GAMMA_300_33F 0x0e28
+#define RADEON_OV0_GAMMA_340_37F 0x0e2c
+#define RADEON_OV0_GAMMA_380_3BF 0x0d50
+#define RADEON_OV0_GAMMA_3C0_3FF 0x0d54
+#define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC
+#define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0
+#define RADEON_OV0_H_INC 0x0480
+#define RADEON_OV0_KEY_CNTL 0x04F4
+# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L
+# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L
+# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L
+# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L
+# define RADEON_VIDEO_KEY_FN_NE 0x00000003L
+# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L
+# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L
+# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L
+# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L
+# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L
+# define RADEON_CMP_MIX_MASK 0x00000100L
+# define RADEON_CMP_MIX_OR 0x00000000L
+# define RADEON_CMP_MIX_AND 0x00000100L
+#define RADEON_OV0_LIN_TRANS_A 0x0d20
+#define RADEON_OV0_LIN_TRANS_B 0x0d24
+#define RADEON_OV0_LIN_TRANS_C 0x0d28
+#define RADEON_OV0_LIN_TRANS_D 0x0d2c
+#define RADEON_OV0_LIN_TRANS_E 0x0d30
+#define RADEON_OV0_LIN_TRANS_F 0x0d34
+#define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430
+# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL
+# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L
+#define RADEON_OV0_P1_H_ACCUM_INIT 0x0488
+#define RADEON_OV0_P1_V_ACCUM_INIT 0x0428
+# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L
+# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L
+#define RADEON_OV0_P1_X_START_END 0x0494
+#define RADEON_OV0_P2_X_START_END 0x0498
+#define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434
+# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL
+# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L
+#define RADEON_OV0_P23_H_ACCUM_INIT 0x048C
+#define RADEON_OV0_P23_V_ACCUM_INIT 0x042C
+#define RADEON_OV0_P3_X_START_END 0x049C
+#define RADEON_OV0_REG_LOAD_CNTL 0x0410
+# define RADEON_REG_LD_CTL_LOCK 0x00000001L
+# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L
+# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L
+# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L
+#define RADEON_OV0_SCALE_CNTL 0x0420
+# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L
+# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L
+# define RADEON_SCALER_SIGNED_UV 0x00000010L
+# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L
+# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L
+# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L
+# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L
+# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L
+# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L
+# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L
+# define RADEON_SCALER_SOURCE_15BPP 0x00000300L
+# define RADEON_SCALER_SOURCE_16BPP 0x00000400L
+# define RADEON_SCALER_SOURCE_32BPP 0x00000600L
+# define RADEON_SCALER_SOURCE_YUV9 0x00000900L
+# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L
+# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L
+# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L
+# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L
+# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L
+# define RADEON_SCALER_SMART_SWITCH 0x00008000L
+# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L
+# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L
+# define RADEON_SCALER_DIS_LIMIT 0x08000000L
+# define RADEON_SCALER_INT_EMU 0x20000000L
+# define RADEON_SCALER_ENABLE 0x40000000L
+# define RADEON_SCALER_SOFT_RESET 0x80000000L
+# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L
+#define RADEON_OV0_STEP_BY 0x0484
+#define RADEON_OV0_TEST 0x04F8
+#define RADEON_OV0_V_INC 0x0424
+#define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460
+#define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464
+#define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440
+# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L
+# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L
+# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L
+# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444
+# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L
+# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L
+# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L
+# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448
+# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L
+# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L
+# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L
+# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C
+#define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450
+#define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454
+#define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8
+#define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4
+#define RADEON_OV0_Y_X_START 0x0400
+#define RADEON_OV0_Y_X_END 0x0404
+#define RADEON_OV1_Y_X_START 0x0600
+#define RADEON_OV1_Y_X_END 0x0604
+#define RADEON_OVR_CLR 0x0230
+#define RADEON_OVR_WID_LEFT_RIGHT 0x0234
+#define RADEON_OVR_WID_TOP_BOTTOM 0x0238
+
+#define RADEON_P2PLL_CNTL 0x002a /* P2PLL */
+# define RADEON_P2PLL_RESET (1 << 0)
+# define RADEON_P2PLL_SLEEP (1 << 1)
+# define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16)
+# define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+# define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18)
+#define RADEON_P2PLL_DIV_0 0x002c
+# define RADEON_P2PLL_FB0_DIV_MASK 0x07ff
+# define RADEON_P2PLL_POST0_DIV_MASK 0x00070000
+#define RADEON_P2PLL_REF_DIV 0x002B /* PLL */
+# define RADEON_P2PLL_REF_DIV_MASK 0x03ff
+# define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
+# define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+# define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18)
+# define R300_PPLL_REF_DIV_ACC_SHIFT 18
+#define RADEON_PALETTE_DATA 0x00b4
+#define RADEON_PALETTE_30_DATA 0x00b8
+#define RADEON_PALETTE_INDEX 0x00b0
+#define RADEON_PCI_GART_PAGE 0x017c
+#define RADEON_PIXCLKS_CNTL 0x002d
+# define RADEON_PIX2CLK_SRC_SEL_MASK 0x03
+# define RADEON_PIX2CLK_SRC_SEL_CPUCLK 0x00
+# define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01
+# define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02
+# define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03
+#define RADEON_PLANE_3D_MASK_C 0x1d44
+#define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */
+#define RADEON_PMI_CAP_ID 0x0f5c /* PCI */
+#define RADEON_PMI_DATA 0x0f63 /* PCI */
+#define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */
+#define RADEON_PMI_PMC_REG 0x0f5e /* PCI */
+#define RADEON_PMI_PMCSR_REG 0x0f60 /* PCI */
+#define RADEON_PMI_REGISTER 0x0f5c /* PCI */
+#define RADEON_PPLL_CNTL 0x0002 /* PLL */
+# define RADEON_PPLL_RESET (1 << 0)
+# define RADEON_PPLL_SLEEP (1 << 1)
+# define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16)
+# define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+# define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18)
+#define RADEON_PPLL_DIV_0 0x0004 /* PLL */
+#define RADEON_PPLL_DIV_1 0x0005 /* PLL */
+#define RADEON_PPLL_DIV_2 0x0006 /* PLL */
+#define RADEON_PPLL_DIV_3 0x0007 /* PLL */
+# define RADEON_PPLL_FB3_DIV_MASK 0x07ff
+# define RADEON_PPLL_POST3_DIV_MASK 0x00070000
+#define RADEON_PPLL_REF_DIV 0x0003 /* PLL */
+# define RADEON_PPLL_REF_DIV_MASK 0x03ff
+# define RADEON_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
+# define RADEON_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+#define RADEON_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */
+
+#define RADEON_RBBM_GUICNTL 0x172c
+# define RADEON_HOST_DATA_SWAP_NONE (0 << 0)
+# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0)
+# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0)
+# define RADEON_HOST_DATA_SWAP_HDW (3 << 0)
+#define RADEON_RBBM_SOFT_RESET 0x00f0
+# define RADEON_SOFT_RESET_CP (1 << 0)
+# define RADEON_SOFT_RESET_HI (1 << 1)
+# define RADEON_SOFT_RESET_SE (1 << 2)
+# define RADEON_SOFT_RESET_RE (1 << 3)
+# define RADEON_SOFT_RESET_PP (1 << 4)
+# define RADEON_SOFT_RESET_E2 (1 << 5)
+# define RADEON_SOFT_RESET_RB (1 << 6)
+# define RADEON_SOFT_RESET_HDP (1 << 7)
+#define RADEON_RBBM_STATUS 0x0e40
+# define RADEON_RBBM_FIFOCNT_MASK 0x007f
+# define RADEON_RBBM_ACTIVE (1 << 31)
+#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c
+# define RADEON_RB2D_DC_FLUSH (3 << 0)
+# define RADEON_RB2D_DC_FREE (3 << 2)
+# define RADEON_RB2D_DC_FLUSH_ALL 0xf
+# define RADEON_RB2D_DC_BUSY (1 << 31)
+#define RADEON_RB2D_DSTCACHE_MODE 0x3428
+#define RADEON_REG_BASE 0x0f18 /* PCI */
+#define RADEON_REGPROG_INF 0x0f09 /* PCI */
+#define RADEON_REVISION_ID 0x0f08 /* PCI */
+
+#define RADEON_SC_BOTTOM 0x164c
+#define RADEON_SC_BOTTOM_RIGHT 0x16f0
+#define RADEON_SC_BOTTOM_RIGHT_C 0x1c8c
+#define RADEON_SC_LEFT 0x1640
+#define RADEON_SC_RIGHT 0x1644
+#define RADEON_SC_TOP 0x1648
+#define RADEON_SC_TOP_LEFT 0x16ec
+#define RADEON_SC_TOP_LEFT_C 0x1c88
+# define RADEON_SC_SIGN_MASK_LO 0x8000
+# define RADEON_SC_SIGN_MASK_HI 0x80000000
+#define RADEON_SCLK_CNTL 0x000d /* PLL */
+# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8
+# define RADEON_CP_MAX_DYN_STOP_LAT 0x0008
+# define RADEON_SCLK_FORCEON_MASK 0xffff8000
+#define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */
+# define RADEON_SCLK_MORE_FORCEON 0x0700
+#define RADEON_SDRAM_MODE_REG 0x0158
+#define RADEON_SEQ8_DATA 0x03c5 /* VGA */
+#define RADEON_SEQ8_IDX 0x03c4 /* VGA */
+#define RADEON_SNAPSHOT_F_COUNT 0x0244
+#define RADEON_SNAPSHOT_VH_COUNTS 0x0240
+#define RADEON_SNAPSHOT_VIF_COUNT 0x024c
+#define RADEON_SRC_OFFSET 0x15ac
+#define RADEON_SRC_PITCH 0x15b0
+#define RADEON_SRC_PITCH_OFFSET 0x1428
+#define RADEON_SRC_SC_BOTTOM 0x165c
+#define RADEON_SRC_SC_BOTTOM_RIGHT 0x16f4
+#define RADEON_SRC_SC_RIGHT 0x1654
+#define RADEON_SRC_X 0x1414
+#define RADEON_SRC_X_Y 0x1590
+#define RADEON_SRC_Y 0x1418
+#define RADEON_SRC_Y_X 0x1434
+#define RADEON_STATUS 0x0f06 /* PCI */
+#define RADEON_SUBPIC_CNTL 0x0540 /* ? */
+#define RADEON_SUB_CLASS 0x0f0a /* PCI */
+#define RADEON_SURFACE_CNTL 0x0b00
+# define RADEON_SURF_TRANSLATION_DIS (1 << 8)
+# define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20)
+# define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21)
+#define RADEON_SURFACE0_INFO 0x0b0c
+#define RADEON_SURFACE0_LOWER_BOUND 0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND 0x0b08
+#define RADEON_SURFACE1_INFO 0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND 0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND 0x0b18
+#define RADEON_SURFACE2_INFO 0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND 0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND 0x0b28
+#define RADEON_SURFACE3_INFO 0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND 0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND 0x0b38
+#define RADEON_SURFACE4_INFO 0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND 0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND 0x0b48
+#define RADEON_SURFACE5_INFO 0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND 0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND 0x0b58
+#define RADEON_SURFACE6_INFO 0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND 0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND 0x0b68
+#define RADEON_SURFACE7_INFO 0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND 0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND 0x0b78
+#define RADEON_SW_SEMAPHORE 0x013c
+
+#define RADEON_TEST_DEBUG_CNTL 0x0120
+#define RADEON_TEST_DEBUG_MUX 0x0124
+#define RADEON_TEST_DEBUG_OUT 0x012c
+#define RADEON_TMDS_PLL_CNTL 0x02a8
+#define RADEON_TRAIL_BRES_DEC 0x1614
+#define RADEON_TRAIL_BRES_ERR 0x160c
+#define RADEON_TRAIL_BRES_INC 0x1610
+#define RADEON_TRAIL_X 0x1618
+#define RADEON_TRAIL_X_SUB 0x1620
+
+#define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */
+# define RADEON_VCLK_SRC_SEL_MASK 0x03
+# define RADEON_VCLK_SRC_SEL_CPUCLK 0x00
+# define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01
+# define RADEON_VCLK_SRC_SEL_BYTECLK 0x02
+# define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03
+#define RADEON_VENDOR_ID 0x0f00 /* PCI */
+#define RADEON_VGA_DDA_CONFIG 0x02e8
+#define RADEON_VGA_DDA_ON_OFF 0x02ec
+#define RADEON_VID_BUFFER_CONTROL 0x0900
+#define RADEON_VIDEOMUX_CNTL 0x0190
+#define RADEON_VIPH_CONTROL 0x0c40 /* ? */
+
+#define RADEON_WAIT_UNTIL 0x1720
+# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
+# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
+# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
+
+#define RADEON_X_MPLL_REF_FB_DIV 0x000a /* PLL */
+#define RADEON_XCLK_CNTL 0x000d /* PLL */
+#define RADEON_XDLL_CNTL 0x000c /* PLL */
+#define RADEON_XPLL_CNTL 0x000b /* PLL */
+
+
+
+ /* Registers for 3D/TCL */
+#define RADEON_PP_BORDER_COLOR_0 0x1d40
+#define RADEON_PP_BORDER_COLOR_1 0x1d44
+#define RADEON_PP_BORDER_COLOR_2 0x1d48
+#define RADEON_PP_CNTL 0x1c38
+# define RADEON_STIPPLE_ENABLE (1 << 0)
+# define RADEON_SCISSOR_ENABLE (1 << 1)
+# define RADEON_PATTERN_ENABLE (1 << 2)
+# define RADEON_SHADOW_ENABLE (1 << 3)
+# define RADEON_TEX_ENABLE_MASK (0xf << 4)
+# define RADEON_TEX_0_ENABLE (1 << 4)
+# define RADEON_TEX_1_ENABLE (1 << 5)
+# define RADEON_TEX_2_ENABLE (1 << 6)
+# define RADEON_TEX_3_ENABLE (1 << 7)
+# define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12)
+# define RADEON_TEX_BLEND_0_ENABLE (1 << 12)
+# define RADEON_TEX_BLEND_1_ENABLE (1 << 13)
+# define RADEON_TEX_BLEND_2_ENABLE (1 << 14)
+# define RADEON_TEX_BLEND_3_ENABLE (1 << 15)
+# define RADEON_PLANAR_YUV_ENABLE (1 << 20)
+# define RADEON_SPECULAR_ENABLE (1 << 21)
+# define RADEON_FOG_ENABLE (1 << 22)
+# define RADEON_ALPHA_TEST_ENABLE (1 << 23)
+# define RADEON_ANTI_ALIAS_NONE (0 << 24)
+# define RADEON_ANTI_ALIAS_LINE (1 << 24)
+# define RADEON_ANTI_ALIAS_POLY (2 << 24)
+# define RADEON_ANTI_ALIAS_LINE_POLY (3 << 24)
+# define RADEON_BUMP_MAP_ENABLE (1 << 26)
+# define RADEON_BUMPED_MAP_T0 (0 << 27)
+# define RADEON_BUMPED_MAP_T1 (1 << 27)
+# define RADEON_BUMPED_MAP_T2 (2 << 27)
+# define RADEON_TEX_3D_ENABLE_0 (1 << 29)
+# define RADEON_TEX_3D_ENABLE_1 (1 << 30)
+# define RADEON_MC_ENABLE (1 << 31)
+#define RADEON_PP_FOG_COLOR 0x1c18
+# define RADEON_FOG_COLOR_MASK 0x00ffffff
+# define RADEON_FOG_VERTEX (0 << 24)
+# define RADEON_FOG_TABLE (1 << 24)
+# define RADEON_FOG_USE_DEPTH (0 << 25)
+# define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25)
+# define RADEON_FOG_USE_SPEC_ALPHA (3 << 25)
+#define RADEON_PP_LUM_MATRIX 0x1d00
+#define RADEON_PP_MISC 0x1c14
+# define RADEON_REF_ALPHA_MASK 0x000000ff
+# define RADEON_ALPHA_TEST_FAIL (0 << 8)
+# define RADEON_ALPHA_TEST_LESS (1 << 8)
+# define RADEON_ALPHA_TEST_LEQUAL (2 << 8)
+# define RADEON_ALPHA_TEST_EQUAL (3 << 8)
+# define RADEON_ALPHA_TEST_GEQUAL (4 << 8)
+# define RADEON_ALPHA_TEST_GREATER (5 << 8)
+# define RADEON_ALPHA_TEST_NEQUAL (6 << 8)
+# define RADEON_ALPHA_TEST_PASS (7 << 8)
+# define RADEON_ALPHA_TEST_OP_MASK (7 << 8)
+# define RADEON_CHROMA_FUNC_FAIL (0 << 16)
+# define RADEON_CHROMA_FUNC_PASS (1 << 16)
+# define RADEON_CHROMA_FUNC_NEQUAL (2 << 16)
+# define RADEON_CHROMA_FUNC_EQUAL (3 << 16)
+# define RADEON_CHROMA_KEY_NEAREST (0 << 18)
+# define RADEON_CHROMA_KEY_ZERO (1 << 18)
+# define RADEON_SHADOW_ID_AUTO_INC (1 << 20)
+# define RADEON_SHADOW_FUNC_EQUAL (0 << 21)
+# define RADEON_SHADOW_FUNC_NEQUAL (1 << 21)
+# define RADEON_SHADOW_PASS_1 (0 << 22)
+# define RADEON_SHADOW_PASS_2 (1 << 22)
+# define RADEON_RIGHT_HAND_CUBE_D3D (0 << 24)
+# define RADEON_RIGHT_HAND_CUBE_OGL (1 << 24)
+#define RADEON_PP_ROT_MATRIX_0 0x1d58
+#define RADEON_PP_ROT_MATRIX_1 0x1d5c
+#define RADEON_PP_TXFILTER_0 0x1c54
+#define RADEON_PP_TXFILTER_1 0x1c6c
+#define RADEON_PP_TXFILTER_2 0x1c84
+# define RADEON_MAG_FILTER_NEAREST (0 << 0)
+# define RADEON_MAG_FILTER_LINEAR (1 << 0)
+# define RADEON_MAG_FILTER_MASK (1 << 0)
+# define RADEON_MIN_FILTER_NEAREST (0 << 1)
+# define RADEON_MIN_FILTER_LINEAR (1 << 1)
+# define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1)
+# define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1)
+# define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1)
+# define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1)
+# define RADEON_MIN_FILTER_ANISO_NEAREST (8 << 1)
+# define RADEON_MIN_FILTER_ANISO_LINEAR (9 << 1)
+# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1)
+# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1)
+# define RADEON_MIN_FILTER_MASK (15 << 1)
+# define RADEON_MAX_ANISO_1_TO_1 (0 << 5)
+# define RADEON_MAX_ANISO_2_TO_1 (1 << 5)
+# define RADEON_MAX_ANISO_4_TO_1 (2 << 5)
+# define RADEON_MAX_ANISO_8_TO_1 (3 << 5)
+# define RADEON_MAX_ANISO_16_TO_1 (4 << 5)
+# define RADEON_MAX_ANISO_MASK (7 << 5)
+# define RADEON_LOD_BIAS_MASK (0xff << 8)
+# define RADEON_LOD_BIAS_SHIFT 8
+# define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16)
+# define RADEON_MAX_MIP_LEVEL_SHIFT 16
+# define RADEON_WRAPEN_S (1 << 22)
+# define RADEON_CLAMP_S_WRAP (0 << 23)
+# define RADEON_CLAMP_S_MIRROR (1 << 23)
+# define RADEON_CLAMP_S_CLAMP_LAST (2 << 23)
+# define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23)
+# define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23)
+# define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23)
+# define RADEON_CLAMP_S_MASK (7 << 23)
+# define RADEON_WRAPEN_T (1 << 26)
+# define RADEON_CLAMP_T_WRAP (0 << 27)
+# define RADEON_CLAMP_T_MIRROR (1 << 27)
+# define RADEON_CLAMP_T_CLAMP_LAST (2 << 27)
+# define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27)
+# define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27)
+# define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27)
+# define RADEON_CLAMP_T_MASK (7 << 27)
+# define RADEON_BORDER_MODE_OGL (0 << 31)
+# define RADEON_BORDER_MODE_D3D (1 << 31)
+#define RADEON_PP_TXFORMAT_0 0x1c58
+#define RADEON_PP_TXFORMAT_1 0x1c70
+#define RADEON_PP_TXFORMAT_2 0x1c88
+# define RADEON_TXFORMAT_I8 (0 << 0)
+# define RADEON_TXFORMAT_AI88 (1 << 0)
+# define RADEON_TXFORMAT_RGB332 (2 << 0)
+# define RADEON_TXFORMAT_ARGB1555 (3 << 0)
+# define RADEON_TXFORMAT_RGB565 (4 << 0)
+# define RADEON_TXFORMAT_ARGB4444 (5 << 0)
+# define RADEON_TXFORMAT_ARGB8888 (6 << 0)
+# define RADEON_TXFORMAT_RGBA8888 (7 << 0)
+# define RADEON_TXFORMAT_Y8 (8 << 0)
+# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0)
+# define RADEON_TXFORMAT_FORMAT_SHIFT 0
+# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5)
+# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6)
+# define RADEON_TXFORMAT_NON_POWER2 (1 << 7)
+# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8)
+# define RADEON_TXFORMAT_WIDTH_SHIFT 8
+# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12)
+# define RADEON_TXFORMAT_HEIGHT_SHIFT 12
+# define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16)
+# define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16
+# define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20)
+# define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20
+# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24)
+# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24)
+# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24)
+# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24)
+# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26)
+# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26)
+# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26)
+# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26)
+# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28)
+# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29)
+# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30)
+# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31)
+#define RADEON_PP_CUBIC_FACES_0 0x1d24
+#define RADEON_PP_CUBIC_FACES_1 0x1d28
+#define RADEON_PP_CUBIC_FACES_2 0x1d2c
+# define RADEON_FACE_WIDTH_1_SHIFT 0
+# define RADEON_FACE_HEIGHT_1_SHIFT 4
+# define RADEON_FACE_WIDTH_1_MASK (0xf << 0)
+# define RADEON_FACE_HEIGHT_1_MASK (0xf << 4)
+# define RADEON_FACE_WIDTH_2_SHIFT 8
+# define RADEON_FACE_HEIGHT_2_SHIFT 12
+# define RADEON_FACE_WIDTH_2_MASK (0xf << 8)
+# define RADEON_FACE_HEIGHT_2_MASK (0xf << 12)
+# define RADEON_FACE_WIDTH_3_SHIFT 16
+# define RADEON_FACE_HEIGHT_3_SHIFT 20
+# define RADEON_FACE_WIDTH_3_MASK (0xf << 16)
+# define RADEON_FACE_HEIGHT_3_MASK (0xf << 20)
+# define RADEON_FACE_WIDTH_4_SHIFT 24
+# define RADEON_FACE_HEIGHT_4_SHIFT 28
+# define RADEON_FACE_WIDTH_4_MASK (0xf << 24)
+# define RADEON_FACE_HEIGHT_4_MASK (0xf << 28)
+
+#define RADEON_PP_TXOFFSET_0 0x1c5c
+#define RADEON_PP_TXOFFSET_1 0x1c74
+#define RADEON_PP_TXOFFSET_2 0x1c8c
+# define RADEON_TXO_ENDIAN_NO_SWAP (0 << 0)
+# define RADEON_TXO_ENDIAN_BYTE_SWAP (1 << 0)
+# define RADEON_TXO_ENDIAN_WORD_SWAP (2 << 0)
+# define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+# define RADEON_TXO_MACRO_LINEAR (0 << 2)
+# define RADEON_TXO_MACRO_TILE (1 << 2)
+# define RADEON_TXO_MICRO_LINEAR (0 << 3)
+# define RADEON_TXO_MICRO_TILE_X2 (1 << 3)
+# define RADEON_TXO_MICRO_TILE_OPT (2 << 3)
+# define RADEON_TXO_OFFSET_MASK 0xffffffe0
+# define RADEON_TXO_OFFSET_SHIFT 5
+
+#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4
+#define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8
+#define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc
+#define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0
+#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04
+#define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08
+#define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c
+#define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10
+#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14
+#define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18
+#define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c
+#define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20
+#define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24
+
+#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
+#define RADEON_PP_TEX_SIZE_1 0x1d0c
+#define RADEON_PP_TEX_SIZE_2 0x1d14
+# define RADEON_TEX_USIZE_MASK (0x7ff << 0)
+# define RADEON_TEX_USIZE_SHIFT 0
+# define RADEON_TEX_VSIZE_MASK (0x7ff << 16)
+# define RADEON_TEX_VSIZE_SHIFT 16
+# define RADEON_SIGNED_RGB_MASK (1 << 30)
+# define RADEON_SIGNED_RGB_SHIFT 30
+# define RADEON_SIGNED_ALPHA_MASK (1 << 31)
+# define RADEON_SIGNED_ALPHA_SHIFT 31
+
+#define RADEON_PP_TXCBLEND_0 0x1c60
+#define RADEON_PP_TXCBLEND_1 0x1c78
+#define RADEON_PP_TXCBLEND_2 0x1c90
+# define RADEON_COLOR_ARG_A_SHIFT 0
+# define RADEON_COLOR_ARG_A_MASK (0x1f << 0)
+# define RADEON_COLOR_ARG_A_ZERO (0 << 0)
+# define RADEON_COLOR_ARG_A_CURRENT_COLOR (2 << 0)
+# define RADEON_COLOR_ARG_A_CURRENT_ALPHA (3 << 0)
+# define RADEON_COLOR_ARG_A_DIFFUSE_COLOR (4 << 0)
+# define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA (5 << 0)
+# define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6 << 0)
+# define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7 << 0)
+# define RADEON_COLOR_ARG_A_TFACTOR_COLOR (8 << 0)
+# define RADEON_COLOR_ARG_A_TFACTOR_ALPHA (9 << 0)
+# define RADEON_COLOR_ARG_A_T0_COLOR (10 << 0)
+# define RADEON_COLOR_ARG_A_T0_ALPHA (11 << 0)
+# define RADEON_COLOR_ARG_A_T1_COLOR (12 << 0)
+# define RADEON_COLOR_ARG_A_T1_ALPHA (13 << 0)
+# define RADEON_COLOR_ARG_A_T2_COLOR (14 << 0)
+# define RADEON_COLOR_ARG_A_T2_ALPHA (15 << 0)
+# define RADEON_COLOR_ARG_A_T3_COLOR (16 << 0)
+# define RADEON_COLOR_ARG_A_T3_ALPHA (17 << 0)
+# define RADEON_COLOR_ARG_B_SHIFT 5
+# define RADEON_COLOR_ARG_B_MASK (0x1f << 5)
+# define RADEON_COLOR_ARG_B_ZERO (0 << 5)
+# define RADEON_COLOR_ARG_B_CURRENT_COLOR (2 << 5)
+# define RADEON_COLOR_ARG_B_CURRENT_ALPHA (3 << 5)
+# define RADEON_COLOR_ARG_B_DIFFUSE_COLOR (4 << 5)
+# define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA (5 << 5)
+# define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6 << 5)
+# define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7 << 5)
+# define RADEON_COLOR_ARG_B_TFACTOR_COLOR (8 << 5)
+# define RADEON_COLOR_ARG_B_TFACTOR_ALPHA (9 << 5)
+# define RADEON_COLOR_ARG_B_T0_COLOR (10 << 5)
+# define RADEON_COLOR_ARG_B_T0_ALPHA (11 << 5)
+# define RADEON_COLOR_ARG_B_T1_COLOR (12 << 5)
+# define RADEON_COLOR_ARG_B_T1_ALPHA (13 << 5)
+# define RADEON_COLOR_ARG_B_T2_COLOR (14 << 5)
+# define RADEON_COLOR_ARG_B_T2_ALPHA (15 << 5)
+# define RADEON_COLOR_ARG_B_T3_COLOR (16 << 5)
+# define RADEON_COLOR_ARG_B_T3_ALPHA (17 << 5)
+# define RADEON_COLOR_ARG_C_SHIFT 10
+# define RADEON_COLOR_ARG_C_MASK (0x1f << 10)
+# define RADEON_COLOR_ARG_C_ZERO (0 << 10)
+# define RADEON_COLOR_ARG_C_CURRENT_COLOR (2 << 10)
+# define RADEON_COLOR_ARG_C_CURRENT_ALPHA (3 << 10)
+# define RADEON_COLOR_ARG_C_DIFFUSE_COLOR (4 << 10)
+# define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA (5 << 10)
+# define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6 << 10)
+# define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7 << 10)
+# define RADEON_COLOR_ARG_C_TFACTOR_COLOR (8 << 10)
+# define RADEON_COLOR_ARG_C_TFACTOR_ALPHA (9 << 10)
+# define RADEON_COLOR_ARG_C_T0_COLOR (10 << 10)
+# define RADEON_COLOR_ARG_C_T0_ALPHA (11 << 10)
+# define RADEON_COLOR_ARG_C_T1_COLOR (12 << 10)
+# define RADEON_COLOR_ARG_C_T1_ALPHA (13 << 10)
+# define RADEON_COLOR_ARG_C_T2_COLOR (14 << 10)
+# define RADEON_COLOR_ARG_C_T2_ALPHA (15 << 10)
+# define RADEON_COLOR_ARG_C_T3_COLOR (16 << 10)
+# define RADEON_COLOR_ARG_C_T3_ALPHA (17 << 10)
+# define RADEON_COMP_ARG_A (1 << 15)
+# define RADEON_COMP_ARG_A_SHIFT 15
+# define RADEON_COMP_ARG_B (1 << 16)
+# define RADEON_COMP_ARG_B_SHIFT 16
+# define RADEON_COMP_ARG_C (1 << 17)
+# define RADEON_COMP_ARG_C_SHIFT 17
+# define RADEON_BLEND_CTL_MASK (7 << 18)
+# define RADEON_BLEND_CTL_ADD (0 << 18)
+# define RADEON_BLEND_CTL_SUBTRACT (1 << 18)
+# define RADEON_BLEND_CTL_ADDSIGNED (2 << 18)
+# define RADEON_BLEND_CTL_BLEND (3 << 18)
+# define RADEON_BLEND_CTL_DOT3 (4 << 18)
+# define RADEON_SCALE_SHIFT 21
+# define RADEON_SCALE_MASK (3 << 21)
+# define RADEON_SCALE_1X (0 << 21)
+# define RADEON_SCALE_2X (1 << 21)
+# define RADEON_SCALE_4X (2 << 21)
+# define RADEON_CLAMP_TX (1 << 23)
+# define RADEON_T0_EQ_TCUR (1 << 24)
+# define RADEON_T1_EQ_TCUR (1 << 25)
+# define RADEON_T2_EQ_TCUR (1 << 26)
+# define RADEON_T3_EQ_TCUR (1 << 27)
+# define RADEON_COLOR_ARG_MASK 0x1f
+# define RADEON_COMP_ARG_SHIFT 15
+#define RADEON_PP_TXABLEND_0 0x1c64
+#define RADEON_PP_TXABLEND_1 0x1c7c
+#define RADEON_PP_TXABLEND_2 0x1c94
+# define RADEON_ALPHA_ARG_A_SHIFT 0
+# define RADEON_ALPHA_ARG_A_MASK (0xf << 0)
+# define RADEON_ALPHA_ARG_A_ZERO (0 << 0)
+# define RADEON_ALPHA_ARG_A_CURRENT_ALPHA (1 << 0)
+# define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA (2 << 0)
+# define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3 << 0)
+# define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA (4 << 0)
+# define RADEON_ALPHA_ARG_A_T0_ALPHA (5 << 0)
+# define RADEON_ALPHA_ARG_A_T1_ALPHA (6 << 0)
+# define RADEON_ALPHA_ARG_A_T2_ALPHA (7 << 0)
+# define RADEON_ALPHA_ARG_A_T3_ALPHA (8 << 0)
+# define RADEON_ALPHA_ARG_B_SHIFT 4
+# define RADEON_ALPHA_ARG_B_MASK (0xf << 4)
+# define RADEON_ALPHA_ARG_B_ZERO (0 << 4)
+# define RADEON_ALPHA_ARG_B_CURRENT_ALPHA (1 << 4)
+# define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA (2 << 4)
+# define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3 << 4)
+# define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA (4 << 4)
+# define RADEON_ALPHA_ARG_B_T0_ALPHA (5 << 4)
+# define RADEON_ALPHA_ARG_B_T1_ALPHA (6 << 4)
+# define RADEON_ALPHA_ARG_B_T2_ALPHA (7 << 4)
+# define RADEON_ALPHA_ARG_B_T3_ALPHA (8 << 4)
+# define RADEON_ALPHA_ARG_C_SHIFT 8
+# define RADEON_ALPHA_ARG_C_MASK (0xf << 8)
+# define RADEON_ALPHA_ARG_C_ZERO (0 << 8)
+# define RADEON_ALPHA_ARG_C_CURRENT_ALPHA (1 << 8)
+# define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA (2 << 8)
+# define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3 << 8)
+# define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA (4 << 8)
+# define RADEON_ALPHA_ARG_C_T0_ALPHA (5 << 8)
+# define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8)
+# define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8)
+# define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8)
+# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9)
+# define RADEON_ALPHA_ARG_MASK 0xf
+
+#define RADEON_PP_TFACTOR_0 0x1c68
+#define RADEON_PP_TFACTOR_1 0x1c80
+#define RADEON_PP_TFACTOR_2 0x1c98
+
+#define RADEON_RB3D_BLENDCNTL 0x1c20
+# define RADEON_COMB_FCN_MASK (3 << 12)
+# define RADEON_COMB_FCN_ADD_CLAMP (0 << 12)
+# define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12)
+# define RADEON_COMB_FCN_SUB_CLAMP (2 << 12)
+# define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12)
+# define RADEON_SRC_BLEND_GL_ZERO (32 << 16)
+# define RADEON_SRC_BLEND_GL_ONE (33 << 16)
+# define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16)
+# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
+# define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16)
+# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
+# define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16)
+# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
+# define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16)
+# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
+# define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16)
+# define RADEON_SRC_BLEND_MASK (63 << 16)
+# define RADEON_DST_BLEND_GL_ZERO (32 << 24)
+# define RADEON_DST_BLEND_GL_ONE (33 << 24)
+# define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24)
+# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
+# define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24)
+# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
+# define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24)
+# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
+# define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24)
+# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
+# define RADEON_DST_BLEND_MASK (63 << 24)
+#define RADEON_RB3D_CNTL 0x1c3c
+# define RADEON_ALPHA_BLEND_ENABLE (1 << 0)
+# define RADEON_PLANE_MASK_ENABLE (1 << 1)
+# define RADEON_DITHER_ENABLE (1 << 2)
+# define RADEON_ROUND_ENABLE (1 << 3)
+# define RADEON_SCALE_DITHER_ENABLE (1 << 4)
+# define RADEON_DITHER_INIT (1 << 5)
+# define RADEON_ROP_ENABLE (1 << 6)
+# define RADEON_STENCIL_ENABLE (1 << 7)
+# define RADEON_Z_ENABLE (1 << 8)
+# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9)
+# define RADEON_COLOR_FORMAT_ARGB1555 (3 << 10)
+# define RADEON_COLOR_FORMAT_RGB565 (4 << 10)
+# define RADEON_COLOR_FORMAT_ARGB8888 (6 << 10)
+# define RADEON_COLOR_FORMAT_RGB332 (7 << 10)
+# define RADEON_COLOR_FORMAT_Y8 (8 << 10)
+# define RADEON_COLOR_FORMAT_RGB8 (9 << 10)
+# define RADEON_COLOR_FORMAT_YUV422_VYUY (11 << 10)
+# define RADEON_COLOR_FORMAT_YUV422_YVYU (12 << 10)
+# define RADEON_COLOR_FORMAT_aYUV444 (14 << 10)
+# define RADEON_COLOR_FORMAT_ARGB4444 (15 << 10)
+# define RADEON_CLRCMP_FLIP_ENABLE (1 << 14)
+#define RADEON_RB3D_COLOROFFSET 0x1c40
+# define RADEON_COLOROFFSET_MASK 0xfffffff0
+#define RADEON_RB3D_COLORPITCH 0x1c48
+# define RADEON_COLORPITCH_MASK 0x000001ff8
+# define RADEON_COLOR_TILE_ENABLE (1 << 16)
+# define RADEON_COLOR_MICROTILE_ENABLE (1 << 17)
+# define RADEON_COLOR_ENDIAN_NO_SWAP (0 << 18)
+# define RADEON_COLOR_ENDIAN_WORD_SWAP (1 << 18)
+# define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18)
+#define RADEON_RB3D_DEPTHOFFSET 0x1c24
+#define RADEON_RB3D_DEPTHPITCH 0x1c28
+# define RADEON_DEPTHPITCH_MASK 0x00001ff8
+# define RADEON_DEPTH_ENDIAN_NO_SWAP (0 << 18)
+# define RADEON_DEPTH_ENDIAN_WORD_SWAP (1 << 18)
+# define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18)
+#define RADEON_RB3D_PLANEMASK 0x1d84
+#define RADEON_RB3D_ROPCNTL 0x1d80
+# define RADEON_ROP_MASK (15 << 8)
+# define RADEON_ROP_CLEAR (0 << 8)
+# define RADEON_ROP_NOR (1 << 8)
+# define RADEON_ROP_AND_INVERTED (2 << 8)
+# define RADEON_ROP_COPY_INVERTED (3 << 8)
+# define RADEON_ROP_AND_REVERSE (4 << 8)
+# define RADEON_ROP_INVERT (5 << 8)
+# define RADEON_ROP_XOR (6 << 8)
+# define RADEON_ROP_NAND (7 << 8)
+# define RADEON_ROP_AND (8 << 8)
+# define RADEON_ROP_EQUIV (9 << 8)
+# define RADEON_ROP_NOOP (10 << 8)
+# define RADEON_ROP_OR_INVERTED (11 << 8)
+# define RADEON_ROP_COPY (12 << 8)
+# define RADEON_ROP_OR_REVERSE (13 << 8)
+# define RADEON_ROP_OR (14 << 8)
+# define RADEON_ROP_SET (15 << 8)
+#define RADEON_RB3D_STENCILREFMASK 0x1d7c
+# define RADEON_STENCIL_REF_SHIFT 0
+# define RADEON_STENCIL_REF_MASK (0xff << 0)
+# define RADEON_STENCIL_MASK_SHIFT 16
+# define RADEON_STENCIL_VALUE_MASK (0xff << 16)
+# define RADEON_STENCIL_WRITEMASK_SHIFT 24
+# define RADEON_STENCIL_WRITE_MASK (0xff << 24)
+#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
+# define RADEON_DEPTH_FORMAT_MASK (0xf << 0)
+# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0)
+# define RADEON_DEPTH_FORMAT_32BIT_INT_Z (4 << 0)
+# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0)
+# define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7 << 0)
+# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0)
+# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0)
+# define RADEON_Z_TEST_NEVER (0 << 4)
+# define RADEON_Z_TEST_LESS (1 << 4)
+# define RADEON_Z_TEST_LEQUAL (2 << 4)
+# define RADEON_Z_TEST_EQUAL (3 << 4)
+# define RADEON_Z_TEST_GEQUAL (4 << 4)
+# define RADEON_Z_TEST_GREATER (5 << 4)
+# define RADEON_Z_TEST_NEQUAL (6 << 4)
+# define RADEON_Z_TEST_ALWAYS (7 << 4)
+# define RADEON_Z_TEST_MASK (7 << 4)
+# define RADEON_STENCIL_TEST_NEVER (0 << 12)
+# define RADEON_STENCIL_TEST_LESS (1 << 12)
+# define RADEON_STENCIL_TEST_LEQUAL (2 << 12)
+# define RADEON_STENCIL_TEST_EQUAL (3 << 12)
+# define RADEON_STENCIL_TEST_GEQUAL (4 << 12)
+# define RADEON_STENCIL_TEST_GREATER (5 << 12)
+# define RADEON_STENCIL_TEST_NEQUAL (6 << 12)
+# define RADEON_STENCIL_TEST_ALWAYS (7 << 12)
+# define RADEON_STENCIL_TEST_MASK (0x7 << 12)
+# define RADEON_STENCIL_FAIL_KEEP (0 << 16)
+# define RADEON_STENCIL_FAIL_ZERO (1 << 16)
+# define RADEON_STENCIL_FAIL_REPLACE (2 << 16)
+# define RADEON_STENCIL_FAIL_INC (3 << 16)
+# define RADEON_STENCIL_FAIL_DEC (4 << 16)
+# define RADEON_STENCIL_FAIL_INVERT (5 << 16)
+# define RADEON_STENCIL_FAIL_MASK (0x7 << 16)
+# define RADEON_STENCIL_ZPASS_KEEP (0 << 20)
+# define RADEON_STENCIL_ZPASS_ZERO (1 << 20)
+# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20)
+# define RADEON_STENCIL_ZPASS_INC (3 << 20)
+# define RADEON_STENCIL_ZPASS_DEC (4 << 20)
+# define RADEON_STENCIL_ZPASS_INVERT (5 << 20)
+# define RADEON_STENCIL_ZPASS_MASK (0x7 << 20)
+# define RADEON_STENCIL_ZFAIL_KEEP (0 << 24)
+# define RADEON_STENCIL_ZFAIL_ZERO (1 << 24)
+# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24)
+# define RADEON_STENCIL_ZFAIL_INC (3 << 24)
+# define RADEON_STENCIL_ZFAIL_DEC (4 << 24)
+# define RADEON_STENCIL_ZFAIL_INVERT (5 << 24)
+# define RADEON_STENCIL_ZFAIL_MASK (0x7 << 24)
+# define RADEON_Z_COMPRESSION_ENABLE (1 << 28)
+# define RADEON_FORCE_Z_DIRTY (1 << 29)
+# define RADEON_Z_WRITE_ENABLE (1 << 30)
+#define RADEON_RE_LINE_PATTERN 0x1cd0
+# define RADEON_LINE_PATTERN_MASK 0x0000ffff
+# define RADEON_LINE_REPEAT_COUNT_SHIFT 16
+# define RADEON_LINE_PATTERN_START_SHIFT 24
+# define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28)
+# define RADEON_LINE_PATTERN_BIG_BIT_ORDER (1 << 28)
+# define RADEON_LINE_PATTERN_AUTO_RESET (1 << 29)
+#define RADEON_RE_LINE_STATE 0x1cd4
+# define RADEON_LINE_CURRENT_PTR_SHIFT 0
+# define RADEON_LINE_CURRENT_COUNT_SHIFT 8
+#define RADEON_RE_MISC 0x26c4
+# define RADEON_STIPPLE_COORD_MASK 0x1f
+# define RADEON_STIPPLE_X_OFFSET_SHIFT 0
+# define RADEON_STIPPLE_X_OFFSET_MASK (0x1f << 0)
+# define RADEON_STIPPLE_Y_OFFSET_SHIFT 8
+# define RADEON_STIPPLE_Y_OFFSET_MASK (0x1f << 8)
+# define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16)
+# define RADEON_STIPPLE_BIG_BIT_ORDER (1 << 16)
+#define RADEON_RE_SOLID_COLOR 0x1c1c
+#define RADEON_RE_TOP_LEFT 0x26c0
+# define RADEON_RE_LEFT_SHIFT 0
+# define RADEON_RE_TOP_SHIFT 16
+#define RADEON_RE_WIDTH_HEIGHT 0x1c44
+# define RADEON_RE_WIDTH_SHIFT 0
+# define RADEON_RE_HEIGHT_SHIFT 16
+
+#define RADEON_SE_CNTL 0x1c4c
+# define RADEON_FFACE_CULL_CW (0 << 0)
+# define RADEON_FFACE_CULL_CCW (1 << 0)
+# define RADEON_FFACE_CULL_DIR_MASK (1 << 0)
+# define RADEON_BFACE_CULL (0 << 1)
+# define RADEON_BFACE_SOLID (3 << 1)
+# define RADEON_FFACE_CULL (0 << 3)
+# define RADEON_FFACE_SOLID (3 << 3)
+# define RADEON_FFACE_CULL_MASK (3 << 3)
+# define RADEON_BADVTX_CULL_DISABLE (1 << 5)
+# define RADEON_FLAT_SHADE_VTX_0 (0 << 6)
+# define RADEON_FLAT_SHADE_VTX_1 (1 << 6)
+# define RADEON_FLAT_SHADE_VTX_2 (2 << 6)
+# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6)
+# define RADEON_DIFFUSE_SHADE_SOLID (0 << 8)
+# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8)
+# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8)
+# define RADEON_DIFFUSE_SHADE_MASK (3 << 8)
+# define RADEON_ALPHA_SHADE_SOLID (0 << 10)
+# define RADEON_ALPHA_SHADE_FLAT (1 << 10)
+# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10)
+# define RADEON_ALPHA_SHADE_MASK (3 << 10)
+# define RADEON_SPECULAR_SHADE_SOLID (0 << 12)
+# define RADEON_SPECULAR_SHADE_FLAT (1 << 12)
+# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12)
+# define RADEON_SPECULAR_SHADE_MASK (3 << 12)
+# define RADEON_FOG_SHADE_SOLID (0 << 14)
+# define RADEON_FOG_SHADE_FLAT (1 << 14)
+# define RADEON_FOG_SHADE_GOURAUD (2 << 14)
+# define RADEON_FOG_SHADE_MASK (3 << 14)
+# define RADEON_ZBIAS_ENABLE_POINT (1 << 16)
+# define RADEON_ZBIAS_ENABLE_LINE (1 << 17)
+# define RADEON_ZBIAS_ENABLE_TRI (1 << 18)
+# define RADEON_WIDELINE_ENABLE (1 << 20)
+# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24)
+# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25)
+# define RADEON_VTX_PIX_CENTER_D3D (0 << 27)
+# define RADEON_VTX_PIX_CENTER_OGL (1 << 27)
+# define RADEON_ROUND_MODE_TRUNC (0 << 28)
+# define RADEON_ROUND_MODE_ROUND (1 << 28)
+# define RADEON_ROUND_MODE_ROUND_EVEN (2 << 28)
+# define RADEON_ROUND_MODE_ROUND_ODD (3 << 28)
+# define RADEON_ROUND_PREC_16TH_PIX (0 << 30)
+# define RADEON_ROUND_PREC_8TH_PIX (1 << 30)
+# define RADEON_ROUND_PREC_4TH_PIX (2 << 30)
+# define RADEON_ROUND_PREC_HALF_PIX (3 << 30)
+#define RADEON_SE_CNTL_STATUS 0x2140
+# define RADEON_VC_NO_SWAP (0 << 0)
+# define RADEON_VC_16BIT_SWAP (1 << 0)
+# define RADEON_VC_32BIT_SWAP (2 << 0)
+# define RADEON_VC_HALF_DWORD_SWAP (3 << 0)
+# define RADEON_TCL_BYPASS (1 << 8)
+#define RADEON_SE_COORD_FMT 0x1c50
+# define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0)
+# define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1)
+# define RADEON_VTX_ST0_NONPARAMETRIC (1 << 8)
+# define RADEON_VTX_ST1_NONPARAMETRIC (1 << 9)
+# define RADEON_VTX_ST2_NONPARAMETRIC (1 << 10)
+# define RADEON_VTX_ST3_NONPARAMETRIC (1 << 11)
+# define RADEON_VTX_W0_NORMALIZE (1 << 12)
+# define RADEON_VTX_W0_IS_NOT_1_OVER_W0 (1 << 16)
+# define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17)
+# define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19)
+# define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21)
+# define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23)
+# define RADEON_TEX1_W_ROUTING_USE_W0 (0 << 26)
+# define RADEON_TEX1_W_ROUTING_USE_Q1 (1 << 26)
+#define RADEON_SE_LINE_WIDTH 0x1db8
+#define RADEON_SE_TCL_LIGHT_MODEL_CTL 0x226c
+# define RADEON_LIGHTING_ENABLE (1 << 0)
+# define RADEON_LIGHT_IN_MODELSPACE (1 << 1)
+# define RADEON_LOCAL_VIEWER (1 << 2)
+# define RADEON_NORMALIZE_NORMALS (1 << 3)
+# define RADEON_RESCALE_NORMALS (1 << 4)
+# define RADEON_SPECULAR_LIGHTS (1 << 5)
+# define RADEON_DIFFUSE_SPECULAR_COMBINE (1 << 6)
+# define RADEON_LIGHT_ALPHA (1 << 7)
+# define RADEON_LOCAL_LIGHT_VEC_GL (1 << 8)
+# define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9)
+# define RADEON_LM_SOURCE_STATE_PREMULT 0
+# define RADEON_LM_SOURCE_STATE_MULT 1
+# define RADEON_LM_SOURCE_VERTEX_DIFFUSE 2
+# define RADEON_LM_SOURCE_VERTEX_SPECULAR 3
+# define RADEON_EMISSIVE_SOURCE_SHIFT 16
+# define RADEON_AMBIENT_SOURCE_SHIFT 18
+# define RADEON_DIFFUSE_SOURCE_SHIFT 20
+# define RADEON_SPECULAR_SOURCE_SHIFT 22
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_RED 0x2220
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN 0x2224
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE 0x2228
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA 0x222c
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED 0x2230
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN 0x2234
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE 0x2238
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA 0x223c
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE 0x2218
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_RED 0x2240
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN 0x2244
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE 0x2248
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA 0x224c
+#define RADEON_SE_TCL_MATRIX_SELECT_0 0x225c
+# define RADEON_MODELVIEW_0_SHIFT 0
+# define RADEON_MODELVIEW_1_SHIFT 4
+# define RADEON_MODELVIEW_2_SHIFT 8
+# define RADEON_MODELVIEW_3_SHIFT 12
+# define RADEON_IT_MODELVIEW_0_SHIFT 16
+# define RADEON_IT_MODELVIEW_1_SHIFT 20
+# define RADEON_IT_MODELVIEW_2_SHIFT 24
+# define RADEON_IT_MODELVIEW_3_SHIFT 28
+#define RADEON_SE_TCL_MATRIX_SELECT_1 0x2260
+# define RADEON_MODELPROJECT_0_SHIFT 0
+# define RADEON_MODELPROJECT_1_SHIFT 4
+# define RADEON_MODELPROJECT_2_SHIFT 8
+# define RADEON_MODELPROJECT_3_SHIFT 12
+# define RADEON_TEXMAT_0_SHIFT 16
+# define RADEON_TEXMAT_1_SHIFT 20
+# define RADEON_TEXMAT_2_SHIFT 24
+# define RADEON_TEXMAT_3_SHIFT 28
+
+
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254
+# define RADEON_TCL_VTX_W0 (1 << 0)
+# define RADEON_TCL_VTX_FP_DIFFUSE (1 << 1)
+# define RADEON_TCL_VTX_FP_ALPHA (1 << 2)
+# define RADEON_TCL_VTX_PK_DIFFUSE (1 << 3)
+# define RADEON_TCL_VTX_FP_SPEC (1 << 4)
+# define RADEON_TCL_VTX_FP_FOG (1 << 5)
+# define RADEON_TCL_VTX_PK_SPEC (1 << 6)
+# define RADEON_TCL_VTX_ST0 (1 << 7)
+# define RADEON_TCL_VTX_ST1 (1 << 8)
+# define RADEON_TCL_VTX_Q1 (1 << 9)
+# define RADEON_TCL_VTX_ST2 (1 << 10)
+# define RADEON_TCL_VTX_Q2 (1 << 11)
+# define RADEON_TCL_VTX_ST3 (1 << 12)
+# define RADEON_TCL_VTX_Q3 (1 << 13)
+# define RADEON_TCL_VTX_Q0 (1 << 14)
+# define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15
+# define RADEON_TCL_VTX_NORM0 (1 << 18)
+# define RADEON_TCL_VTX_XY1 (1 << 27)
+# define RADEON_TCL_VTX_Z1 (1 << 28)
+# define RADEON_TCL_VTX_W1 (1 << 29)
+# define RADEON_TCL_VTX_NORM1 (1 << 30)
+# define RADEON_TCL_VTX_Z0 (1 << 31)
+
+#define RADEON_SE_TCL_OUTPUT_VTX_SEL 0x2258
+# define RADEON_TCL_COMPUTE_XYZW (1 << 0)
+# define RADEON_TCL_COMPUTE_DIFFUSE (1 << 1)
+# define RADEON_TCL_COMPUTE_SPECULAR (1 << 2)
+# define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3)
+# define RADEON_TCL_FORCE_INORDER_PROC (1 << 4)
+# define RADEON_TCL_TEX_INPUT_TEX_0 0
+# define RADEON_TCL_TEX_INPUT_TEX_1 1
+# define RADEON_TCL_TEX_INPUT_TEX_2 2
+# define RADEON_TCL_TEX_INPUT_TEX_3 3
+# define RADEON_TCL_TEX_COMPUTED_TEX_0 8
+# define RADEON_TCL_TEX_COMPUTED_TEX_1 9
+# define RADEON_TCL_TEX_COMPUTED_TEX_2 10
+# define RADEON_TCL_TEX_COMPUTED_TEX_3 11
+# define RADEON_TCL_TEX_0_OUTPUT_SHIFT 16
+# define RADEON_TCL_TEX_1_OUTPUT_SHIFT 20
+# define RADEON_TCL_TEX_2_OUTPUT_SHIFT 24
+# define RADEON_TCL_TEX_3_OUTPUT_SHIFT 28
+
+#define RADEON_SE_TCL_PER_LIGHT_CTL_0 0x2270
+# define RADEON_LIGHT_0_ENABLE (1 << 0)
+# define RADEON_LIGHT_0_ENABLE_AMBIENT (1 << 1)
+# define RADEON_LIGHT_0_ENABLE_SPECULAR (1 << 2)
+# define RADEON_LIGHT_0_IS_LOCAL (1 << 3)
+# define RADEON_LIGHT_0_IS_SPOT (1 << 4)
+# define RADEON_LIGHT_0_DUAL_CONE (1 << 5)
+# define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN (1 << 6)
+# define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 << 7)
+# define RADEON_LIGHT_0_SHIFT 0
+# define RADEON_LIGHT_1_ENABLE (1 << 16)
+# define RADEON_LIGHT_1_ENABLE_AMBIENT (1 << 17)
+# define RADEON_LIGHT_1_ENABLE_SPECULAR (1 << 18)
+# define RADEON_LIGHT_1_IS_LOCAL (1 << 19)
+# define RADEON_LIGHT_1_IS_SPOT (1 << 20)
+# define RADEON_LIGHT_1_DUAL_CONE (1 << 21)
+# define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN (1 << 22)
+# define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23)
+# define RADEON_LIGHT_1_SHIFT 16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_1 0x2274
+# define RADEON_LIGHT_2_SHIFT 0
+# define RADEON_LIGHT_3_SHIFT 16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_2 0x2278
+# define RADEON_LIGHT_4_SHIFT 0
+# define RADEON_LIGHT_5_SHIFT 16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_3 0x227c
+# define RADEON_LIGHT_6_SHIFT 0
+# define RADEON_LIGHT_7_SHIFT 16
+
+#define RADEON_SE_TCL_SHININESS 0x2250
+
+#define RADEON_SE_TCL_TEXTURE_PROC_CTL 0x2268
+# define RADEON_TEXGEN_TEXMAT_0_ENABLE (1 << 0)
+# define RADEON_TEXGEN_TEXMAT_1_ENABLE (1 << 1)
+# define RADEON_TEXGEN_TEXMAT_2_ENABLE (1 << 2)
+# define RADEON_TEXGEN_TEXMAT_3_ENABLE (1 << 3)
+# define RADEON_TEXMAT_0_ENABLE (1 << 4)
+# define RADEON_TEXMAT_1_ENABLE (1 << 5)
+# define RADEON_TEXMAT_2_ENABLE (1 << 6)
+# define RADEON_TEXMAT_3_ENABLE (1 << 7)
+# define RADEON_TEXGEN_INPUT_MASK 0xf
+# define RADEON_TEXGEN_INPUT_TEXCOORD_0 0
+# define RADEON_TEXGEN_INPUT_TEXCOORD_1 1
+# define RADEON_TEXGEN_INPUT_TEXCOORD_2 2
+# define RADEON_TEXGEN_INPUT_TEXCOORD_3 3
+# define RADEON_TEXGEN_INPUT_OBJ 4
+# define RADEON_TEXGEN_INPUT_EYE 5
+# define RADEON_TEXGEN_INPUT_EYE_NORMAL 6
+# define RADEON_TEXGEN_INPUT_EYE_REFLECT 7
+# define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8
+# define RADEON_TEXGEN_0_INPUT_SHIFT 16
+# define RADEON_TEXGEN_1_INPUT_SHIFT 20
+# define RADEON_TEXGEN_2_INPUT_SHIFT 24
+# define RADEON_TEXGEN_3_INPUT_SHIFT 28
+
+#define RADEON_SE_TCL_UCP_VERT_BLEND_CTL 0x2264
+# define RADEON_UCP_IN_CLIP_SPACE (1 << 0)
+# define RADEON_UCP_IN_MODEL_SPACE (1 << 1)
+# define RADEON_UCP_ENABLE_0 (1 << 2)
+# define RADEON_UCP_ENABLE_1 (1 << 3)
+# define RADEON_UCP_ENABLE_2 (1 << 4)
+# define RADEON_UCP_ENABLE_3 (1 << 5)
+# define RADEON_UCP_ENABLE_4 (1 << 6)
+# define RADEON_UCP_ENABLE_5 (1 << 7)
+# define RADEON_TCL_FOG_MASK (3 << 8)
+# define RADEON_TCL_FOG_DISABLE (0 << 8)
+# define RADEON_TCL_FOG_EXP (1 << 8)
+# define RADEON_TCL_FOG_EXP2 (2 << 8)
+# define RADEON_TCL_FOG_LINEAR (3 << 8)
+# define RADEON_RNG_BASED_FOG (1 << 10)
+# define RADEON_LIGHT_TWOSIDE (1 << 11)
+# define RADEON_BLEND_OP_COUNT_MASK (7 << 12)
+# define RADEON_BLEND_OP_COUNT_SHIFT 12
+# define RADEON_POSITION_BLEND_OP_ENABLE (1 << 16)
+# define RADEON_NORMAL_BLEND_OP_ENABLE (1 << 17)
+# define RADEON_VERTEX_BLEND_SRC_0_PRIMARY (1 << 18)
+# define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18)
+# define RADEON_VERTEX_BLEND_SRC_1_PRIMARY (1 << 19)
+# define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19)
+# define RADEON_VERTEX_BLEND_SRC_2_PRIMARY (1 << 20)
+# define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20)
+# define RADEON_VERTEX_BLEND_SRC_3_PRIMARY (1 << 21)
+# define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21)
+# define RADEON_VERTEX_BLEND_WGT_MINUS_ONE (1 << 22)
+# define RADEON_CULL_FRONT_IS_CW (0 << 28)
+# define RADEON_CULL_FRONT_IS_CCW (1 << 28)
+# define RADEON_CULL_FRONT (1 << 29)
+# define RADEON_CULL_BACK (1 << 30)
+# define RADEON_FORCE_W_TO_ONE (1 << 31)
+
+#define RADEON_SE_VPORT_XSCALE 0x1d98
+#define RADEON_SE_VPORT_XOFFSET 0x1d9c
+#define RADEON_SE_VPORT_YSCALE 0x1da0
+#define RADEON_SE_VPORT_YOFFSET 0x1da4
+#define RADEON_SE_VPORT_ZSCALE 0x1da8
+#define RADEON_SE_VPORT_ZOFFSET 0x1dac
+#define RADEON_SE_ZBIAS_FACTOR 0x1db0
+#define RADEON_SE_ZBIAS_CONSTANT 0x1db4
+
+
+
+ /* Registers for CP and Microcode Engine */
+#define RADEON_CP_ME_RAM_ADDR 0x07d4
+#define RADEON_CP_ME_RAM_RADDR 0x07d8
+#define RADEON_CP_ME_RAM_DATAH 0x07dc
+#define RADEON_CP_ME_RAM_DATAL 0x07e0
+
+#define RADEON_CP_RB_BASE 0x0700
+#define RADEON_CP_RB_CNTL 0x0704
+#define RADEON_CP_RB_RPTR_ADDR 0x070c
+#define RADEON_CP_RB_RPTR 0x0710
+#define RADEON_CP_RB_WPTR 0x0714
+
+#define RADEON_CP_IB_BASE 0x0738
+#define RADEON_CP_IB_BUFSZ 0x073c
+
+#define RADEON_CP_CSQ_CNTL 0x0740
+# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0)
+# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28)
+# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28)
+# define RADEON_CSQ_PRIBM_INDDIS (2 << 28)
+# define RADEON_CSQ_PRIPIO_INDBM (3 << 28)
+# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
+# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
+#define RADEON_CP_CSQ_STAT 0x07f8
+# define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0)
+# define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8)
+# define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16)
+# define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24)
+#define RADEON_CP_CSQ_ADDR 0x07f0
+#define RADEON_CP_CSQ_DATA 0x07f4
+#define RADEON_CP_CSQ_APER_PRIMARY 0x1000
+#define RADEON_CP_CSQ_APER_INDIRECT 0x1300
+
+#define RADEON_CP_RB_WPTR_DELAY 0x0718
+# define RADEON_PRE_WRITE_TIMER_SHIFT 0
+# define RADEON_PRE_WRITE_LIMIT_SHIFT 23
+
+#define RADEON_AIC_CNTL 0x01d0
+# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
+
+
+
+ /* Constants */
+#define RADEON_AGP_TEX_OFFSET 0x02000000
+
+#define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0
+#define RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2
+
+
+
+ /* CP packet types */
+#define RADEON_CP_PACKET0 0x00000000
+#define RADEON_CP_PACKET1 0x40000000
+#define RADEON_CP_PACKET2 0x80000000
+#define RADEON_CP_PACKET3 0xC0000000
+# define RADEON_CP_PACKET_MASK 0xC0000000
+# define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000
+# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12)
+# define RADEON_CP_PACKET0_REG_MASK 0x000007ff
+# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
+# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
+
+#define RADEON_CP_PACKET0_ONE_REG_WR 0x00008000
+
+#define RADEON_CP_PACKET3_NOP 0xC0001000
+#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900
+#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00
+#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400
+#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600
+#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800
+#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900
+#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00
+#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00
+#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00
+#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100
+#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200
+#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500
+#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+
+
+#define RADEON_CP_VC_FRMT_XY 0x00000000
+#define RADEON_CP_VC_FRMT_W0 0x00000001
+#define RADEON_CP_VC_FRMT_FPCOLOR 0x00000002
+#define RADEON_CP_VC_FRMT_FPALPHA 0x00000004
+#define RADEON_CP_VC_FRMT_PKCOLOR 0x00000008
+#define RADEON_CP_VC_FRMT_FPSPEC 0x00000010
+#define RADEON_CP_VC_FRMT_FPFOG 0x00000020
+#define RADEON_CP_VC_FRMT_PKSPEC 0x00000040
+#define RADEON_CP_VC_FRMT_ST0 0x00000080
+#define RADEON_CP_VC_FRMT_ST1 0x00000100
+#define RADEON_CP_VC_FRMT_Q1 0x00000200
+#define RADEON_CP_VC_FRMT_ST2 0x00000400
+#define RADEON_CP_VC_FRMT_Q2 0x00000800
+#define RADEON_CP_VC_FRMT_ST3 0x00001000
+#define RADEON_CP_VC_FRMT_Q3 0x00002000
+#define RADEON_CP_VC_FRMT_Q0 0x00004000
+#define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK 0x00038000
+#define RADEON_CP_VC_FRMT_N0 0x00040000
+#define RADEON_CP_VC_FRMT_XY1 0x08000000
+#define RADEON_CP_VC_FRMT_Z1 0x10000000
+#define RADEON_CP_VC_FRMT_W1 0x20000000
+#define RADEON_CP_VC_FRMT_N1 0x40000000
+#define RADEON_CP_VC_FRMT_Z 0x80000000
+
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a
+#define RADEON_CP_VC_CNTL_PRIM_WALK_IND 0x00000010
+#define RADEON_CP_VC_CNTL_PRIM_WALK_LIST 0x00000020
+#define RADEON_CP_VC_CNTL_PRIM_WALK_RING 0x00000030
+#define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA 0x00000000
+#define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA 0x00000040
+#define RADEON_CP_VC_CNTL_MAOS_ENABLE 0x00000080
+#define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE 0x00000000
+#define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE 0x00000100
+#define RADEON_CP_VC_CNTL_TCL_DISABLE 0x00000000
+#define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200
+#define RADEON_CP_VC_CNTL_NUM_SHIFT 16
+
+#define RADEON_VS_MATRIX_0_ADDR 0
+#define RADEON_VS_MATRIX_1_ADDR 4
+#define RADEON_VS_MATRIX_2_ADDR 8
+#define RADEON_VS_MATRIX_3_ADDR 12
+#define RADEON_VS_MATRIX_4_ADDR 16
+#define RADEON_VS_MATRIX_5_ADDR 20
+#define RADEON_VS_MATRIX_6_ADDR 24
+#define RADEON_VS_MATRIX_7_ADDR 28
+#define RADEON_VS_MATRIX_8_ADDR 32
+#define RADEON_VS_MATRIX_9_ADDR 36
+#define RADEON_VS_MATRIX_10_ADDR 40
+#define RADEON_VS_MATRIX_11_ADDR 44
+#define RADEON_VS_MATRIX_12_ADDR 48
+#define RADEON_VS_MATRIX_13_ADDR 52
+#define RADEON_VS_MATRIX_14_ADDR 56
+#define RADEON_VS_MATRIX_15_ADDR 60
+#define RADEON_VS_LIGHT_AMBIENT_ADDR 64
+#define RADEON_VS_LIGHT_DIFFUSE_ADDR 72
+#define RADEON_VS_LIGHT_SPECULAR_ADDR 80
+#define RADEON_VS_LIGHT_DIRPOS_ADDR 88
+#define RADEON_VS_LIGHT_HWVSPOT_ADDR 96
+#define RADEON_VS_LIGHT_ATTENUATION_ADDR 104
+#define RADEON_VS_MATRIX_EYE2CLIP_ADDR 112
+#define RADEON_VS_UCP_ADDR 116
+#define RADEON_VS_GLOBAL_AMBIENT_ADDR 122
+#define RADEON_VS_FOG_PARAM_ADDR 123
+#define RADEON_VS_EYE_VECTOR_ADDR 124
+
+#define RADEON_SS_LIGHT_DCD_ADDR 0
+#define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR 8
+#define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR 16
+#define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR 24
+#define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32
+#define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48
+#define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49
+#define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50
+#define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51
+#define RADEON_SS_SHININESS 60
+
+#endif
diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h
new file mode 100644
index 0000000..788c6f6
--- /dev/null
+++ b/src/radeon_sarea.h
@@ -0,0 +1,237 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.5 2002/10/30 12:52:14 alanh Exp $ */
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario,
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@xfree86.org>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _RADEON_SAREA_H_
+#define _RADEON_SAREA_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the kernel file (radeon_drm.h)
+ */
+#ifndef __RADEON_SAREA_DEFINES__
+#define __RADEON_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer? */
+#define RADEON_UPLOAD_CONTEXT 0x00000001
+#define RADEON_UPLOAD_VERTFMT 0x00000002
+#define RADEON_UPLOAD_LINE 0x00000004
+#define RADEON_UPLOAD_BUMPMAP 0x00000008
+#define RADEON_UPLOAD_MASKS 0x00000010
+#define RADEON_UPLOAD_VIEWPORT 0x00000020
+#define RADEON_UPLOAD_SETUP 0x00000040
+#define RADEON_UPLOAD_TCL 0x00000080
+#define RADEON_UPLOAD_MISC 0x00000100
+#define RADEON_UPLOAD_TEX0 0x00000200
+#define RADEON_UPLOAD_TEX1 0x00000400
+#define RADEON_UPLOAD_TEX2 0x00000800
+#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
+#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
+#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
+#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
+#define RADEON_REQUIRE_QUIESCENCE 0x00010000
+#define RADEON_UPLOAD_ZBIAS 0x00020000
+#define RADEON_UPLOAD_ALL 0x0002ffff
+#define RADEON_UPLOAD_CONTEXT_ALL 0x000201ff
+
+#define RADEON_FRONT 0x1
+#define RADEON_BACK 0x2
+#define RADEON_DEPTH 0x4
+#define RADEON_STENCIL 0x8
+
+/* Primitive types */
+#define RADEON_POINTS 0x1
+#define RADEON_LINES 0x2
+#define RADEON_LINE_STRIP 0x3
+#define RADEON_TRIANGLES 0x4
+#define RADEON_TRIANGLE_FAN 0x5
+#define RADEON_TRIANGLE_STRIP 0x6
+#define RADEON_3VTX_POINTS 0x9
+#define RADEON_3VTX_LINES 0xa
+
+/* Vertex/indirect buffer size */
+#define RADEON_BUFFER_SIZE 65536
+
+/* Byte offsets for indirect buffer data */
+#define RADEON_INDEX_PRIM_OFFSET 20
+#define RADEON_HOSTDATA_BLIT_OFFSET 32
+
+#define RADEON_SCRATCH_REG_OFFSET 32
+
+/* Keep these small for testing */
+#define RADEON_NR_SAREA_CLIPRECTS 12
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define RADEON_CARD_HEAP 0
+#define RADEON_AGP_HEAP 1
+#define RADEON_NR_TEX_HEAPS 2
+#define RADEON_NR_TEX_REGIONS 64
+#define RADEON_LOG_TEX_GRANULARITY 16
+
+#define RADEON_MAX_TEXTURE_LEVELS 12
+#define RADEON_MAX_TEXTURE_UNITS 3
+
+/* Blits have strict offset rules. All blit offset must be aligned on
+ * a 1K-byte boundary.
+ */
+#define RADEON_OFFSET_SHIFT 10
+#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
+#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
+
+#endif /* __RADEON_SAREA_DEFINES__ */
+
+typedef struct {
+ unsigned int red;
+ unsigned int green;
+ unsigned int blue;
+ unsigned int alpha;
+} radeon_color_regs_t;
+
+typedef struct {
+ /* Context state */
+ unsigned int pp_misc;
+ unsigned int pp_fog_color;
+ unsigned int re_solid_color;
+ unsigned int rb3d_blendcntl;
+ unsigned int rb3d_depthoffset;
+ unsigned int rb3d_depthpitch;
+ unsigned int rb3d_zstencilcntl;
+
+ unsigned int pp_cntl;
+ unsigned int rb3d_cntl;
+ unsigned int rb3d_coloroffset;
+ unsigned int re_width_height;
+ unsigned int rb3d_colorpitch;
+ unsigned int se_cntl;
+
+ /* Vertex format state */
+ unsigned int se_coord_fmt;
+
+ /* Line state */
+ unsigned int re_line_pattern;
+ unsigned int re_line_state;
+
+ unsigned int se_line_width;
+
+ /* Bumpmap state */
+ unsigned int pp_lum_matrix;
+
+ unsigned int pp_rot_matrix_0;
+ unsigned int pp_rot_matrix_1;
+
+ /* Mask state */
+ unsigned int rb3d_stencilrefmask;
+ unsigned int rb3d_ropcntl;
+ unsigned int rb3d_planemask;
+
+ /* Viewport state */
+ unsigned int se_vport_xscale;
+ unsigned int se_vport_xoffset;
+ unsigned int se_vport_yscale;
+ unsigned int se_vport_yoffset;
+ unsigned int se_vport_zscale;
+ unsigned int se_vport_zoffset;
+
+ /* Setup state */
+ unsigned int se_cntl_status;
+
+ /* Misc state */
+ unsigned int re_top_left;
+ unsigned int re_misc;
+} radeon_context_regs_t;
+
+/* Setup registers for each texture unit */
+typedef struct {
+ unsigned int pp_txfilter;
+ unsigned int pp_txformat;
+ unsigned int pp_txoffset;
+ unsigned int pp_txcblend;
+ unsigned int pp_txablend;
+ unsigned int pp_tfactor;
+ unsigned int pp_border_color;
+} radeon_texture_regs_t;
+
+typedef struct {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} radeon_tex_region_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ radeon_context_regs_t ContextState;
+ radeon_texture_regs_t TexState[RADEON_MAX_TEXTURE_UNITS];
+ unsigned int dirty;
+ unsigned int vertsize;
+ unsigned int vc_format;
+
+ /* The current cliprects, or a subset thereof */
+ XF86DRIClipRectRec boxes[RADEON_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+
+ /* Counters for throttling of rendering clients */
+ unsigned int last_frame;
+ unsigned int last_dispatch;
+ unsigned int last_clear;
+
+ /* Maintain an LRU of contiguous regions of texture space. If you
+ * think you own a region of texture memory, and it has an age
+ * different to the one you set, then you are mistaken and it has
+ * been stolen by another client. If global texAge hasn't changed,
+ * there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained texture
+ * information of other clients - by maintaining them in the same
+ * lru which is used to age their own textures, clients have an
+ * approximate lru for the whole of global texture space, and can
+ * make informed decisions as to which areas to kick out. There is
+ * no need to choose whether to kick out your own texture or someone
+ * else's - simply eject them all in LRU order.
+ */
+ /* Last elt is sentinal */
+ radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+ /* last time texture was uploaded */
+ int texAge[RADEON_NR_TEX_HEAPS];
+
+ int ctxOwner; /* last context to upload state */
+ int pfAllowPageFlip; /* set by the 2d driver, read by the client */
+ int pfCurrentPage; /* set by kernel, read by others */
+ int crtc2_base; /* for pageflipping with CloneMode */
+} RADEONSAREAPriv, *RADEONSAREAPrivPtr;
+
+#endif
diff --git a/src/radeon_version.h b/src/radeon_version.h
new file mode 100644
index 0000000..a1170d3
--- /dev/null
+++ b/src/radeon_version.h
@@ -0,0 +1,63 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h,v 1.8 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _RADEON_VERSION_H_
+#define _RADEON_VERSION_H_ 1
+
+#undef RADEON_NAME
+#undef RADEON_DRIVER_NAME
+#undef R200_DRIVER_NAME
+#undef RADEON_VERSION_MAJOR
+#undef RADEON_VERSION_MINOR
+#undef RADEON_VERSION_PATCH
+#undef RADEON_VERSION_CURRENT
+#undef RADEON_VERSION_EVALUATE
+#undef RADEON_VERSION_STRINGIFY
+#undef RADEON_VERSION_NAME
+
+#define RADEON_NAME "RADEON"
+#define RADEON_DRIVER_NAME "radeon"
+#define R200_DRIVER_NAME "r200"
+#define RV250_DRIVER_NAME "r200"
+
+#define RADEON_VERSION_MAJOR 4
+#define RADEON_VERSION_MINOR 0
+#define RADEON_VERSION_PATCH 1
+
+#ifndef RADEON_VERSION_EXTRA
+#define RADEON_VERSION_EXTRA ""
+#endif
+
+#define RADEON_VERSION_CURRENT \
+ ((RADEON_VERSION_MAJOR << 20) | \
+ (RADEON_VERSION_MINOR << 10) | \
+ (RADEON_VERSION_PATCH))
+
+#define RADEON_VERSION_EVALUATE(__x) #__x
+#define RADEON_VERSION_STRINGIFY(_x) RADEON_VERSION_EVALUATE(_x)
+#define RADEON_VERSION_NAME \
+ RADEON_VERSION_STRINGIFY(RADEON_VERSION_MAJOR) "." \
+ RADEON_VERSION_STRINGIFY(RADEON_VERSION_MINOR) "." \
+ RADEON_VERSION_STRINGIFY(RADEON_VERSION_PATCH) RADEON_VERSION_EXTRA
+
+#endif /* _RADEON_VERSION_H_ */
diff --git a/src/radeon_video.c b/src/radeon_video.c
new file mode 100644
index 0000000..44ee2e6
--- /dev/null
+++ b/src/radeon_video.c
@@ -0,0 +1,1586 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.24 2003/02/19 01:19:43 dawes Exp $ */
+
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_reg.h"
+
+#include "xf86.h"
+#include "dixstruct.h"
+
+#include "Xv.h"
+#include "fourcc.h"
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+extern int gRADEONEntityIndex;
+
+#ifndef XvExtension
+void RADEONInitVideo(ScreenPtr pScreen) {}
+#else
+
+static void RADEONInitOffscreenImages(ScreenPtr);
+
+static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
+static int RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static void RADEONStopVideo(ScrnInfoPtr, pointer, Bool);
+static void RADEONQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
+ unsigned int *, unsigned int *, pointer);
+static int RADEONPutImage(ScrnInfoPtr, short, short, short, short, short,
+ short, short, short, int, unsigned char*, short,
+ short, Bool, RegionPtr, pointer);
+static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
+ unsigned short *, int *, int *);
+
+
+static void RADEONResetVideo(ScrnInfoPtr);
+
+static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
+static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity;
+static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults;
+
+typedef struct {
+ CARD32 transform_index;
+ int brightness;
+ int saturation;
+ int hue;
+ int contrast;
+ int red_intensity;
+ int green_intensity;
+ int blue_intensity;
+ int ecp_div;
+
+ Bool doubleBuffer;
+ unsigned char currentBuffer;
+ RegionRec clip;
+ CARD32 colorKey;
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ Bool autopaint_colorkey;
+} RADEONPortPrivRec, *RADEONPortPrivPtr;
+
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+
+void RADEONInitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+ if(info->accel && info->accel->FillSolidRects)
+ {
+ newAdaptor = RADEONSetupImageVideo(pScreen);
+ RADEONInitOffscreenImages(pScreen);
+ }
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if(newAdaptor) {
+ if(!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ xfree(newAdaptors);
+}
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding =
+{
+ 0,
+ "XV_IMAGE",
+ 2048, 2048,
+ {1, 1}
+};
+
+#define NUM_FORMATS 12
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+ {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
+ {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
+ {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
+};
+
+
+#define NUM_ATTRIBUTES 9+3
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+ {XvSettable , 0, 1, "XV_SET_DEFAULTS"},
+ {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
+ {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"},
+ {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"},
+};
+
+#define NUM_IMAGES 4
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_UYVY,
+ XVIMAGE_YV12,
+ XVIMAGE_I420
+};
+
+/* Reference color space transform data */
+typedef struct tagREF_TRANSFORM
+{
+ float RefLuma;
+ float RefRCb;
+ float RefRCr;
+ float RefGCb;
+ float RefGCr;
+ float RefBCb;
+ float RefBCr;
+} REF_TRANSFORM;
+
+/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
+REF_TRANSFORM trans[2] =
+{
+ {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
+ {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
+};
+
+
+/* Gamma curve definition */
+typedef struct
+{
+ unsigned int gammaReg;
+ unsigned int gammaSlope;
+ unsigned int gammaOffset;
+} GAMMA_SETTINGS;
+
+/* Recommended gamma curve parameters */
+GAMMA_SETTINGS def_gamma[18] =
+{
+ {RADEON_OV0_GAMMA_000_00F, 0x100, 0x0000},
+ {RADEON_OV0_GAMMA_010_01F, 0x100, 0x0020},
+ {RADEON_OV0_GAMMA_020_03F, 0x100, 0x0040},
+ {RADEON_OV0_GAMMA_040_07F, 0x100, 0x0080},
+ {RADEON_OV0_GAMMA_080_0BF, 0x100, 0x0100},
+ {RADEON_OV0_GAMMA_0C0_0FF, 0x100, 0x0100},
+ {RADEON_OV0_GAMMA_100_13F, 0x100, 0x0200},
+ {RADEON_OV0_GAMMA_140_17F, 0x100, 0x0200},
+ {RADEON_OV0_GAMMA_180_1BF, 0x100, 0x0300},
+ {RADEON_OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
+ {RADEON_OV0_GAMMA_200_23F, 0x100, 0x0400},
+ {RADEON_OV0_GAMMA_240_27F, 0x100, 0x0400},
+ {RADEON_OV0_GAMMA_280_2BF, 0x100, 0x0500},
+ {RADEON_OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
+ {RADEON_OV0_GAMMA_300_33F, 0x100, 0x0600},
+ {RADEON_OV0_GAMMA_340_37F, 0x100, 0x0600},
+ {RADEON_OV0_GAMMA_380_3BF, 0x100, 0x0700},
+ {RADEON_OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
+};
+
+/****************************************************************************
+ * SetTransform *
+ * Function: Calculates and sets color space transform from supplied *
+ * reference transform, gamma, brightness, contrast, hue and *
+ * saturation. *
+ * Inputs: bright - brightness *
+ * cont - contrast *
+ * sat - saturation *
+ * hue - hue *
+ * red_intensity - intensity of red component *
+ * green_intensity - intensity of green component *
+ * blue_intensity - intensity of blue component *
+ * ref - index to the table of refernce transforms *
+ * Outputs: NONE *
+ ****************************************************************************/
+
+static void RADEONSetTransform (ScrnInfoPtr pScrn,
+ float bright,
+ float cont,
+ float sat,
+ float hue,
+ float red_intensity,
+ float green_intensity,
+ float blue_intensity,
+ CARD32 ref)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ float OvHueSin, OvHueCos;
+ float CAdjLuma, CAdjOff;
+ float CAdjRCb, CAdjRCr;
+ float CAdjGCb, CAdjGCr;
+ float CAdjBCb, CAdjBCr;
+ float RedAdj,GreenAdj,BlueAdj;
+ float OvLuma, OvROff, OvGOff, OvBOff;
+ float OvRCb, OvRCr;
+ float OvGCb, OvGCr;
+ float OvBCb, OvBCr;
+ float Loff = 64.0;
+ float Coff = 512.0f;
+
+ CARD32 dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
+ CARD32 dwOvRCb, dwOvRCr;
+ CARD32 dwOvGCb, dwOvGCr;
+ CARD32 dwOvBCb, dwOvBCr;
+
+ if (ref >= 2)
+ return;
+
+ OvHueSin = sin(hue);
+ OvHueCos = cos(hue);
+
+ CAdjLuma = cont * trans[ref].RefLuma;
+ CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
+ RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
+ GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
+ BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
+
+ CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
+ CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
+ CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
+ CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
+ CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
+ CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
+
+#if 0 /* default constants */
+ CAdjLuma = 1.16455078125;
+
+ CAdjRCb = 0.0;
+ CAdjRCr = 1.59619140625;
+ CAdjGCb = -0.39111328125;
+ CAdjGCr = -0.8125;
+ CAdjBCb = 2.01708984375;
+ CAdjBCr = 0;
+#endif
+ OvLuma = CAdjLuma;
+ OvRCb = CAdjRCb;
+ OvRCr = CAdjRCr;
+ OvGCb = CAdjGCb;
+ OvGCr = CAdjGCr;
+ OvBCb = CAdjBCb;
+ OvBCr = CAdjBCr;
+ OvROff = RedAdj + CAdjOff -
+ OvLuma * Loff - (OvRCb + OvRCr) * Coff;
+ OvGOff = GreenAdj + CAdjOff -
+ OvLuma * Loff - (OvGCb + OvGCr) * Coff;
+ OvBOff = BlueAdj + CAdjOff -
+ OvLuma * Loff - (OvBCb + OvBCr) * Coff;
+#if 0 /* default constants */
+ OvROff = -888.5;
+ OvGOff = 545;
+ OvBOff = -1104;
+#endif
+
+ dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff;
+ dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff;
+ dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff;
+ /*
+ * Whatever docs say about R200 having 3.8 format instead of 3.11
+ * as in Radeon is a lie
+ * Or more precisely the location of bit fields is a lie
+ */
+ if(1 || info->ChipFamily < CHIP_FAMILY_R200)
+ {
+ dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17;
+ dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1;
+ dwOvRCr = (((INT32)(OvRCr * 2048.0))&0x7fff)<<17;
+ dwOvGCb = (((INT32)(OvGCb * 2048.0))&0x7fff)<<1;
+ dwOvGCr = (((INT32)(OvGCr * 2048.0))&0x7fff)<<17;
+ dwOvBCb = (((INT32)(OvBCb * 2048.0))&0x7fff)<<1;
+ dwOvBCr = (((INT32)(OvBCr * 2048.0))&0x7fff)<<17;
+ }
+ else
+ {
+ dwOvLuma = (((INT32)(OvLuma * 256.0))&0x7ff)<<20;
+ dwOvRCb = (((INT32)(OvRCb * 256.0))&0x7ff)<<4;
+ dwOvRCr = (((INT32)(OvRCr * 256.0))&0x7ff)<<20;
+ dwOvGCb = (((INT32)(OvGCb * 256.0))&0x7ff)<<4;
+ dwOvGCr = (((INT32)(OvGCr * 256.0))&0x7ff)<<20;
+ dwOvBCb = (((INT32)(OvBCb * 256.0))&0x7ff)<<4;
+ dwOvBCr = (((INT32)(OvBCr * 256.0))&0x7ff)<<20;
+ }
+ OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
+ OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
+ OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
+ OUTREG(RADEON_OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
+ OUTREG(RADEON_OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
+ OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
+}
+
+static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 colorKey)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 min, max;
+ CARD8 r, g, b;
+
+ if (info->CurrentLayout.depth > 8)
+ {
+ CARD32 rbits, gbits, bbits;
+
+ rbits = (colorKey & pScrn->mask.red) >> pScrn->offset.red;
+ gbits = (colorKey & pScrn->mask.green) >> pScrn->offset.green;
+ bbits = (colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
+
+ r = rbits << (8 - pScrn->weight.red);
+ g = gbits << (8 - pScrn->weight.green);
+ b = bbits << (8 - pScrn->weight.blue);
+ }
+ else
+ {
+ CARD32 bits;
+
+ bits = colorKey & ((1 << info->CurrentLayout.depth) - 1);
+ r = bits;
+ g = bits;
+ b = bits;
+ }
+ min = (r << 16) | (g << 8) | (b);
+ max = (0xff << 24) | (r << 16) | (g << 8) | (b);
+
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, max);
+ OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min);
+}
+
+static void
+RADEONResetVideo(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ RADEONWaitForIdleMMIO(pScrn);
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0x80000000);
+ OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0); /* maybe */
+ OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0);
+ OUTREG(RADEON_OV0_FILTER_CNTL, 0x0000000f);
+ OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ |
+ RADEON_VIDEO_KEY_FN_FALSE |
+ RADEON_CMP_MIX_OR);
+ OUTREG(RADEON_OV0_TEST, 0);
+ OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND);
+ OUTREG(RADEON_CAP0_TRIG_CNTL, 0);
+ RADEONSetColorKey(pScrn, pPriv->colorKey);
+
+ if (info->ChipFamily == CHIP_FAMILY_R200 ||
+ info->ChipFamily == CHIP_FAMILY_R300) {
+ int i;
+
+ OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000);
+ OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e);
+ OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a2f9da);
+ OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442);
+ OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046);
+ OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
+
+ /*
+ * Set default Gamma ramp:
+ *
+ * Of 18 segments for gamma curve, all segments in R200 (and
+ * newer) are programmable, while only lower 4 and upper 2
+ * segments are programmable in the older Radeons.
+ */
+ for (i = 0; i < 18; i++) {
+ OUTREG(def_gamma[i].gammaReg,
+ (def_gamma[i].gammaSlope<<16) | def_gamma[i].gammaOffset);
+ }
+ } else {
+ OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000);
+ OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e);
+ OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0);
+ OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442);
+ OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040);
+ OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
+ }
+}
+
+
+static XF86VideoAdaptorPtr
+RADEONAllocAdaptor(ScrnInfoPtr pScrn)
+{
+ XF86VideoAdaptorPtr adapt;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr pPriv;
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
+ return NULL;
+
+ if(!(pPriv = xcalloc(1, sizeof(RADEONPortPrivRec) + sizeof(DevUnion))))
+ {
+ xfree(adapt);
+ return NULL;
+ }
+
+ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
+ adapt->pPortPrivates[0].ptr = (pointer)pPriv;
+
+ pPriv->colorKey = info->videoKey;
+ pPriv->doubleBuffer = TRUE;
+ pPriv->videoStatus = 0;
+ pPriv->brightness = 0;
+ pPriv->transform_index = 0;
+ pPriv->saturation = 0;
+ pPriv->contrast = 0;
+ pPriv->red_intensity = 0;
+ pPriv->green_intensity = 0;
+ pPriv->blue_intensity = 0;
+ pPriv->hue = 0;
+ pPriv->currentBuffer = 0;
+ pPriv->autopaint_colorkey = TRUE;
+
+ /*
+ * Unlike older Mach64 chips, RADEON has only two ECP settings:
+ * 0 for PIXCLK < 175Mhz, and 1 (divide by 2)
+ * for higher clocks, sure makes life nicer
+ */
+ if(info->ModeReg.dot_clock_freq < 17500)
+ pPriv->ecp_div = 0;
+ else
+ pPriv->ecp_div = 1;
+
+#if 0
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div);
+#endif
+
+ OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) &
+ 0xfffffCff) | (pPriv->ecp_div << 8));
+
+ info->adaptor = adapt;
+
+ return adapt;
+}
+
+static XF86VideoAdaptorPtr
+RADEONSetupImageVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONPortPrivPtr pPriv;
+ XF86VideoAdaptorPtr adapt;
+
+ if(!(adapt = RADEONAllocAdaptor(pScrn)))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "ATI Radeon Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = &DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = RADEONStopVideo;
+ adapt->SetPortAttribute = RADEONSetPortAttribute;
+ adapt->GetPortAttribute = RADEONGetPortAttribute;
+ adapt->QueryBestSize = RADEONQueryBestSize;
+ adapt->PutImage = RADEONPutImage;
+ adapt->QueryImageAttributes = RADEONQueryImageAttributes;
+
+ pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr);
+ REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0);
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvSaturation = MAKE_ATOM("XV_SATURATION");
+ xvColor = MAKE_ATOM("XV_COLOR");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+ xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
+ xvHue = MAKE_ATOM("XV_HUE");
+ xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY");
+ xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY");
+ xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY");
+
+ xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
+ xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
+
+ RADEONResetVideo(pScrn);
+
+ return adapt;
+}
+
+/* I really should stick this in miregion */
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (pointer)REGION_RECTS(A);
+ dataB = (pointer)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* RADEONClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (xa, ya
+ inclusive, xb, yb exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+#define DummyScreen screenInfo.screens[0]
+
+static Bool
+RADEONClipVideo(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+ int diff;
+
+ hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+ *xa <<= 16; *xb <<= 16;
+ *ya <<= 16; *yb <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *xa += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *xb -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *ya += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *yb -= diff * vscale;
+ }
+
+ if(*xa < 0) {
+ diff = (- *xa + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *xa += diff * hscale;
+ }
+ delta = *xb - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *xb -= diff * hscale;
+ }
+ if(*xa >= *xb) return FALSE;
+
+ if(*ya < 0) {
+ diff = (- *ya + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *ya += diff * vscale;
+ }
+ delta = *yb - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *yb -= diff * vscale;
+ }
+ if(*ya >= *yb) return FALSE;
+
+ if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+ (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+ {
+ RegionRec clipReg;
+ REGION_INIT(DummyScreen, &clipReg, dst, 1);
+ REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+ REGION_UNINIT(DummyScreen, &clipReg);
+ }
+ return TRUE;
+}
+
+static void
+RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(cleanup) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0);
+ if (info->cursor_start)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ }
+ if(info->videoLinear) {
+ xf86FreeOffscreenLinear(info->videoLinear);
+ info->videoLinear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+}
+
+static int
+RADEONSetPortAttribute(ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+ Bool setTransform = FALSE;
+
+ info->accel->Sync(pScrn);
+
+#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFBrightness(a) (((a)*1.0)/2000.0)
+#define RTFIntensity(a) (((a)*1.0)/2000.0)
+#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFHue(a) (((a)*3.1416)/1000.0)
+#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
+
+ if(attribute == xvAutopaintColorkey)
+ {
+ pPriv->autopaint_colorkey = ClipValue (value, 0, 1);
+ }
+ else if(attribute == xvSetDefaults)
+ {
+ pPriv->autopaint_colorkey = TRUE;
+ pPriv->brightness = 0;
+ pPriv->saturation = 0;
+ pPriv->contrast = 0;
+ pPriv->hue = 0;
+ pPriv->red_intensity = 0;
+ pPriv->green_intensity = 0;
+ pPriv->blue_intensity = 0;
+ pPriv->doubleBuffer = FALSE;
+ setTransform = TRUE;
+ }
+ else if(attribute == xvBrightness)
+ {
+ pPriv->brightness = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if((attribute == xvSaturation) || (attribute == xvColor))
+ {
+ pPriv->saturation = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvContrast)
+ {
+ pPriv->contrast = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvHue)
+ {
+ pPriv->hue = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvRedIntensity)
+ {
+ pPriv->red_intensity = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvGreenIntensity)
+ {
+ pPriv->green_intensity = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvBlueIntensity)
+ {
+ pPriv->blue_intensity = ClipValue (value, -1000, 1000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvDoubleBuffer)
+ {
+ pPriv->doubleBuffer = ClipValue (value, 0, 1);
+ pPriv->doubleBuffer = value;
+ }
+ else if(attribute == xvColorKey)
+ {
+ pPriv->colorKey = value;
+ RADEONSetColorKey (pScrn, pPriv->colorKey);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ }
+ else
+ return BadMatch;
+
+ if (setTransform)
+ {
+ RADEONSetTransform(pScrn,
+ RTFBrightness(pPriv->brightness),
+ RTFContrast(pPriv->contrast),
+ RTFSaturation(pPriv->saturation),
+ RTFHue(pPriv->hue),
+ RTFIntensity(pPriv->red_intensity),
+ RTFIntensity(pPriv->green_intensity),
+ RTFIntensity(pPriv->blue_intensity),
+ pPriv->transform_index);
+ }
+
+ return Success;
+}
+
+static int
+RADEONGetPortAttribute(ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+
+ if (info->accelOn) info->accel->Sync(pScrn);
+
+ if(attribute == xvAutopaintColorkey)
+ *value = pPriv->autopaint_colorkey;
+ else if(attribute == xvBrightness)
+ *value = pPriv->brightness;
+ else if((attribute == xvSaturation) || (attribute == xvColor))
+ *value = pPriv->saturation;
+ else if(attribute == xvContrast)
+ *value = pPriv->contrast;
+ else if(attribute == xvHue)
+ *value = pPriv->hue;
+ else if(attribute == xvRedIntensity)
+ *value = pPriv->red_intensity;
+ else if(attribute == xvGreenIntensity)
+ *value = pPriv->green_intensity;
+ else if(attribute == xvBlueIntensity)
+ *value = pPriv->blue_intensity;
+ else if(attribute == xvDoubleBuffer)
+ *value = pPriv->doubleBuffer ? 1 : 0;
+ else if(attribute == xvColorKey)
+ *value = pPriv->colorKey;
+ else
+ return BadMatch;
+
+ return Success;
+}
+
+static void
+RADEONQueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > (drw_w << 4))
+ drw_w = vid_w >> 4;
+ if(vid_h > (drw_h << 4))
+ drw_h = vid_h >> 4;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+static void
+RADEONCopyData(
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int h,
+ int w
+){
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+RADEONCopyMungedData(
+ unsigned char *src1,
+ unsigned char *src2,
+ unsigned char *src3,
+ unsigned char *dst1,
+ int srcPitch,
+ int srcPitch2,
+ int dstPitch,
+ int h,
+ int w
+){
+ CARD32 *dst;
+ CARD8 *s1, *s2, *s3;
+ int i, j;
+
+ w >>= 1;
+
+ for(j = 0; j < h; j++) {
+ dst = (pointer)dst1;
+ s1 = src1; s2 = src2; s3 = src3;
+ i = w;
+ while(i > 4) {
+ dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
+ dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
+ dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
+ dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
+ dst += 4; s2 += 4; s3 += 4; s1 += 8;
+ i -= 4;
+ }
+ while(i--) {
+ dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
+ dst++; s2++; s3++;
+ s1 += 2;
+ }
+
+ dst1 += dstPitch;
+ src1 += srcPitch;
+ if(j & 1) {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
+}
+
+
+static FBLinearPtr
+RADEONAllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBLinearPtr linear,
+ int size
+){
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+
+ xf86FreeOffscreenLinear(linear);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ NULL, NULL, NULL);
+
+ if(!new_linear) {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
+ PRIORITY_EXTREME);
+
+ if(max_size < size)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ NULL, NULL, NULL);
+ }
+
+ return new_linear;
+}
+
+static void
+RADEONDisplayVideo(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset1, int offset2,
+ short width, short height,
+ int pitch,
+ int left, int right, int top,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ int v_inc, h_inc, step_by, tmp;
+ int p1_h_accum_init, p23_h_accum_init;
+ int p1_v_accum_init;
+ int ecp_div;
+ int v_inc_shift;
+ int y_mult;
+ int x_off;
+ CARD32 scaler_src;
+
+ /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < 175Mhz, and 1 (divide by 2)
+ for higher clocks, sure makes life nicer
+
+ Here we need to find ecp_div again, as the user may have switched resolutions */
+ if(info->ModeReg.dot_clock_freq < 17500)
+ ecp_div = 0;
+ else
+ ecp_div = 1;
+
+ OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8));
+
+ v_inc_shift = 20;
+ if (pScrn->currentMode->Flags & V_INTERLACE)
+ v_inc_shift++;
+ if (pScrn->currentMode->Flags & V_DBLSCAN)
+ v_inc_shift--;
+ v_inc = (src_h << v_inc_shift) / drw_h;
+ h_inc = ((src_w << (12 + ecp_div)) / drw_w);
+ step_by = 1;
+
+ while(h_inc >= (2 << 12)) {
+ step_by++;
+ h_inc >>= 1;
+ }
+
+ /* keep everything in 16.16 */
+
+ offset1 += ((left >> 16) & ~7) << 1;
+ offset2 += ((left >> 16) & ~7) << 1;
+
+ if (info->IsSecondary) {
+ offset1 += info->FbMapSize;
+ offset2 += info->FbMapSize;
+ }
+
+ tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
+ p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0xf0000000);
+
+ tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
+ p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
+ ((tmp << 12) & 0x70000000);
+
+ tmp = (top & 0x0000ffff) + 0x00018000;
+ p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
+
+ left = (left >> 16) & 7;
+
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_OV0_REG_LOAD_CNTL, 1);
+ if (info->accelOn) info->accel->Sync(pScrn);
+ while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3)));
+
+ RADEONWaitForFifo(pScrn, 14);
+ OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
+ OUTREG(RADEON_OV0_STEP_BY, step_by | (step_by << 8));
+
+ y_mult = 1;
+ if (pScrn->currentMode->Flags & V_DBLSCAN)
+ y_mult = 2;
+ x_off = 8;
+ if (info->ChipFamily == CHIP_FAMILY_R200 ||
+ info->ChipFamily == CHIP_FAMILY_R300)
+ x_off = 0;
+
+ /* Put the hardware overlay on CRTC2:
+ *
+ * Since one hardware overlay can not be displayed on two heads
+ * at the same time, we might need to consider using software
+ * rendering for the second head.
+ */
+ if ((info->Clone && info->OverlayOnCRTC2) || info->IsSecondary) {
+ x_off = 0;
+ OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1
+ + x_off
+ - info->CloneFrameX0
+ + pScrn->frameX0) |
+ ((dstBox->y1*y_mult -
+ info->CloneFrameY0
+ + pScrn->frameY0) << 16)));
+ OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2
+ + x_off
+ - info->CloneFrameX0
+ + pScrn->frameX0) |
+ ((dstBox->y2*y_mult
+ - info->CloneFrameY0
+ + pScrn->frameY0) << 16)));
+ scaler_src = (1 << 14);
+ } else {
+ OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) |
+ ((dstBox->y1*y_mult) << 16)));
+ OUTREG(RADEON_OV0_Y_X_END, ((dstBox->x2 + x_off) |
+ ((dstBox->y2*y_mult) << 16)));
+ scaler_src = 0;
+ }
+
+ OUTREG(RADEON_OV0_V_INC, v_inc);
+ OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
+ OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch);
+ OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, pitch);
+ OUTREG(RADEON_OV0_P1_X_START_END, (src_w + left - 1) | (left << 16));
+ left >>= 1; src_w >>= 1;
+ OUTREG(RADEON_OV0_P2_X_START_END, (src_w + left - 1) | (left << 16));
+ OUTREG(RADEON_OV0_P3_X_START_END, (src_w + left - 1) | (left << 16));
+ OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0);
+ OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2 & 0xfffffff0);
+ OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset1 & 0xfffffff0);
+
+ RADEONWaitForFifo(pScrn, 9);
+ OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset2 & 0xfffffff0);
+ OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset1 & 0xfffffff0);
+ OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset2 & 0xfffffff0);
+ OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
+ OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
+ OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
+
+#if 0
+ if(id == FOURCC_UYVY)
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008C03);
+ else
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008B03);
+#endif
+
+ if (id == FOURCC_UYVY)
+ OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_YVYU422
+ | RADEON_SCALER_ADAPTIVE_DEINT
+ | RADEON_SCALER_SMART_SWITCH
+ | RADEON_SCALER_DOUBLE_BUFFER
+ | RADEON_SCALER_ENABLE
+ | scaler_src));
+ else
+ OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_VYUY422
+ | RADEON_SCALER_ADAPTIVE_DEINT
+ | RADEON_SCALER_SMART_SWITCH
+ | RADEON_SCALER_DOUBLE_BUFFER
+ | RADEON_SCALER_ENABLE
+ | scaler_src));
+
+ OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0);
+}
+
+
+static int
+RADEONPutImage(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool Sync,
+ RegionPtr clipBoxes, pointer data
+){
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+ INT32 xa, xb, ya, yb;
+ unsigned char *dst_start;
+ int pitch, new_size, offset, s2offset, s3offset;
+ int srcPitch, srcPitch2, dstPitch;
+ int top, left, npixels, nlines, bpp;
+ BoxRec dstBox;
+ CARD32 tmp;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 surface_cntl = INREG(RADEON_SURFACE_CNTL);
+
+ OUTREG(RADEON_SURFACE_CNTL, (surface_cntl |
+ RADEON_NONSURF_AP0_SWP_32BPP) & ~RADEON_NONSURF_AP0_SWP_16BPP);
+#endif
+
+ /*
+ * s2offset, s3offset - byte offsets into U and V plane of the
+ * source where copying starts. Y plane is
+ * done by editing "buf".
+ *
+ * offset - byte offset to the first line of the destination.
+ *
+ * dst_start - byte address to the first displayed pel.
+ *
+ */
+
+ /* make the compiler happy */
+ s2offset = s3offset = srcPitch2 = 0;
+
+ if(src_w > (drw_w << 4))
+ drw_w = src_w >> 4;
+ if(src_h > (drw_h << 4))
+ drw_h = src_h >> 4;
+
+ /* Clip */
+ xa = src_x;
+ xb = src_x + src_w;
+ ya = src_y;
+ yb = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!RADEONClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ bpp = pScrn->bitsPerPixel >> 3;
+ pitch = bpp * pScrn->displayWidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ dstPitch = ((width << 1) + 15) & ~15;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width + 3) & ~3;
+ s2offset = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ dstPitch = ((width << 1) + 15) & ~15;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width << 1);
+ break;
+ }
+
+ if(!(info->videoLinear = RADEONAllocateMemory(pScrn, info->videoLinear,
+ pPriv->doubleBuffer ? (new_size << 1) : new_size)))
+ {
+ return BadAlloc;
+ }
+
+ pPriv->currentBuffer ^= 1;
+
+ /* copy data */
+ top = ya >> 16;
+ left = (xa >> 16) & ~1;
+ npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
+
+ offset = (info->videoLinear->offset * bpp) + (top * dstPitch);
+ if(pPriv->doubleBuffer)
+ offset += pPriv->currentBuffer * new_size * bpp;
+
+ dst_start = info->FB + offset;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ dst_start += left << 1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ s2offset += tmp;
+ s3offset += tmp;
+ if(id == FOURCC_I420) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+ nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | RADEON_NONSURF_AP0_SWP_32BPP)
+ & ~RADEON_NONSURF_AP0_SWP_16BPP);
+#endif
+ RADEONCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
+ buf + s3offset, dst_start, srcPitch, srcPitch2,
+ dstPitch, nlines, npixels);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ left <<= 1;
+ buf += (top * srcPitch) + left;
+ nlines = ((yb + 0xffff) >> 16) - top;
+ dst_start += left;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ OUTREG(RADEON_SURFACE_CNTL, surface_cntl & ~(RADEON_NONSURF_AP0_SWP_32BPP
+ | RADEON_NONSURF_AP0_SWP_16BPP));
+#endif
+ RADEONCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* restore byte swapping */
+ OUTREG(RADEON_SURFACE_CNTL, surface_cntl);
+#endif
+
+ /* update cliplist */
+ if(!RegionsEqual(&pPriv->clip, clipBoxes))
+ {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ if(pPriv->autopaint_colorkey)
+ (*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy,
+ (CARD32)~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+ if (info->cursor_start && !(pPriv->videoStatus & CLIENT_VIDEO_ON))
+ xf86ForceHWCursor (pScrn->pScreen, TRUE);
+
+ RADEONDisplayVideo(pScrn, id, offset, offset, width, height, dstPitch,
+ xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ info->VideoTimerCallback = RADEONVideoTimerCallback;
+
+ return Success;
+}
+
+
+static int
+RADEONQueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > 2048) *w = 2048;
+ if(*h > 2048) *h = 2048;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static void
+RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < now) {
+ unsigned char *RADEONMMIO = info->MMIO;
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0);
+ if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = now + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if(pPriv->freeTime < now) {
+ if(info->videoLinear) {
+ xf86FreeOffscreenLinear(info->videoLinear);
+ info->videoLinear = NULL;
+ }
+ if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ pPriv->videoStatus = 0;
+ info->VideoTimerCallback = NULL;
+ }
+ }
+ } else /* shouldn't get here */
+ info->VideoTimerCallback = NULL;
+}
+
+/****************** Offscreen stuff ***************/
+typedef struct {
+ FBLinearPtr linear;
+ Bool isOn;
+} OffscreenPrivRec, * OffscreenPrivPtr;
+
+static int
+RADEONAllocateSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h,
+ XF86SurfacePtr surface
+){
+ FBLinearPtr linear;
+ int pitch, fbpitch, size, bpp;
+ OffscreenPrivPtr pPriv;
+ if((w > 1024) || (h > 1024))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ bpp = pScrn->bitsPerPixel >> 3;
+ fbpitch = bpp * pScrn->displayWidth;
+ size = ((pitch * h) + bpp - 1) / bpp;
+
+ if(!(linear = RADEONAllocateMemory(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if(!(surface->pitches = xalloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+
+ pPriv->linear = linear;
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = linear->offset * bpp;
+ surface->devPrivate.ptr = (pointer)pPriv;
+
+ return Success;
+}
+
+static int
+RADEONStopSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+ RADEONInfoPtr info = RADEONPTR(surface->pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if(pPriv->isOn) {
+ OUTREG(RADEON_OV0_SCALE_CNTL, 0);
+ pPriv->isOn = FALSE;
+ }
+ return Success;
+}
+
+
+static int
+RADEONFreeSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn)
+ RADEONStopSurface(surface);
+ xf86FreeOffscreenLinear(pPriv->linear);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+RADEONGetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value
+){
+ return RADEONGetPortAttribute(pScrn, attribute, value,
+ (pointer)(GET_PORT_PRIVATE(pScrn)));
+}
+
+static int
+RADEONSetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value
+){
+ return RADEONSetPortAttribute(pScrn, attribute, value,
+ (pointer)(GET_PORT_PRIVATE(pScrn)));
+}
+
+
+static int
+RADEONDisplaySurface(
+ XF86SurfacePtr surface,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ RegionPtr clipBoxes
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+ ScrnInfoPtr pScrn = surface->pScrn;
+
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr;
+
+ INT32 xa, ya, xb, yb;
+ BoxRec dstBox;
+
+ if (src_w > (drw_w << 4))
+ drw_w = src_w >> 4;
+ if (src_h > (drw_h << 4))
+ drw_h = src_h >> 4;
+
+ xa = src_x;
+ xb = src_x + src_w;
+ ya = src_y;
+ yb = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if (!RADEONClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
+ surface->width, surface->height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ RADEONResetVideo(pScrn);
+
+ RADEONDisplayVideo(pScrn, surface->id,
+ surface->offsets[0], surface->offsets[0],
+ surface->width, surface->height, surface->pitches[0],
+ xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ if (portPriv->autopaint_colorkey)
+ (*info->accel->FillSolidRects)(pScrn, portPriv->colorKey, GXcopy,
+ (CARD32)~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
+ UpdateCurrentTime();
+ if (info->cursor_start)
+ xf86ForceHWCursor (pScrn->pScreen, FALSE);
+ portPriv->videoStatus = FREE_TIMER;
+ portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ info->VideoTimerCallback = RADEONVideoTimerCallback;
+ }
+
+ return Success;
+}
+
+
+static void
+RADEONInitOffscreenImages(ScreenPtr pScreen)
+{
+/* ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn); */
+ XF86OffscreenImagePtr offscreenImages;
+ /* need to free this someplace */
+
+ if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
+ return;
+
+ offscreenImages[0].image = &Images[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
+ VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = RADEONAllocateSurface;
+ offscreenImages[0].free_surface = RADEONFreeSurface;
+ offscreenImages[0].display = RADEONDisplaySurface;
+ offscreenImages[0].stop = RADEONStopSurface;
+ offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute;
+ offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute;
+ offscreenImages[0].max_width = 1024;
+ offscreenImages[0].max_height = 1024;
+ offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
+ offscreenImages[0].attributes = Attributes;
+
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
+
+#endif /* !XvExtension */