summaryrefslogtreecommitdiff
path: root/src/atimach64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atimach64.c')
-rw-r--r--src/atimach64.c2164
1 files changed, 2164 insertions, 0 deletions
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;
+}