atiwonder.c revision 32b578d3
1/*
2 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of Marc Aurele La France not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  Marc Aurele La France makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as-is" without express or implied warranty.
13 *
14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27/*
28 * The ATI x8800 chips use special registers for their extended VGA features.
29 * These registers are accessible through an index I/O port and a data I/O
30 * port.  BIOS initialisation stores the index port number in the Graphics
31 * register bank (0x03CE), indices 0x50 and 0x51.  Unfortunately, for all but
32 * the 18800-x series of adapters, these registers are write-only (a.k.a. black
33 * holes).  On all but 88800's, the index port number can be found in the short
34 * integer at offset 0x10 in the BIOS.  For 88800's, this driver will use
35 * 0x01CE or 0x03CE as the index port number, depending on the I/O port
36 * decoding used.  The data port number is one more than the index port number
37 * (i.e. 0x01CF).  These ports differ slightly in their I/O behaviour from the
38 * normal VGA ones:
39 *
40 *    write:  outw(0x01CE, (data << 8) | index);        (16-bit, not used)
41 *            outb(0x01CE, index);  outb(0x01CF, data); (8-bit)
42 *    read:   outb(0x01CE, index);  data = inb(0x01CF);
43 *
44 * Two consecutive byte-writes to the data port will not work.  Furthermore an
45 * index written to 0x01CE is usable only once.  Note also that the setting of
46 * ATI extended registers (especially those with clock selection bits) should
47 * be bracketed by a sequencer reset.
48 *
49 * The number of these extended VGA registers varies by chipset.  The 18800
50 * series have 16, the 28800 series have 32, while 68800's and 88800's have 64.
51 * The last 16 on each have almost identical definitions.  Thus, the BIOS sets
52 * up an indexing scheme whereby the last 16 extended VGA registers are
53 * accessed at indices 0xB0 through 0xBF on all chipsets.
54 */
55
56#include "ati.h"
57#include "atichip.h"
58#include "atiwonder.h"
59#include "atiwonderio.h"
60
61#ifndef AVOID_CPIO
62
63/*
64 * ATIVGAWonderPreInit --
65 *
66 * This function is called to initialise the VGA Wonder part of an ATIHWRec
67 * that is common to all modes generated by the driver.
68 */
69void
70ATIVGAWonderPreInit
71(
72    ATIPtr      pATI,
73    ATIHWPtr    pATIHW
74)
75{
76    pATIHW->b3 = ATIGetExtReg(0xB3U) & 0x20U;
77        pATIHW->b6 = 0x04U;
78        pATIHW->b6 |= 0x01U;
79        pATIHW->bf = ATIGetExtReg(0xBFU) & 0x5FU;
80        pATIHW->a3 = ATIGetExtReg(0xA3U) & 0x67U;
81        pATIHW->ab = ATIGetExtReg(0xABU) & 0xE7U;
82        pATIHW->ae = ATIGetExtReg(0xAEU) & 0xE0U;
83}
84
85/*
86 * ATIVGAWonderSave --
87 *
88 * This function is called to save the VGA Wonder portion of the current video
89 * state.
90 */
91void
92ATIVGAWonderSave
93(
94    ATIPtr      pATI,
95    ATIHWPtr    pATIHW
96)
97{
98    pATIHW->b0 = ATIGetExtReg(0xB0U);
99    pATIHW->b1 = ATIGetExtReg(0xB1U);
100    pATIHW->b2 = ATIGetExtReg(0xB2U);
101    pATIHW->b3 = ATIGetExtReg(0xB3U);
102    pATIHW->b5 = ATIGetExtReg(0xB5U);
103    pATIHW->b6 = ATIGetExtReg(0xB6U);
104    pATIHW->b8 = ATIGetExtReg(0xB8U);
105    pATIHW->b9 = ATIGetExtReg(0xB9U);
106    pATIHW->ba = ATIGetExtReg(0xBAU);
107    pATIHW->bd = ATIGetExtReg(0xBDU);
108    {
109        pATIHW->be = ATIGetExtReg(0xBEU);
110        {
111            pATIHW->bf = ATIGetExtReg(0xBFU);
112            pATIHW->a3 = ATIGetExtReg(0xA3U);
113            pATIHW->a6 = ATIGetExtReg(0xA6U);
114            pATIHW->a7 = ATIGetExtReg(0xA7U);
115            pATIHW->ab = ATIGetExtReg(0xABU);
116            pATIHW->ac = ATIGetExtReg(0xACU);
117            pATIHW->ad = ATIGetExtReg(0xADU);
118            pATIHW->ae = ATIGetExtReg(0xAEU);
119        }
120    }
121}
122
123/*
124 * ATIVGAWonderSet --
125 *
126 * This function loads the VGA Wonder portion of a video state.
127 */
128void
129ATIVGAWonderSet
130(
131    ATIPtr      pATI,
132    ATIHWPtr    pATIHW
133)
134{
135    {
136        ATIModifyExtReg(pATI, 0xBEU, -1, 0x00U, pATIHW->be);
137        {
138            ATIModifyExtReg(pATI, 0xBFU, -1, 0x00U, pATIHW->bf);
139            ATIModifyExtReg(pATI, 0xA3U, -1, 0x00U, pATIHW->a3);
140            ATIModifyExtReg(pATI, 0xA6U, -1, 0x00U, pATIHW->a6);
141            ATIModifyExtReg(pATI, 0xA7U, -1, 0x00U, pATIHW->a7);
142            ATIModifyExtReg(pATI, 0xABU, -1, 0x00U, pATIHW->ab);
143            ATIModifyExtReg(pATI, 0xACU, -1, 0x00U, pATIHW->ac);
144            ATIModifyExtReg(pATI, 0xADU, -1, 0x00U, pATIHW->ad);
145            ATIModifyExtReg(pATI, 0xAEU, -1, 0x00U, pATIHW->ae);
146        }
147    }
148    ATIModifyExtReg(pATI, 0xB0U, -1, 0x00U, pATIHW->b0);
149    ATIModifyExtReg(pATI, 0xB1U, -1, 0x00U, pATIHW->b1);
150    ATIModifyExtReg(pATI, 0xB3U, -1, 0x00U, pATIHW->b3);
151    ATIModifyExtReg(pATI, 0xB5U, -1, 0x00U, pATIHW->b5);
152    ATIModifyExtReg(pATI, 0xB6U, -1, 0x00U, pATIHW->b6);
153    ATIModifyExtReg(pATI, 0xB8U, -1, 0x00U, pATIHW->b8);
154    ATIModifyExtReg(pATI, 0xB9U, -1, 0x00U, pATIHW->b9);
155    ATIModifyExtReg(pATI, 0xBAU, -1, 0x00U, pATIHW->ba);
156    ATIModifyExtReg(pATI, 0xBDU, -1, 0x00U, pATIHW->bd);
157}
158
159#endif /* AVOID_CPIO */
160