132b578d3Smrg/*
232b578d3Smrg * Copyright 1999 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
332b578d3Smrg *
432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that
632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright
732b578d3Smrg * notice and this permission notice appear in supporting documentation, and
832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or
932b578d3Smrg * publicity pertaining to distribution of the software without specific,
1032b578d3Smrg * written prior permission.  Marc Aurele La France makes no representations
1132b578d3Smrg * about the suitability of this software for any purpose.  It is provided
1232b578d3Smrg * "as-is" without express or implied warranty.
1332b578d3Smrg *
1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE.
2132b578d3Smrg */
2232b578d3Smrg
2332b578d3Smrg#ifdef HAVE_CONFIG_H
2432b578d3Smrg#include "config.h"
2532b578d3Smrg#endif
2632b578d3Smrg
2732b578d3Smrg#include "ati.h"
2832b578d3Smrg#include "atichip.h"
2932b578d3Smrg#include "atilock.h"
3032b578d3Smrg#include "atimach64io.h"
3132b578d3Smrg#include "atiwonderio.h"
3232b578d3Smrg
3332b578d3Smrg/*
3432b578d3Smrg * ATIUnlock --
3532b578d3Smrg *
3632b578d3Smrg * This function is entered to unlock registers and disable unwanted
3732b578d3Smrg * emulations.  It saves the current state for later restoration by ATILock().
3832b578d3Smrg */
3932b578d3Smrgvoid
4032b578d3SmrgATIUnlock
4132b578d3Smrg(
4232b578d3Smrg    ATIPtr pATI
4332b578d3Smrg)
4432b578d3Smrg{
4532b578d3Smrg    CARD32 tmp;
4632b578d3Smrg
4732b578d3Smrg#ifndef AVOID_CPIO
4832b578d3Smrg
4932b578d3Smrg    CARD32 saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
5032b578d3Smrg
5132b578d3Smrg#endif /* AVOID_CPIO */
5232b578d3Smrg
5332b578d3Smrg    if (pATI->Unlocked)
5432b578d3Smrg        return;
5532b578d3Smrg    pATI->Unlocked = TRUE;
5632b578d3Smrg
5732b578d3Smrg    {
5832b578d3Smrg        /* Reset everything */
5932b578d3Smrg        pATI->LockData.bus_cntl = inr(BUS_CNTL);
6032b578d3Smrg        if (pATI->Chip < ATI_CHIP_264VT4)
6132b578d3Smrg        {
6232b578d3Smrg            pATI->LockData.bus_cntl =
6332b578d3Smrg                (pATI->LockData.bus_cntl & ~BUS_HOST_ERR_INT_EN) |
6432b578d3Smrg                BUS_HOST_ERR_INT;
6532b578d3Smrg            if (pATI->Chip < ATI_CHIP_264VTB)
6632b578d3Smrg                pATI->LockData.bus_cntl =
6732b578d3Smrg                    (pATI->LockData.bus_cntl & ~BUS_FIFO_ERR_INT_EN) |
6832b578d3Smrg                        BUS_FIFO_ERR_INT;
6932b578d3Smrg        }
7032b578d3Smrg        tmp = pATI->LockData.bus_cntl & ~BUS_ROM_DIS;
7132b578d3Smrg        if (pATI->Chip < ATI_CHIP_264VTB)
7232b578d3Smrg            tmp |= SetBits(15, BUS_FIFO_WS);
7332b578d3Smrg        else
7432b578d3Smrg            tmp &= ~BUS_MASTER_DIS;
7532b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264VT)
7632b578d3Smrg            tmp |= BUS_EXT_REG_EN;              /* Enable Block 1 */
7732b578d3Smrg        outr(BUS_CNTL, tmp);
7832b578d3Smrg        pATI->LockData.crtc_int_cntl = inr(CRTC_INT_CNTL);
7932b578d3Smrg        outr(CRTC_INT_CNTL, (pATI->LockData.crtc_int_cntl & ~CRTC_INT_ENS) |
8032b578d3Smrg            CRTC_INT_ACKS);
8132b578d3Smrg
8232b578d3Smrg#ifdef XF86DRI_DEVEL
8332b578d3Smrg
8432b578d3Smrg	if (pATI->irq > 0)
8532b578d3Smrg	    outr(CRTC_INT_CNTL, (inr(CRTC_INT_CNTL) & ~CRTC_INT_ACKS) |
8632b578d3Smrg		 CRTC_VBLANK_INT_EN); /* Enable VBLANK interrupt - handled by DRM */
8732b578d3Smrg
8832b578d3Smrg#endif /* XF86DRI_DEVEL */
8932b578d3Smrg
9032b578d3Smrg        pATI->LockData.gen_test_cntl = inr(GEN_TEST_CNTL) &
9132b578d3Smrg            (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN |
9232b578d3Smrg                GEN_BLOCK_WR_EN);
9332b578d3Smrg        tmp = pATI->LockData.gen_test_cntl & ~GEN_CUR_EN;
9432b578d3Smrg        outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
9532b578d3Smrg        outr(GEN_TEST_CNTL, tmp);
9632b578d3Smrg        outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
9732b578d3Smrg        tmp = pATI->LockData.crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
9832b578d3Smrg            ~(CRTC_EN | CRTC_LOCK_REGS);
9932b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264XL)
10032b578d3Smrg            tmp = (tmp & ~CRTC_INT_ENS_X) | CRTC_INT_ACKS_X;
10132b578d3Smrg        outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
10232b578d3Smrg        outr(CRTC_GEN_CNTL, tmp);
10332b578d3Smrg        outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
10432b578d3Smrg        if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
10532b578d3Smrg        {
10632b578d3Smrg            pATI->LockData.lcd_index = inr(LCD_INDEX);
10732b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264XL)
10832b578d3Smrg                outr(LCD_INDEX, pATI->LockData.lcd_index &
10932b578d3Smrg                    ~(LCD_MONDET_INT_EN | LCD_MONDET_INT));
11032b578d3Smrg
11132b578d3Smrg            /*
11232b578d3Smrg             * Prevent BIOS initiated display switches on dual-CRT controllers.
11332b578d3Smrg             */
11432b578d3Smrg            if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
11532b578d3Smrg            {
11632b578d3Smrg#ifdef TV_OUT
11732b578d3Smrg		pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3) & ~DISPLAY_SWITCH_DISABLE;
11832b578d3Smrg		outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
11932b578d3Smrg#else
12032b578d3Smrg		pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3);
12132b578d3Smrg		outr(SCRATCH_REG3,
12232b578d3Smrg		     pATI->LockData.scratch_reg3 | DISPLAY_SWITCH_DISABLE);
12332b578d3Smrg#endif /* TV_OUT */
12432b578d3Smrg            }
12532b578d3Smrg        }
12632b578d3Smrg
12732b578d3Smrg        pATI->LockData.mem_cntl = inr(MEM_CNTL);
12832b578d3Smrg        if (pATI->Chip < ATI_CHIP_264CT)
12932b578d3Smrg            outr(MEM_CNTL, pATI->LockData.mem_cntl &
13032b578d3Smrg                ~(CTL_MEM_BNDRY | CTL_MEM_BNDRY_EN));
13132b578d3Smrg
13232b578d3Smrg        /* Disable feature connector on integrated controllers */
13332b578d3Smrg        tmp = pATI->LockData.dac_cntl = inr(DAC_CNTL);
13432b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264CT)
13532b578d3Smrg            tmp &= ~DAC_FEA_CON_EN;
13632b578d3Smrg
13732b578d3Smrg#ifndef AVOID_CPIO
13832b578d3Smrg
13932b578d3Smrg        /* Ensure VGA aperture is enabled */
14032b578d3Smrg        pATI->LockData.config_cntl = inr(CONFIG_CNTL);
14132b578d3Smrg        tmp |= DAC_VGA_ADR_EN;
14232b578d3Smrg        outr(CONFIG_CNTL, pATI->LockData.config_cntl & ~CFG_VGA_DIS);
14332b578d3Smrg
14432b578d3Smrg#endif /* AVOID_CPIO */
14532b578d3Smrg
14632b578d3Smrg        outr(DAC_CNTL, tmp);
14732b578d3Smrg
14832b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264VTB)
14932b578d3Smrg        {
15032b578d3Smrg            pATI->LockData.mpp_config = inr(MPP_CONFIG);
15132b578d3Smrg            pATI->LockData.mpp_strobe_seq = inr(MPP_STROBE_SEQ);
15232b578d3Smrg            pATI->LockData.tvo_cntl = inr(TVO_CNTL);
15332b578d3Smrg
15432b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264GT2C)
15532b578d3Smrg            {
15632b578d3Smrg                pATI->LockData.hw_debug = inr(HW_DEBUG);
15732b578d3Smrg
15832b578d3Smrg                if (pATI->Chip >= ATI_CHIP_264GTPRO)
15932b578d3Smrg                {
16032b578d3Smrg                    if (!(pATI->LockData.hw_debug & CMDFIFO_SIZE_EN))
16132b578d3Smrg                        outr(HW_DEBUG,
16232b578d3Smrg                            pATI->LockData.hw_debug | CMDFIFO_SIZE_EN);
16332b578d3Smrg
16432b578d3Smrg                    pATI->LockData.i2c_cntl_0 =
16532b578d3Smrg                        inr(I2C_CNTL_0) | (I2C_CNTL_STAT | I2C_CNTL_HPTR_RST);
16632b578d3Smrg                    outr(I2C_CNTL_0,
16732b578d3Smrg                        pATI->LockData.i2c_cntl_0 & ~I2C_CNTL_INT_EN);
16832b578d3Smrg                    pATI->LockData.i2c_cntl_1 = inr(I2C_CNTL_1);
16932b578d3Smrg                }
17032b578d3Smrg                else
17132b578d3Smrg                {
17232b578d3Smrg                    if (pATI->LockData.hw_debug & CMDFIFO_SIZE_DIS)
17332b578d3Smrg                        outr(HW_DEBUG,
17432b578d3Smrg                            pATI->LockData.hw_debug & ~CMDFIFO_SIZE_DIS);
17532b578d3Smrg                }
17632b578d3Smrg            }
17732b578d3Smrg        }
17832b578d3Smrg    }
17932b578d3Smrg
18032b578d3Smrg#ifndef AVOID_CPIO
18132b578d3Smrg
18232b578d3Smrg    if (pATI->VGAAdapter)
18332b578d3Smrg    {
18432b578d3Smrg        if (pATI->CPIO_VGAWonder)
18532b578d3Smrg        {
18632b578d3Smrg            /*
18732b578d3Smrg             * Ensure all registers are read/write and disable all non-VGA
18832b578d3Smrg             * emulations.
18932b578d3Smrg             */
19032b578d3Smrg            pATI->LockData.b1 = ATIGetExtReg(0xB1U);
19132b578d3Smrg            ATIModifyExtReg(pATI, 0xB1U, pATI->LockData.b1, 0xFCU, 0x00U);
19232b578d3Smrg            pATI->LockData.b4 = ATIGetExtReg(0xB4U);
19332b578d3Smrg            ATIModifyExtReg(pATI, 0xB4U, pATI->LockData.b4, 0x00U, 0x00U);
19432b578d3Smrg            pATI->LockData.b5 = ATIGetExtReg(0xB5U);
19532b578d3Smrg            ATIModifyExtReg(pATI, 0xB5U, pATI->LockData.b5, 0xBFU, 0x00U);
19632b578d3Smrg            pATI->LockData.b6 = ATIGetExtReg(0xB6U);
19732b578d3Smrg            ATIModifyExtReg(pATI, 0xB6U, pATI->LockData.b6, 0xDDU, 0x00U);
19832b578d3Smrg            pATI->LockData.b8 = ATIGetExtReg(0xB8U);
19932b578d3Smrg            ATIModifyExtReg(pATI, 0xB8U, pATI->LockData.b8, 0xC0U, 0x00U);
20032b578d3Smrg            pATI->LockData.b9 = ATIGetExtReg(0xB9U);
20132b578d3Smrg            ATIModifyExtReg(pATI, 0xB9U, pATI->LockData.b9, 0x7FU, 0x00U);
20232b578d3Smrg            {
20332b578d3Smrg                pATI->LockData.be = ATIGetExtReg(0xBEU);
20432b578d3Smrg                ATIModifyExtReg(pATI, 0xBEU, pATI->LockData.be, 0xFAU, 0x01U);
20532b578d3Smrg                {
20632b578d3Smrg                    pATI->LockData.a6 = ATIGetExtReg(0xA6U);
20732b578d3Smrg                    ATIModifyExtReg(pATI, 0xA6U, pATI->LockData.a6,
20832b578d3Smrg                        0x7FU, 0x00U);
20932b578d3Smrg                    pATI->LockData.ab = ATIGetExtReg(0xABU);
21032b578d3Smrg                    ATIModifyExtReg(pATI, 0xABU, pATI->LockData.ab,
21132b578d3Smrg                        0xE7U, 0x00U);
21232b578d3Smrg                }
21332b578d3Smrg            }
21432b578d3Smrg        }
21532b578d3Smrg
21632b578d3Smrg        if (pATI->LCDPanelID >= 0)
21732b578d3Smrg        {
21832b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
21932b578d3Smrg            {
22032b578d3Smrg                saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
22132b578d3Smrg
22232b578d3Smrg                /* Setup to unlock non-shadow registers */
22332b578d3Smrg                lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN;
22432b578d3Smrg                outr(LCD_GEN_CTRL, lcd_gen_ctrl);
22532b578d3Smrg            }
22632b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
22732b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
22832b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
22932b578d3Smrg            {
23032b578d3Smrg                saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
23132b578d3Smrg
23232b578d3Smrg                /* Setup to unlock non-shadow registers */
23332b578d3Smrg                lcd_gen_ctrl = saved_lcd_gen_ctrl &
23432b578d3Smrg                    ~(CRTC_RW_SELECT | SHADOW_RW_EN);
23532b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
23632b578d3Smrg            }
23732b578d3Smrg        }
23832b578d3Smrg
23932b578d3Smrg        ATISetVGAIOBase(pATI, inb(R_GENMO));
24032b578d3Smrg
24132b578d3Smrg        /*
24232b578d3Smrg         * There's a bizarre interaction here.  If bit 0x80 of CRTC[17] is on,
24332b578d3Smrg         * then CRTC[3] is read-only.  If bit 0x80 of CRTC[3] is off, then
24432b578d3Smrg         * CRTC[17] is write-only (or a read attempt actually returns bits from
24532b578d3Smrg         * C/EGA's light pen position).  This means that if both conditions are
24632b578d3Smrg         * met, CRTC[17]'s value on server entry cannot be retrieved.
24732b578d3Smrg         */
24832b578d3Smrg
24932b578d3Smrg        pATI->LockData.crt03 = tmp = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
25032b578d3Smrg        if ((tmp & 0x80U) ||
25132b578d3Smrg            ((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
25232b578d3Smrg                tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
25332b578d3Smrg        {
25432b578d3Smrg            /* CRTC[16-17] should be readable */
25532b578d3Smrg            pATI->LockData.crt11 = tmp =
25632b578d3Smrg                GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
25732b578d3Smrg            if (tmp & 0x80U)            /* Unprotect CRTC[0-7] */
25832b578d3Smrg                outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
25932b578d3Smrg        }
26032b578d3Smrg        else
26132b578d3Smrg        {
26232b578d3Smrg            /*
26332b578d3Smrg             * Could not make CRTC[17] readable, so unprotect CRTC[0-7]
26432b578d3Smrg             * replacing VSyncEnd with zero.  This zero will be replaced after
26532b578d3Smrg             * acquiring the needed access.
26632b578d3Smrg             */
26732b578d3Smrg            unsigned int VSyncEnd, VBlankStart, VBlankEnd;
26832b578d3Smrg            CARD8 crt07, crt09;
26932b578d3Smrg
27032b578d3Smrg            PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
27132b578d3Smrg            /* Make CRTC[16-17] readable */
27232b578d3Smrg            PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
27332b578d3Smrg            /* Make vertical synch pulse as wide as possible */
27432b578d3Smrg            crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
27532b578d3Smrg            crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
27632b578d3Smrg            VBlankStart = (((crt09 & 0x20U) << 4) | ((crt07 & 0x08U) << 5) |
27732b578d3Smrg                GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
27832b578d3Smrg            VBlankEnd = (VBlankStart & 0x0300U) |
27932b578d3Smrg                GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
28032b578d3Smrg            if (VBlankEnd <= VBlankStart)
28132b578d3Smrg                VBlankEnd += 0x0100U;
28232b578d3Smrg            VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
28332b578d3Smrg                GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
28432b578d3Smrg            if (VSyncEnd >= VBlankEnd)
28532b578d3Smrg                VSyncEnd = VBlankEnd - 1;
28632b578d3Smrg            pATI->LockData.crt11 = (VSyncEnd & 0x0FU) | 0x20U;
28732b578d3Smrg            PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
28832b578d3Smrg            pATI->LockData.crt11 |= 0x80U;
28932b578d3Smrg        }
29032b578d3Smrg
29132b578d3Smrg        if (pATI->LCDPanelID >= 0)
29232b578d3Smrg        {
29332b578d3Smrg            /* Setup to unlock shadow registers */
29432b578d3Smrg            lcd_gen_ctrl |= SHADOW_RW_EN;
29532b578d3Smrg
29632b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
29732b578d3Smrg                outr(LCD_GEN_CTRL, lcd_gen_ctrl);
29832b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
29932b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
30032b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
30132b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
30232b578d3Smrg
30332b578d3Smrg            /* Unlock shadow registers */
30432b578d3Smrg            ATISetVGAIOBase(pATI, inb(R_GENMO));
30532b578d3Smrg
30632b578d3Smrg            pATI->LockData.shadow_crt03 = tmp =
30732b578d3Smrg                GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
30832b578d3Smrg            if ((tmp & 0x80U) ||
30932b578d3Smrg                ((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
31032b578d3Smrg                    tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
31132b578d3Smrg            {
31232b578d3Smrg                /* CRTC[16-17] should be readable */
31332b578d3Smrg                pATI->LockData.shadow_crt11 = tmp =
31432b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
31532b578d3Smrg                if (tmp & 0x80U)            /* Unprotect CRTC[0-7] */
31632b578d3Smrg                {
31732b578d3Smrg                    outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
31832b578d3Smrg                }
31932b578d3Smrg                else if (!tmp && pATI->LockData.crt11)
32032b578d3Smrg                {
32132b578d3Smrg                    pATI->LockData.shadow_crt11 = tmp = pATI->LockData.crt11;
32232b578d3Smrg                    outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
32332b578d3Smrg                }
32432b578d3Smrg            }
32532b578d3Smrg            else
32632b578d3Smrg            {
32732b578d3Smrg                /*
32832b578d3Smrg                 * Could not make CRTC[17] readable, so unprotect CRTC[0-7]
32932b578d3Smrg                 * replacing VSyncEnd with zero.  This zero will be replaced
33032b578d3Smrg                 * after acquiring the needed access.
33132b578d3Smrg                 */
33232b578d3Smrg                unsigned int VSyncEnd, VBlankStart, VBlankEnd;
33332b578d3Smrg                CARD8 crt07, crt09;
33432b578d3Smrg
33532b578d3Smrg                PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
33632b578d3Smrg                /* Make CRTC[16-17] readable */
33732b578d3Smrg                PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
33832b578d3Smrg                /* Make vertical synch pulse as wide as possible */
33932b578d3Smrg                crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
34032b578d3Smrg                crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
34132b578d3Smrg                VBlankStart = (((crt09 & 0x20U) << 4) |
34232b578d3Smrg                    ((crt07 & 0x08U) << 5) |
34332b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
34432b578d3Smrg                VBlankEnd = (VBlankStart & 0x0300U) |
34532b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
34632b578d3Smrg                if (VBlankEnd <= VBlankStart)
34732b578d3Smrg                    VBlankEnd += 0x0100U;
34832b578d3Smrg                VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
34932b578d3Smrg                    GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
35032b578d3Smrg                if (VSyncEnd >= VBlankEnd)
35132b578d3Smrg                    VSyncEnd = VBlankEnd - 1;
35232b578d3Smrg                pATI->LockData.shadow_crt11 = (VSyncEnd & 0x0FU) | 0x20U;
35332b578d3Smrg                PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
35432b578d3Smrg                    pATI->LockData.shadow_crt11);
35532b578d3Smrg                pATI->LockData.shadow_crt11 |= 0x80U;
35632b578d3Smrg            }
35732b578d3Smrg
35832b578d3Smrg            /* Restore selection */
35932b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
36032b578d3Smrg            {
36132b578d3Smrg                outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
36232b578d3Smrg            }
36332b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
36432b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
36532b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
36632b578d3Smrg            {
36732b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
36832b578d3Smrg
36932b578d3Smrg                /* Restore LCD index */
37032b578d3Smrg                out8(LCD_INDEX, GetByte(pATI->LockData.lcd_index, 0));
37132b578d3Smrg            }
37232b578d3Smrg        }
37332b578d3Smrg    }
37432b578d3Smrg
37532b578d3Smrg#endif /* AVOID_CPIO */
37632b578d3Smrg
37732b578d3Smrg}
37832b578d3Smrg
37932b578d3Smrg/*
38032b578d3Smrg * ATILock --
38132b578d3Smrg *
38232b578d3Smrg * This function restores the state saved by ATIUnlock() above.
38332b578d3Smrg */
38432b578d3Smrgvoid
38532b578d3SmrgATILock
38632b578d3Smrg(
38732b578d3Smrg    ATIPtr pATI
38832b578d3Smrg)
38932b578d3Smrg{
39032b578d3Smrg
39132b578d3Smrg#ifndef AVOID_CPIO
39232b578d3Smrg
39332b578d3Smrg    CARD32 saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
39432b578d3Smrg
39532b578d3Smrg#endif /* AVOID_CPIO */
39632b578d3Smrg
39732b578d3Smrg    if (!pATI->Unlocked)
39832b578d3Smrg        return;
39932b578d3Smrg    pATI->Unlocked = FALSE;
40032b578d3Smrg
40132b578d3Smrg#ifndef AVOID_CPIO
40232b578d3Smrg
40332b578d3Smrg    if (pATI->VGAAdapter)
40432b578d3Smrg    {
40532b578d3Smrg        if (pATI->LCDPanelID >= 0)
40632b578d3Smrg        {
40732b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
40832b578d3Smrg            {
40932b578d3Smrg                saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
41032b578d3Smrg
41132b578d3Smrg                /* Setup to lock non-shadow registers */
41232b578d3Smrg                lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN;
41332b578d3Smrg                outr(LCD_GEN_CTRL, lcd_gen_ctrl);
41432b578d3Smrg            }
41532b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
41632b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
41732b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
41832b578d3Smrg            {
41932b578d3Smrg                saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
42032b578d3Smrg
42132b578d3Smrg                /* Setup to lock non-shadow registers */
42232b578d3Smrg                lcd_gen_ctrl = saved_lcd_gen_ctrl &
42332b578d3Smrg                    ~(CRTC_RW_SELECT | SHADOW_RW_EN);
42432b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
42532b578d3Smrg            }
42632b578d3Smrg        }
42732b578d3Smrg
42832b578d3Smrg        ATISetVGAIOBase(pATI, inb(R_GENMO));
42932b578d3Smrg
43032b578d3Smrg        /* Restore VGA locks */
43132b578d3Smrg        PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, pATI->LockData.crt03);
43232b578d3Smrg        PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
43332b578d3Smrg
43432b578d3Smrg        if (pATI->LCDPanelID >= 0)
43532b578d3Smrg        {
43632b578d3Smrg            /* Setup to lock shadow registers */
43732b578d3Smrg            lcd_gen_ctrl |= SHADOW_RW_EN;
43832b578d3Smrg
43932b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
44032b578d3Smrg                outr(LCD_GEN_CTRL, lcd_gen_ctrl);
44132b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
44232b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
44332b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
44432b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
44532b578d3Smrg
44632b578d3Smrg            /* Lock shadow registers */
44732b578d3Smrg            ATISetVGAIOBase(pATI, inb(R_GENMO));
44832b578d3Smrg
44932b578d3Smrg            PutReg(CRTX(pATI->CPIO_VGABase), 0x03U,
45032b578d3Smrg                pATI->LockData.shadow_crt03);
45132b578d3Smrg            PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
45232b578d3Smrg                pATI->LockData.shadow_crt11);
45332b578d3Smrg
45432b578d3Smrg            /* Restore selection */
45532b578d3Smrg            if (pATI->Chip == ATI_CHIP_264LT)
45632b578d3Smrg                outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
45732b578d3Smrg            else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
45832b578d3Smrg                        (pATI->Chip == ATI_CHIP_264XL) ||
45932b578d3Smrg                        (pATI->Chip == ATI_CHIP_MOBILITY)) */
46032b578d3Smrg                ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
46132b578d3Smrg        }
46232b578d3Smrg
46332b578d3Smrg        if (pATI->CPIO_VGAWonder)
46432b578d3Smrg        {
46532b578d3Smrg            /*
46632b578d3Smrg             * Restore emulation and protection bits in ATI extended VGA
46732b578d3Smrg             * registers.
46832b578d3Smrg             */
46932b578d3Smrg            ATIModifyExtReg(pATI, 0xB1U, -1, 0xFCU, pATI->LockData.b1);
47032b578d3Smrg            ATIModifyExtReg(pATI, 0xB4U, -1, 0x00U, pATI->LockData.b4);
47132b578d3Smrg            ATIModifyExtReg(pATI, 0xB5U, -1, 0xBFU, pATI->LockData.b5);
47232b578d3Smrg            ATIModifyExtReg(pATI, 0xB6U, -1, 0xDDU, pATI->LockData.b6);
47332b578d3Smrg            ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8 & 0x03U);
47432b578d3Smrg            ATIModifyExtReg(pATI, 0xB9U, -1, 0x7FU, pATI->LockData.b9);
47532b578d3Smrg            {
47632b578d3Smrg                ATIModifyExtReg(pATI, 0xBEU, -1, 0xFAU, pATI->LockData.be);
47732b578d3Smrg                {
47832b578d3Smrg                    ATIModifyExtReg(pATI, 0xA6U, -1, 0x7FU, pATI->LockData.a6);
47932b578d3Smrg                    ATIModifyExtReg(pATI, 0xABU, -1, 0xE7U, pATI->LockData.ab);
48032b578d3Smrg                }
48132b578d3Smrg            }
48232b578d3Smrg            ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8);
48332b578d3Smrg        }
48432b578d3Smrg    }
48532b578d3Smrg
48632b578d3Smrg#endif /* AVOID_CPIO */
48732b578d3Smrg
48832b578d3Smrg    {
48932b578d3Smrg        /* Reset everything */
49032b578d3Smrg        outr(BUS_CNTL, pATI->LockData.bus_cntl);
49132b578d3Smrg
49232b578d3Smrg        outr(CRTC_INT_CNTL, pATI->LockData.crtc_int_cntl);
49332b578d3Smrg
49432b578d3Smrg        outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
49532b578d3Smrg        outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl);
49632b578d3Smrg        outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
49732b578d3Smrg
49832b578d3Smrg        outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
49932b578d3Smrg        outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl);
50032b578d3Smrg        outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
50132b578d3Smrg
50232b578d3Smrg#ifndef AVOID_CPIO
50332b578d3Smrg
50432b578d3Smrg        outr(CONFIG_CNTL, pATI->LockData.config_cntl);
50532b578d3Smrg
50632b578d3Smrg#endif /* AVOID_CPIO */
50732b578d3Smrg
50832b578d3Smrg        outr(DAC_CNTL, pATI->LockData.dac_cntl);
50932b578d3Smrg        if (pATI->Chip < ATI_CHIP_264CT)
51032b578d3Smrg            outr(MEM_CNTL, pATI->LockData.mem_cntl);
51132b578d3Smrg        if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
51232b578d3Smrg        {
51332b578d3Smrg            outr(LCD_INDEX, pATI->LockData.lcd_index);
51432b578d3Smrg#ifndef TV_OUT
51532b578d3Smrg            if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
51632b578d3Smrg                outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
51732b578d3Smrg#endif /* TV_OUT */
51832b578d3Smrg        }
51932b578d3Smrg        if (pATI->Chip >= ATI_CHIP_264VTB)
52032b578d3Smrg        {
52132b578d3Smrg            outr(MPP_CONFIG, pATI->LockData.mpp_config);
52232b578d3Smrg            outr(MPP_STROBE_SEQ, pATI->LockData.mpp_strobe_seq);
52332b578d3Smrg#ifndef TV_OUT
52432b578d3Smrg            outr(TVO_CNTL, pATI->LockData.tvo_cntl);
52532b578d3Smrg#endif /* TV_OUT */
52632b578d3Smrg            if (pATI->Chip >= ATI_CHIP_264GT2C)
52732b578d3Smrg            {
52832b578d3Smrg                outr(HW_DEBUG, pATI->LockData.hw_debug);
52932b578d3Smrg                if (pATI->Chip >= ATI_CHIP_264GTPRO)
53032b578d3Smrg                {
53132b578d3Smrg                    outr(I2C_CNTL_0, pATI->LockData.i2c_cntl_0);
53232b578d3Smrg                    outr(I2C_CNTL_1, pATI->LockData.i2c_cntl_1);
53332b578d3Smrg                }
53432b578d3Smrg            }
53532b578d3Smrg        }
53632b578d3Smrg    }
53732b578d3Smrg}
538