105b261ecSmrg
205b261ecSmrg/*
305b261ecSmrg *
405b261ecSmrg * Copyright 1991-1999 by The XFree86 Project, Inc.
505b261ecSmrg *
605b261ecSmrg * Loosely based on code bearing the following copyright:
705b261ecSmrg *
805b261ecSmrg *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
905b261ecSmrg *
1005b261ecSmrg */
1105b261ecSmrg
1205b261ecSmrg#define _NEED_SYSI86
1305b261ecSmrg
1405b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
1505b261ecSmrg#include <xorg-config.h>
1605b261ecSmrg#endif
1705b261ecSmrg
1805b261ecSmrg#include <stdlib.h>
1905b261ecSmrg#include <string.h>
2005b261ecSmrg#include <unistd.h>
2105b261ecSmrg
2205b261ecSmrg#include <X11/X.h>
2305b261ecSmrg#include "misc.h"
2405b261ecSmrg
2505b261ecSmrg#include "xf86.h"
2605b261ecSmrg#include "xf86_OSproc.h"
2705b261ecSmrg#include "vgaHW.h"
2805b261ecSmrg
2905b261ecSmrg#include "compiler.h"
3005b261ecSmrg
3105b261ecSmrg#include "xf86cmap.h"
3205b261ecSmrg
334642e01fSmrg#include "Pci.h"
344642e01fSmrg
3505b261ecSmrg#ifndef SAVE_FONT1
3605b261ecSmrg#define SAVE_FONT1 1
3705b261ecSmrg#endif
3805b261ecSmrg
3905b261ecSmrg/*
4005b261ecSmrg * These used to be OS-specific, which made this module have an undesirable
4105b261ecSmrg * OS dependency.  Define them by default for all platforms.
4205b261ecSmrg */
4305b261ecSmrg#ifndef NEED_SAVED_CMAP
4405b261ecSmrg#define NEED_SAVED_CMAP
4505b261ecSmrg#endif
4605b261ecSmrg#ifndef SAVE_TEXT
4705b261ecSmrg#define SAVE_TEXT 1
4805b261ecSmrg#endif
4905b261ecSmrg#ifndef SAVE_FONT2
5005b261ecSmrg#define SAVE_FONT2 1
5105b261ecSmrg#endif
5205b261ecSmrg
5305b261ecSmrg/* bytes per plane to save for text */
5405b261ecSmrg#define TEXT_AMOUNT 16384
5505b261ecSmrg
5605b261ecSmrg/* bytes per plane to save for font data */
5705b261ecSmrg#define FONT_AMOUNT (8*8192)
5805b261ecSmrg
5905b261ecSmrg#if 0
6005b261ecSmrg/* Override all of these for now */
6105b261ecSmrg#undef SAVE_FONT1
6205b261ecSmrg#define SAVE_FONT1 1
6305b261ecSmrg#undef SAVE_FONT2
6405b261ecSmrg#define SAVE_FONT2 1
6505b261ecSmrg#undef SAVE_TEST
6605b261ecSmrg#define SAVE_TEST 1
6705b261ecSmrg#undef FONT_AMOUNT
6805b261ecSmrg#define FONT_AMOUNT 65536
6905b261ecSmrg#undef TEXT_AMOUNT
7005b261ecSmrg#define TEXT_AMOUNT 65536
7105b261ecSmrg#endif
7205b261ecSmrg
7305b261ecSmrg/* DAC indices for white and black */
7405b261ecSmrg#define WHITE_VALUE 0x3F
7505b261ecSmrg#define BLACK_VALUE 0x00
7605b261ecSmrg#define OVERSCAN_VALUE 0x01
7705b261ecSmrg
7805b261ecSmrg/* Use a private definition of this here */
7905b261ecSmrg#undef VGAHWPTR
8005b261ecSmrg#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
8105b261ecSmrg#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
8205b261ecSmrg
8305b261ecSmrgstatic int vgaHWPrivateIndex = -1;
8405b261ecSmrg
8505b261ecSmrg#define DAC_TEST_MASK 0x3F
8605b261ecSmrg
8705b261ecSmrg#ifdef NEED_SAVED_CMAP
8805b261ecSmrg/* This default colourmap is used only when it can't be read from the VGA */
8905b261ecSmrg
9035c4bbdfSmrgstatic CARD8 defaultDAC[768] = {
9135c4bbdfSmrg    0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
9235c4bbdfSmrg    42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
9335c4bbdfSmrg    21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
9435c4bbdfSmrg    63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
9535c4bbdfSmrg    0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11,
9635c4bbdfSmrg    14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24,
9735c4bbdfSmrg    28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40,
9835c4bbdfSmrg    45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63,
9935c4bbdfSmrg    0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63,
10035c4bbdfSmrg    63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16,
10135c4bbdfSmrg    63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0,
10235c4bbdfSmrg    63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0,
10335c4bbdfSmrg    0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47,
10435c4bbdfSmrg    0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63,
10535c4bbdfSmrg    31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63,
10635c4bbdfSmrg    63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39,
10735c4bbdfSmrg    63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31,
10835c4bbdfSmrg    63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31,
10935c4bbdfSmrg    31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55,
11035c4bbdfSmrg    31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63,
11135c4bbdfSmrg    45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63,
11235c4bbdfSmrg    63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49,
11335c4bbdfSmrg    63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45,
11435c4bbdfSmrg    63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45,
11535c4bbdfSmrg    45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58,
11635c4bbdfSmrg    45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63,
11735c4bbdfSmrg    0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28,
11835c4bbdfSmrg    28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7,
11935c4bbdfSmrg    28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0,
12035c4bbdfSmrg    28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0,
12135c4bbdfSmrg    0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21,
12235c4bbdfSmrg    0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28,
12335c4bbdfSmrg    14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28,
12435c4bbdfSmrg    28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17,
12535c4bbdfSmrg    28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14,
12635c4bbdfSmrg    28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14,
12735c4bbdfSmrg    14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24,
12835c4bbdfSmrg    14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28,
12935c4bbdfSmrg    20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28,
13035c4bbdfSmrg    28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22,
13135c4bbdfSmrg    28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20,
13235c4bbdfSmrg    28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20,
13335c4bbdfSmrg    20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26,
13435c4bbdfSmrg    20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28,
13535c4bbdfSmrg    0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16,
13635c4bbdfSmrg    16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4,
13735c4bbdfSmrg    16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0,
13835c4bbdfSmrg    16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0,
13935c4bbdfSmrg    0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12,
14035c4bbdfSmrg    0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16,
14135c4bbdfSmrg    8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16,
14235c4bbdfSmrg    16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10,
14335c4bbdfSmrg    16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8,
14435c4bbdfSmrg    16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8,
14535c4bbdfSmrg    8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14,
14635c4bbdfSmrg    8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16,
14735c4bbdfSmrg    11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16,
14835c4bbdfSmrg    16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12,
14935c4bbdfSmrg    16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11,
15035c4bbdfSmrg    16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11,
15135c4bbdfSmrg    11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15,
15235c4bbdfSmrg    11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16,
15335c4bbdfSmrg    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15435c4bbdfSmrg    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15505b261ecSmrg};
15635c4bbdfSmrg#endif                          /* NEED_SAVED_CMAP */
15705b261ecSmrg
15805b261ecSmrg/*
15905b261ecSmrg * Standard VGA versions of the register access functions.
16005b261ecSmrg */
16105b261ecSmrgstatic void
16205b261ecSmrgstdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
16305b261ecSmrg{
16435c4bbdfSmrg    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
16535c4bbdfSmrg    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
16605b261ecSmrg}
16705b261ecSmrg
16805b261ecSmrgstatic CARD8
16905b261ecSmrgstdReadCrtc(vgaHWPtr hwp, CARD8 index)
17005b261ecSmrg{
17135c4bbdfSmrg    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
17235c4bbdfSmrg    return pci_io_read8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET);
17305b261ecSmrg}
17405b261ecSmrg
17505b261ecSmrgstatic void
17605b261ecSmrgstdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
17705b261ecSmrg{
17835c4bbdfSmrg    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
17935c4bbdfSmrg    pci_io_write8(hwp->io, VGA_GRAPH_DATA, value);
18005b261ecSmrg}
18105b261ecSmrg
18205b261ecSmrgstatic CARD8
18305b261ecSmrgstdReadGr(vgaHWPtr hwp, CARD8 index)
18405b261ecSmrg{
18535c4bbdfSmrg    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
18635c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_GRAPH_DATA);
18705b261ecSmrg}
18805b261ecSmrg
18905b261ecSmrgstatic void
19005b261ecSmrgstdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
19105b261ecSmrg{
19235c4bbdfSmrg    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
19335c4bbdfSmrg    pci_io_write8(hwp->io, VGA_SEQ_DATA, value);
19405b261ecSmrg}
19505b261ecSmrg
19605b261ecSmrgstatic CARD8
19705b261ecSmrgstdReadSeq(vgaHWPtr hwp, CARD8 index)
19805b261ecSmrg{
19935c4bbdfSmrg    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
20035c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_SEQ_DATA);
20105b261ecSmrg}
20205b261ecSmrg
20305b261ecSmrgstatic CARD8
20405b261ecSmrgstdReadST00(vgaHWPtr hwp)
20505b261ecSmrg{
20635c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_IN_STAT_0);
20705b261ecSmrg}
20805b261ecSmrg
20905b261ecSmrgstatic CARD8
21005b261ecSmrgstdReadST01(vgaHWPtr hwp)
21105b261ecSmrg{
21235c4bbdfSmrg    return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
21305b261ecSmrg}
21405b261ecSmrg
21505b261ecSmrgstatic CARD8
21605b261ecSmrgstdReadFCR(vgaHWPtr hwp)
21705b261ecSmrg{
21835c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_FEATURE_R);
21905b261ecSmrg}
22005b261ecSmrg
22105b261ecSmrgstatic void
22205b261ecSmrgstdWriteFCR(vgaHWPtr hwp, CARD8 value)
22305b261ecSmrg{
22435c4bbdfSmrg    pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrgstatic void
22805b261ecSmrgstdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
22905b261ecSmrg{
23005b261ecSmrg    if (hwp->paletteEnabled)
23135c4bbdfSmrg        index &= ~0x20;
23205b261ecSmrg    else
23335c4bbdfSmrg        index |= 0x20;
23405b261ecSmrg
23535c4bbdfSmrg    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
23635c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
23735c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ATTR_DATA_W, value);
23805b261ecSmrg}
23905b261ecSmrg
24005b261ecSmrgstatic CARD8
24105b261ecSmrgstdReadAttr(vgaHWPtr hwp, CARD8 index)
24205b261ecSmrg{
24305b261ecSmrg    if (hwp->paletteEnabled)
24435c4bbdfSmrg        index &= ~0x20;
24505b261ecSmrg    else
24635c4bbdfSmrg        index |= 0x20;
24705b261ecSmrg
24835c4bbdfSmrg    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
24935c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
25035c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_ATTR_DATA_R);
25105b261ecSmrg}
25205b261ecSmrg
25305b261ecSmrgstatic void
25405b261ecSmrgstdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
25505b261ecSmrg{
25635c4bbdfSmrg    pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
25705b261ecSmrg}
25805b261ecSmrg
25905b261ecSmrgstatic CARD8
26005b261ecSmrgstdReadMiscOut(vgaHWPtr hwp)
26105b261ecSmrg{
26235c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
26305b261ecSmrg}
26405b261ecSmrg
26505b261ecSmrgstatic void
26605b261ecSmrgstdEnablePalette(vgaHWPtr hwp)
26705b261ecSmrg{
26835c4bbdfSmrg    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
26935c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x00);
27005b261ecSmrg    hwp->paletteEnabled = TRUE;
27105b261ecSmrg}
27205b261ecSmrg
27305b261ecSmrgstatic void
27405b261ecSmrgstdDisablePalette(vgaHWPtr hwp)
27505b261ecSmrg{
27635c4bbdfSmrg    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
27735c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x20);
27805b261ecSmrg    hwp->paletteEnabled = FALSE;
27905b261ecSmrg}
28005b261ecSmrg
28105b261ecSmrgstatic void
28205b261ecSmrgstdWriteDacMask(vgaHWPtr hwp, CARD8 value)
28305b261ecSmrg{
28435c4bbdfSmrg    pci_io_write8(hwp->io, VGA_DAC_MASK, value);
28505b261ecSmrg}
28605b261ecSmrg
28705b261ecSmrgstatic CARD8
28805b261ecSmrgstdReadDacMask(vgaHWPtr hwp)
28905b261ecSmrg{
29035c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_DAC_MASK);
29105b261ecSmrg}
29205b261ecSmrg
29305b261ecSmrgstatic void
29405b261ecSmrgstdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
29505b261ecSmrg{
29635c4bbdfSmrg    pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
29705b261ecSmrg}
29805b261ecSmrg
29905b261ecSmrgstatic void
30005b261ecSmrgstdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
30105b261ecSmrg{
30235c4bbdfSmrg    pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
30305b261ecSmrg}
30405b261ecSmrg
30505b261ecSmrgstatic void
30605b261ecSmrgstdWriteDacData(vgaHWPtr hwp, CARD8 value)
30705b261ecSmrg{
30835c4bbdfSmrg    pci_io_write8(hwp->io, VGA_DAC_DATA, value);
30905b261ecSmrg}
31005b261ecSmrg
31105b261ecSmrgstatic CARD8
31205b261ecSmrgstdReadDacData(vgaHWPtr hwp)
31305b261ecSmrg{
31435c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_DAC_DATA);
31505b261ecSmrg}
31605b261ecSmrg
31705b261ecSmrgstatic CARD8
31805b261ecSmrgstdReadEnable(vgaHWPtr hwp)
31905b261ecSmrg{
32035c4bbdfSmrg    return pci_io_read8(hwp->io, VGA_ENABLE);
32105b261ecSmrg}
32205b261ecSmrg
32305b261ecSmrgstatic void
32405b261ecSmrgstdWriteEnable(vgaHWPtr hwp, CARD8 value)
32505b261ecSmrg{
32635c4bbdfSmrg    pci_io_write8(hwp->io, VGA_ENABLE, value);
32705b261ecSmrg}
32805b261ecSmrg
32905b261ecSmrgvoid
33005b261ecSmrgvgaHWSetStdFuncs(vgaHWPtr hwp)
33105b261ecSmrg{
33235c4bbdfSmrg    hwp->writeCrtc = stdWriteCrtc;
33335c4bbdfSmrg    hwp->readCrtc = stdReadCrtc;
33435c4bbdfSmrg    hwp->writeGr = stdWriteGr;
33535c4bbdfSmrg    hwp->readGr = stdReadGr;
33635c4bbdfSmrg    hwp->readST00 = stdReadST00;
33735c4bbdfSmrg    hwp->readST01 = stdReadST01;
33835c4bbdfSmrg    hwp->readFCR = stdReadFCR;
33935c4bbdfSmrg    hwp->writeFCR = stdWriteFCR;
34035c4bbdfSmrg    hwp->writeAttr = stdWriteAttr;
34135c4bbdfSmrg    hwp->readAttr = stdReadAttr;
34235c4bbdfSmrg    hwp->writeSeq = stdWriteSeq;
34335c4bbdfSmrg    hwp->readSeq = stdReadSeq;
34435c4bbdfSmrg    hwp->writeMiscOut = stdWriteMiscOut;
34535c4bbdfSmrg    hwp->readMiscOut = stdReadMiscOut;
34635c4bbdfSmrg    hwp->enablePalette = stdEnablePalette;
34735c4bbdfSmrg    hwp->disablePalette = stdDisablePalette;
34835c4bbdfSmrg    hwp->writeDacMask = stdWriteDacMask;
34935c4bbdfSmrg    hwp->readDacMask = stdReadDacMask;
35035c4bbdfSmrg    hwp->writeDacWriteAddr = stdWriteDacWriteAddr;
35135c4bbdfSmrg    hwp->writeDacReadAddr = stdWriteDacReadAddr;
35235c4bbdfSmrg    hwp->writeDacData = stdWriteDacData;
35335c4bbdfSmrg    hwp->readDacData = stdReadDacData;
35435c4bbdfSmrg    hwp->readEnable = stdReadEnable;
35535c4bbdfSmrg    hwp->writeEnable = stdWriteEnable;
35635c4bbdfSmrg
35735c4bbdfSmrg    hwp->io = pci_legacy_open_io(hwp->dev, 0, 64 * 1024);
35805b261ecSmrg}
35905b261ecSmrg
36005b261ecSmrg/*
36105b261ecSmrg * MMIO versions of the register access functions.  These require
36205b261ecSmrg * hwp->MemBase to be set in such a way that when the standard VGA port
36305b261ecSmrg * adderss is added the correct memory address results.
36405b261ecSmrg */
36505b261ecSmrg
36605b261ecSmrg#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
36705b261ecSmrg#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
36805b261ecSmrg
36905b261ecSmrgstatic void
37005b261ecSmrgmmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
37105b261ecSmrg{
37205b261ecSmrg    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
37305b261ecSmrg    moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
37405b261ecSmrg}
37505b261ecSmrg
37605b261ecSmrgstatic CARD8
37705b261ecSmrgmmioReadCrtc(vgaHWPtr hwp, CARD8 index)
37805b261ecSmrg{
37905b261ecSmrg    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
38005b261ecSmrg    return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
38105b261ecSmrg}
38205b261ecSmrg
38305b261ecSmrgstatic void
38405b261ecSmrgmmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
38505b261ecSmrg{
38605b261ecSmrg    moutb(VGA_GRAPH_INDEX, index);
38705b261ecSmrg    moutb(VGA_GRAPH_DATA, value);
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrgstatic CARD8
39105b261ecSmrgmmioReadGr(vgaHWPtr hwp, CARD8 index)
39205b261ecSmrg{
39305b261ecSmrg    moutb(VGA_GRAPH_INDEX, index);
39405b261ecSmrg    return minb(VGA_GRAPH_DATA);
39505b261ecSmrg}
39605b261ecSmrg
39705b261ecSmrgstatic void
39805b261ecSmrgmmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
39905b261ecSmrg{
40005b261ecSmrg    moutb(VGA_SEQ_INDEX, index);
40105b261ecSmrg    moutb(VGA_SEQ_DATA, value);
40205b261ecSmrg}
40305b261ecSmrg
40405b261ecSmrgstatic CARD8
40505b261ecSmrgmmioReadSeq(vgaHWPtr hwp, CARD8 index)
40605b261ecSmrg{
40705b261ecSmrg    moutb(VGA_SEQ_INDEX, index);
40805b261ecSmrg    return minb(VGA_SEQ_DATA);
40905b261ecSmrg}
41005b261ecSmrg
41105b261ecSmrgstatic CARD8
41205b261ecSmrgmmioReadST00(vgaHWPtr hwp)
41305b261ecSmrg{
41405b261ecSmrg    return minb(VGA_IN_STAT_0);
41505b261ecSmrg}
41605b261ecSmrg
41705b261ecSmrgstatic CARD8
41805b261ecSmrgmmioReadST01(vgaHWPtr hwp)
41905b261ecSmrg{
42005b261ecSmrg    return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
42105b261ecSmrg}
42205b261ecSmrg
42305b261ecSmrgstatic CARD8
42405b261ecSmrgmmioReadFCR(vgaHWPtr hwp)
42505b261ecSmrg{
42605b261ecSmrg    return minb(VGA_FEATURE_R);
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrgstatic void
43005b261ecSmrgmmioWriteFCR(vgaHWPtr hwp, CARD8 value)
43105b261ecSmrg{
43235c4bbdfSmrg    moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
43305b261ecSmrg}
43405b261ecSmrg
43505b261ecSmrgstatic void
43605b261ecSmrgmmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
43705b261ecSmrg{
43805b261ecSmrg    if (hwp->paletteEnabled)
43935c4bbdfSmrg        index &= ~0x20;
44005b261ecSmrg    else
44135c4bbdfSmrg        index |= 0x20;
44205b261ecSmrg
44305b261ecSmrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
44405b261ecSmrg    moutb(VGA_ATTR_INDEX, index);
44505b261ecSmrg    moutb(VGA_ATTR_DATA_W, value);
44605b261ecSmrg}
44705b261ecSmrg
44805b261ecSmrgstatic CARD8
44905b261ecSmrgmmioReadAttr(vgaHWPtr hwp, CARD8 index)
45005b261ecSmrg{
45105b261ecSmrg    if (hwp->paletteEnabled)
45235c4bbdfSmrg        index &= ~0x20;
45305b261ecSmrg    else
45435c4bbdfSmrg        index |= 0x20;
45505b261ecSmrg
45605b261ecSmrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
45705b261ecSmrg    moutb(VGA_ATTR_INDEX, index);
45805b261ecSmrg    return minb(VGA_ATTR_DATA_R);
45905b261ecSmrg}
46005b261ecSmrg
46105b261ecSmrgstatic void
46205b261ecSmrgmmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
46305b261ecSmrg{
46405b261ecSmrg    moutb(VGA_MISC_OUT_W, value);
46505b261ecSmrg}
46605b261ecSmrg
46705b261ecSmrgstatic CARD8
46805b261ecSmrgmmioReadMiscOut(vgaHWPtr hwp)
46905b261ecSmrg{
47005b261ecSmrg    return minb(VGA_MISC_OUT_R);
47105b261ecSmrg}
47205b261ecSmrg
47305b261ecSmrgstatic void
47405b261ecSmrgmmioEnablePalette(vgaHWPtr hwp)
47505b261ecSmrg{
47605b261ecSmrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
47705b261ecSmrg    moutb(VGA_ATTR_INDEX, 0x00);
47805b261ecSmrg    hwp->paletteEnabled = TRUE;
47905b261ecSmrg}
48005b261ecSmrg
48105b261ecSmrgstatic void
48205b261ecSmrgmmioDisablePalette(vgaHWPtr hwp)
48305b261ecSmrg{
48405b261ecSmrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
48505b261ecSmrg    moutb(VGA_ATTR_INDEX, 0x20);
48605b261ecSmrg    hwp->paletteEnabled = FALSE;
48705b261ecSmrg}
48805b261ecSmrg
48905b261ecSmrgstatic void
49005b261ecSmrgmmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
49105b261ecSmrg{
49205b261ecSmrg    moutb(VGA_DAC_MASK, value);
49305b261ecSmrg}
49405b261ecSmrg
49505b261ecSmrgstatic CARD8
49605b261ecSmrgmmioReadDacMask(vgaHWPtr hwp)
49705b261ecSmrg{
49805b261ecSmrg    return minb(VGA_DAC_MASK);
49905b261ecSmrg}
50005b261ecSmrg
50105b261ecSmrgstatic void
50205b261ecSmrgmmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
50305b261ecSmrg{
50405b261ecSmrg    moutb(VGA_DAC_READ_ADDR, value);
50505b261ecSmrg}
50605b261ecSmrg
50705b261ecSmrgstatic void
50805b261ecSmrgmmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
50905b261ecSmrg{
51005b261ecSmrg    moutb(VGA_DAC_WRITE_ADDR, value);
51105b261ecSmrg}
51205b261ecSmrg
51305b261ecSmrgstatic void
51405b261ecSmrgmmioWriteDacData(vgaHWPtr hwp, CARD8 value)
51505b261ecSmrg{
51605b261ecSmrg    moutb(VGA_DAC_DATA, value);
51705b261ecSmrg}
51805b261ecSmrg
51905b261ecSmrgstatic CARD8
52005b261ecSmrgmmioReadDacData(vgaHWPtr hwp)
52105b261ecSmrg{
52205b261ecSmrg    return minb(VGA_DAC_DATA);
52305b261ecSmrg}
52405b261ecSmrg
52505b261ecSmrgstatic CARD8
52605b261ecSmrgmmioReadEnable(vgaHWPtr hwp)
52705b261ecSmrg{
52805b261ecSmrg    return minb(VGA_ENABLE);
52905b261ecSmrg}
53005b261ecSmrg
53105b261ecSmrgstatic void
53205b261ecSmrgmmioWriteEnable(vgaHWPtr hwp, CARD8 value)
53305b261ecSmrg{
53405b261ecSmrg    moutb(VGA_ENABLE, value);
53505b261ecSmrg}
53605b261ecSmrg
53705b261ecSmrgvoid
53805b261ecSmrgvgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
53905b261ecSmrg{
54035c4bbdfSmrg    hwp->writeCrtc = mmioWriteCrtc;
54135c4bbdfSmrg    hwp->readCrtc = mmioReadCrtc;
54235c4bbdfSmrg    hwp->writeGr = mmioWriteGr;
54335c4bbdfSmrg    hwp->readGr = mmioReadGr;
54435c4bbdfSmrg    hwp->readST00 = mmioReadST00;
54535c4bbdfSmrg    hwp->readST01 = mmioReadST01;
54635c4bbdfSmrg    hwp->readFCR = mmioReadFCR;
54735c4bbdfSmrg    hwp->writeFCR = mmioWriteFCR;
54835c4bbdfSmrg    hwp->writeAttr = mmioWriteAttr;
54935c4bbdfSmrg    hwp->readAttr = mmioReadAttr;
55035c4bbdfSmrg    hwp->writeSeq = mmioWriteSeq;
55135c4bbdfSmrg    hwp->readSeq = mmioReadSeq;
55235c4bbdfSmrg    hwp->writeMiscOut = mmioWriteMiscOut;
55335c4bbdfSmrg    hwp->readMiscOut = mmioReadMiscOut;
55435c4bbdfSmrg    hwp->enablePalette = mmioEnablePalette;
55535c4bbdfSmrg    hwp->disablePalette = mmioDisablePalette;
55635c4bbdfSmrg    hwp->writeDacMask = mmioWriteDacMask;
55735c4bbdfSmrg    hwp->readDacMask = mmioReadDacMask;
55835c4bbdfSmrg    hwp->writeDacWriteAddr = mmioWriteDacWriteAddr;
55935c4bbdfSmrg    hwp->writeDacReadAddr = mmioWriteDacReadAddr;
56035c4bbdfSmrg    hwp->writeDacData = mmioWriteDacData;
56135c4bbdfSmrg    hwp->readDacData = mmioReadDacData;
56235c4bbdfSmrg    hwp->MMIOBase = base;
56335c4bbdfSmrg    hwp->MMIOOffset = offset;
56435c4bbdfSmrg    hwp->readEnable = mmioReadEnable;
56535c4bbdfSmrg    hwp->writeEnable = mmioWriteEnable;
56605b261ecSmrg}
56705b261ecSmrg
56805b261ecSmrg/*
56905b261ecSmrg * vgaHWProtect --
57005b261ecSmrg *	Protect VGA registers and memory from corruption during loads.
57105b261ecSmrg */
57205b261ecSmrg
57305b261ecSmrgvoid
57405b261ecSmrgvgaHWProtect(ScrnInfoPtr pScrn, Bool on)
57505b261ecSmrg{
57635c4bbdfSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
57735c4bbdfSmrg
57835c4bbdfSmrg    unsigned char tmp;
57935c4bbdfSmrg
58035c4bbdfSmrg    if (pScrn->vtSema) {
58135c4bbdfSmrg        if (on) {
58235c4bbdfSmrg            /*
58335c4bbdfSmrg             * Turn off screen and disable sequencer.
58435c4bbdfSmrg             */
58535c4bbdfSmrg            tmp = hwp->readSeq(hwp, 0x01);
58635c4bbdfSmrg
58735c4bbdfSmrg            vgaHWSeqReset(hwp, TRUE);   /* start synchronous reset */
58835c4bbdfSmrg            hwp->writeSeq(hwp, 0x01, tmp | 0x20);       /* disable the display */
58935c4bbdfSmrg
59035c4bbdfSmrg            hwp->enablePalette(hwp);
59135c4bbdfSmrg        }
59235c4bbdfSmrg        else {
59335c4bbdfSmrg            /*
594ed6184dfSmrg             * Re-enable sequencer, then turn on screen.
59535c4bbdfSmrg             */
59635c4bbdfSmrg
59735c4bbdfSmrg            tmp = hwp->readSeq(hwp, 0x01);
59835c4bbdfSmrg
599ed6184dfSmrg            hwp->writeSeq(hwp, 0x01, tmp & ~0x20);      /* re-enable display */
60035c4bbdfSmrg            vgaHWSeqReset(hwp, FALSE);  /* clear synchronousreset */
60135c4bbdfSmrg
60235c4bbdfSmrg            hwp->disablePalette(hwp);
60335c4bbdfSmrg        }
60405b261ecSmrg    }
60505b261ecSmrg}
60605b261ecSmrg
60735c4bbdfSmrgvgaHWProtectProc *
60835c4bbdfSmrgvgaHWProtectWeak(void)
60935c4bbdfSmrg{
61035c4bbdfSmrg    return vgaHWProtect;
61105b261ecSmrg}
61205b261ecSmrg
61305b261ecSmrg/*
61405b261ecSmrg * vgaHWBlankScreen -- blank the screen.
61505b261ecSmrg */
61605b261ecSmrg
61705b261ecSmrgvoid
61805b261ecSmrgvgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
61905b261ecSmrg{
62035c4bbdfSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
62135c4bbdfSmrg    unsigned char scrn;
62205b261ecSmrg
62335c4bbdfSmrg    scrn = hwp->readSeq(hwp, 0x01);
62405b261ecSmrg
62535c4bbdfSmrg    if (on) {
62635c4bbdfSmrg        scrn &= ~0x20;          /* enable screen */
62735c4bbdfSmrg    }
62835c4bbdfSmrg    else {
62935c4bbdfSmrg        scrn |= 0x20;           /* blank screen */
63035c4bbdfSmrg    }
63105b261ecSmrg
63235c4bbdfSmrg    vgaHWSeqReset(hwp, TRUE);
63335c4bbdfSmrg    hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
63435c4bbdfSmrg    vgaHWSeqReset(hwp, FALSE);
63505b261ecSmrg}
63605b261ecSmrg
63735c4bbdfSmrgvgaHWBlankScreenProc *
63835c4bbdfSmrgvgaHWBlankScreenWeak(void)
63935c4bbdfSmrg{
64035c4bbdfSmrg    return vgaHWBlankScreen;
64135c4bbdfSmrg}
64205b261ecSmrg
64305b261ecSmrg/*
64405b261ecSmrg * vgaHWSaveScreen -- blank the screen.
64505b261ecSmrg */
64605b261ecSmrg
64705b261ecSmrgBool
64805b261ecSmrgvgaHWSaveScreen(ScreenPtr pScreen, int mode)
64905b261ecSmrg{
65035c4bbdfSmrg    ScrnInfoPtr pScrn = NULL;
65135c4bbdfSmrg    Bool on;
65205b261ecSmrg
65335c4bbdfSmrg    if (pScreen != NULL)
65435c4bbdfSmrg        pScrn = xf86ScreenToScrn(pScreen);
65505b261ecSmrg
65635c4bbdfSmrg    on = xf86IsUnblank(mode);
65705b261ecSmrg
65805b261ecSmrg#if 0
65935c4bbdfSmrg    if (on)
66035c4bbdfSmrg        SetTimeSinceLastInputEvent();
66105b261ecSmrg#endif
66205b261ecSmrg
66335c4bbdfSmrg    if ((pScrn != NULL) && pScrn->vtSema) {
66435c4bbdfSmrg        vgaHWBlankScreen(pScrn, on);
66535c4bbdfSmrg    }
66635c4bbdfSmrg    return TRUE;
66705b261ecSmrg}
66805b261ecSmrg
66905b261ecSmrg/*
67005b261ecSmrg * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
67105b261ecSmrg *
67205b261ecSmrg * This generic VGA function can only set the Off and On modes.  If the
67305b261ecSmrg * Standby and Suspend modes are to be supported, a chip specific replacement
67405b261ecSmrg * for this function must be written.
67505b261ecSmrg */
67605b261ecSmrg
67705b261ecSmrgvoid
67805b261ecSmrgvgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
67905b261ecSmrg{
68035c4bbdfSmrg    unsigned char seq1 = 0, crtc17 = 0;
68135c4bbdfSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
68205b261ecSmrg
68335c4bbdfSmrg    if (!pScrn->vtSema)
68435c4bbdfSmrg        return;
68535c4bbdfSmrg
68635c4bbdfSmrg    switch (PowerManagementMode) {
68735c4bbdfSmrg    case DPMSModeOn:
68835c4bbdfSmrg        /* Screen: On; HSync: On, VSync: On */
68935c4bbdfSmrg        seq1 = 0x00;
69035c4bbdfSmrg        crtc17 = 0x80;
69135c4bbdfSmrg        break;
69235c4bbdfSmrg    case DPMSModeStandby:
69335c4bbdfSmrg        /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
69435c4bbdfSmrg        seq1 = 0x20;
69535c4bbdfSmrg        crtc17 = 0x80;
69635c4bbdfSmrg        break;
69735c4bbdfSmrg    case DPMSModeSuspend:
69835c4bbdfSmrg        /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
69935c4bbdfSmrg        seq1 = 0x20;
70035c4bbdfSmrg        crtc17 = 0x80;
70135c4bbdfSmrg        break;
70235c4bbdfSmrg    case DPMSModeOff:
70335c4bbdfSmrg        /* Screen: Off; HSync: Off, VSync: Off */
70435c4bbdfSmrg        seq1 = 0x20;
70535c4bbdfSmrg        crtc17 = 0x00;
70635c4bbdfSmrg        break;
70735c4bbdfSmrg    }
70835c4bbdfSmrg    hwp->writeSeq(hwp, 0x00, 0x01);     /* Synchronous Reset */
70935c4bbdfSmrg    seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
71035c4bbdfSmrg    hwp->writeSeq(hwp, 0x01, seq1);
71135c4bbdfSmrg    crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
71235c4bbdfSmrg    usleep(10000);
71335c4bbdfSmrg    hwp->writeCrtc(hwp, 0x17, crtc17);
71435c4bbdfSmrg    hwp->writeSeq(hwp, 0x00, 0x03);     /* End Reset */
71535c4bbdfSmrg}
71605b261ecSmrg
71705b261ecSmrg/*
71805b261ecSmrg * vgaHWSeqReset
71905b261ecSmrg *      perform a sequencer reset.
72005b261ecSmrg */
72105b261ecSmrg
72205b261ecSmrgvoid
72305b261ecSmrgvgaHWSeqReset(vgaHWPtr hwp, Bool start)
72405b261ecSmrg{
72535c4bbdfSmrg    if (start)
72635c4bbdfSmrg        hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
72735c4bbdfSmrg    else
72835c4bbdfSmrg        hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
72905b261ecSmrg}
73005b261ecSmrg
73105b261ecSmrgvoid
73205b261ecSmrgvgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
73305b261ecSmrg{
73405b261ecSmrg#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
73505b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
73605b261ecSmrg    int savedIOBase;
73705b261ecSmrg    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
73805b261ecSmrg    Bool doMap = FALSE;
73905b261ecSmrg
74005b261ecSmrg    /* If nothing to do, return now */
74105b261ecSmrg    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
74235c4bbdfSmrg        return;
74305b261ecSmrg
74405b261ecSmrg    if (hwp->Base == NULL) {
74535c4bbdfSmrg        doMap = TRUE;
74635c4bbdfSmrg        if (!vgaHWMapMem(scrninfp)) {
74735c4bbdfSmrg            xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
74835c4bbdfSmrg                       "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
74935c4bbdfSmrg            return;
75035c4bbdfSmrg        }
75105b261ecSmrg    }
75205b261ecSmrg
75305b261ecSmrg    /* save the registers that are needed here */
75405b261ecSmrg    miscOut = hwp->readMiscOut(hwp);
75505b261ecSmrg    attr10 = hwp->readAttr(hwp, 0x10);
75605b261ecSmrg    gr1 = hwp->readGr(hwp, 0x01);
75705b261ecSmrg    gr3 = hwp->readGr(hwp, 0x03);
75805b261ecSmrg    gr4 = hwp->readGr(hwp, 0x04);
75905b261ecSmrg    gr5 = hwp->readGr(hwp, 0x05);
76005b261ecSmrg    gr6 = hwp->readGr(hwp, 0x06);
76105b261ecSmrg    gr8 = hwp->readGr(hwp, 0x08);
76205b261ecSmrg    seq2 = hwp->readSeq(hwp, 0x02);
76305b261ecSmrg    seq4 = hwp->readSeq(hwp, 0x04);
76405b261ecSmrg
76505b261ecSmrg    /* save hwp->IOBase and temporarily set it for colour mode */
76605b261ecSmrg    savedIOBase = hwp->IOBase;
76705b261ecSmrg    hwp->IOBase = VGA_IOBASE_COLOR;
76805b261ecSmrg
76905b261ecSmrg    /* Force into colour mode */
77005b261ecSmrg    hwp->writeMiscOut(hwp, miscOut | 0x01);
77105b261ecSmrg
77205b261ecSmrg    vgaHWBlankScreen(scrninfp, FALSE);
77305b261ecSmrg
77405b261ecSmrg    /*
77505b261ecSmrg     * here we temporarily switch to 16 colour planar mode, to simply
77605b261ecSmrg     * copy the font-info and saved text.
77705b261ecSmrg     *
77805b261ecSmrg     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
77905b261ecSmrg     */
78005b261ecSmrg#if 0
78135c4bbdfSmrg    hwp->writeAttr(hwp, 0x10, 0x01);    /* graphics mode */
78205b261ecSmrg#endif
78305b261ecSmrg
78435c4bbdfSmrg    hwp->writeSeq(hwp, 0x04, 0x06);     /* enable plane graphics */
78535c4bbdfSmrg    hwp->writeGr(hwp, 0x05, 0x00);      /* write mode 0, read mode 0 */
78635c4bbdfSmrg    hwp->writeGr(hwp, 0x06, 0x05);      /* set graphics */
78705b261ecSmrg
78805b261ecSmrg    if (scrninfp->depth == 4) {
78935c4bbdfSmrg        /* GJA */
79035c4bbdfSmrg        hwp->writeGr(hwp, 0x03, 0x00);  /* don't rotate, write unmodified */
79135c4bbdfSmrg        hwp->writeGr(hwp, 0x08, 0xFF);  /* write all bits in a byte */
79235c4bbdfSmrg        hwp->writeGr(hwp, 0x01, 0x00);  /* all planes come from CPU */
79305b261ecSmrg    }
79405b261ecSmrg
79505b261ecSmrg#if SAVE_FONT1
79605b261ecSmrg    if (hwp->FontInfo1) {
79735c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
79835c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
79935c4bbdfSmrg        slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
80005b261ecSmrg    }
80105b261ecSmrg#endif
80205b261ecSmrg
80305b261ecSmrg#if SAVE_FONT2
80405b261ecSmrg    if (hwp->FontInfo2) {
80535c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
80635c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
80735c4bbdfSmrg        slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
80805b261ecSmrg    }
80905b261ecSmrg#endif
81005b261ecSmrg
81105b261ecSmrg#if SAVE_TEXT
81205b261ecSmrg    if (hwp->TextInfo) {
81335c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
81435c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
81535c4bbdfSmrg        slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
81635c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
81735c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
81835c4bbdfSmrg        slowbcopy_tobus((unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
81935c4bbdfSmrg                        hwp->Base, TEXT_AMOUNT);
82005b261ecSmrg    }
82105b261ecSmrg#endif
82205b261ecSmrg
82305b261ecSmrg    vgaHWBlankScreen(scrninfp, TRUE);
82405b261ecSmrg
82505b261ecSmrg    /* restore the registers that were changed */
82605b261ecSmrg    hwp->writeMiscOut(hwp, miscOut);
82705b261ecSmrg    hwp->writeAttr(hwp, 0x10, attr10);
82805b261ecSmrg    hwp->writeGr(hwp, 0x01, gr1);
82905b261ecSmrg    hwp->writeGr(hwp, 0x03, gr3);
83005b261ecSmrg    hwp->writeGr(hwp, 0x04, gr4);
83105b261ecSmrg    hwp->writeGr(hwp, 0x05, gr5);
83205b261ecSmrg    hwp->writeGr(hwp, 0x06, gr6);
83305b261ecSmrg    hwp->writeGr(hwp, 0x08, gr8);
83405b261ecSmrg    hwp->writeSeq(hwp, 0x02, seq2);
83505b261ecSmrg    hwp->writeSeq(hwp, 0x04, seq4);
83605b261ecSmrg    hwp->IOBase = savedIOBase;
83705b261ecSmrg
83805b261ecSmrg    if (doMap)
83935c4bbdfSmrg        vgaHWUnmapMem(scrninfp);
84005b261ecSmrg
84135c4bbdfSmrg#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
84205b261ecSmrg}
84305b261ecSmrg
84405b261ecSmrgvoid
84505b261ecSmrgvgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
84605b261ecSmrg{
84705b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
84805b261ecSmrg    int i;
84905b261ecSmrg
85005b261ecSmrg    if (restore->MiscOutReg & 0x01)
85135c4bbdfSmrg        hwp->IOBase = VGA_IOBASE_COLOR;
85205b261ecSmrg    else
85335c4bbdfSmrg        hwp->IOBase = VGA_IOBASE_MONO;
85405b261ecSmrg
85505b261ecSmrg    hwp->writeMiscOut(hwp, restore->MiscOutReg);
85605b261ecSmrg
85705b261ecSmrg    for (i = 1; i < restore->numSequencer; i++)
85835c4bbdfSmrg        hwp->writeSeq(hwp, i, restore->Sequencer[i]);
85935c4bbdfSmrg
86005b261ecSmrg    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
86105b261ecSmrg    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
86205b261ecSmrg
86305b261ecSmrg    for (i = 0; i < restore->numCRTC; i++)
86435c4bbdfSmrg        hwp->writeCrtc(hwp, i, restore->CRTC[i]);
86505b261ecSmrg
86605b261ecSmrg    for (i = 0; i < restore->numGraphics; i++)
86735c4bbdfSmrg        hwp->writeGr(hwp, i, restore->Graphics[i]);
86805b261ecSmrg
86905b261ecSmrg    hwp->enablePalette(hwp);
87005b261ecSmrg    for (i = 0; i < restore->numAttribute; i++)
87135c4bbdfSmrg        hwp->writeAttr(hwp, i, restore->Attribute[i]);
87205b261ecSmrg    hwp->disablePalette(hwp);
87305b261ecSmrg}
87405b261ecSmrg
87505b261ecSmrgvoid
87605b261ecSmrgvgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
87705b261ecSmrg{
87805b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
87905b261ecSmrg    int i;
88005b261ecSmrg
88105b261ecSmrg#if 0
88205b261ecSmrg    hwp->enablePalette(hwp);
88305b261ecSmrg#endif
88405b261ecSmrg
88505b261ecSmrg    hwp->writeDacMask(hwp, 0xFF);
88605b261ecSmrg    hwp->writeDacWriteAddr(hwp, 0x00);
88705b261ecSmrg    for (i = 0; i < 768; i++) {
88835c4bbdfSmrg        hwp->writeDacData(hwp, restore->DAC[i]);
88935c4bbdfSmrg        DACDelay(hwp);
89005b261ecSmrg    }
89105b261ecSmrg
89205b261ecSmrg    hwp->disablePalette(hwp);
89305b261ecSmrg}
89405b261ecSmrg
89505b261ecSmrg/*
89605b261ecSmrg * vgaHWRestore --
89705b261ecSmrg *      restore the VGA state
89805b261ecSmrg */
89905b261ecSmrg
90005b261ecSmrgvoid
90105b261ecSmrgvgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
90205b261ecSmrg{
90305b261ecSmrg    if (flags & VGA_SR_MODE)
90435c4bbdfSmrg        vgaHWRestoreMode(scrninfp, restore);
90505b261ecSmrg
90605b261ecSmrg    if (flags & VGA_SR_FONTS)
90735c4bbdfSmrg        vgaHWRestoreFonts(scrninfp, restore);
90805b261ecSmrg
90905b261ecSmrg    if (flags & VGA_SR_CMAP)
91035c4bbdfSmrg        vgaHWRestoreColormap(scrninfp, restore);
91105b261ecSmrg}
91205b261ecSmrg
91305b261ecSmrgvoid
91405b261ecSmrgvgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
91505b261ecSmrg{
91605b261ecSmrg#if  SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
91705b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
91805b261ecSmrg    int savedIOBase;
91905b261ecSmrg    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
92005b261ecSmrg    Bool doMap = FALSE;
92105b261ecSmrg
92205b261ecSmrg    if (hwp->Base == NULL) {
92335c4bbdfSmrg        doMap = TRUE;
92435c4bbdfSmrg        if (!vgaHWMapMem(scrninfp)) {
92535c4bbdfSmrg            xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
92635c4bbdfSmrg                       "vgaHWSaveFonts: vgaHWMapMem() failed\n");
92735c4bbdfSmrg            return;
92835c4bbdfSmrg        }
92905b261ecSmrg    }
93005b261ecSmrg
93105b261ecSmrg    /* If in graphics mode, don't save anything */
93205b261ecSmrg    attr10 = hwp->readAttr(hwp, 0x10);
93305b261ecSmrg    if (attr10 & 0x01)
93435c4bbdfSmrg        return;
93505b261ecSmrg
93605b261ecSmrg    /* save the registers that are needed here */
93705b261ecSmrg    miscOut = hwp->readMiscOut(hwp);
93805b261ecSmrg    gr4 = hwp->readGr(hwp, 0x04);
93905b261ecSmrg    gr5 = hwp->readGr(hwp, 0x05);
94005b261ecSmrg    gr6 = hwp->readGr(hwp, 0x06);
94105b261ecSmrg    seq2 = hwp->readSeq(hwp, 0x02);
94205b261ecSmrg    seq4 = hwp->readSeq(hwp, 0x04);
94305b261ecSmrg
94405b261ecSmrg    /* save hwp->IOBase and temporarily set it for colour mode */
94505b261ecSmrg    savedIOBase = hwp->IOBase;
94605b261ecSmrg    hwp->IOBase = VGA_IOBASE_COLOR;
94705b261ecSmrg
94805b261ecSmrg    /* Force into colour mode */
94905b261ecSmrg    hwp->writeMiscOut(hwp, miscOut | 0x01);
95005b261ecSmrg
95105b261ecSmrg    vgaHWBlankScreen(scrninfp, FALSE);
95235c4bbdfSmrg
95305b261ecSmrg    /*
95405b261ecSmrg     * get the character sets, and text screen if required
95505b261ecSmrg     */
95605b261ecSmrg    /*
95705b261ecSmrg     * Here we temporarily switch to 16 colour planar mode, to simply
95805b261ecSmrg     * copy the font-info
95905b261ecSmrg     *
96005b261ecSmrg     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
96105b261ecSmrg     */
96205b261ecSmrg#if 0
96335c4bbdfSmrg    hwp->writeAttr(hwp, 0x10, 0x01);    /* graphics mode */
96405b261ecSmrg#endif
96505b261ecSmrg
96635c4bbdfSmrg    hwp->writeSeq(hwp, 0x04, 0x06);     /* enable plane graphics */
96735c4bbdfSmrg    hwp->writeGr(hwp, 0x05, 0x00);      /* write mode 0, read mode 0 */
96835c4bbdfSmrg    hwp->writeGr(hwp, 0x06, 0x05);      /* set graphics */
96905b261ecSmrg
97005b261ecSmrg#if SAVE_FONT1
9716747b715Smrg    if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) {
97235c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
97335c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
97435c4bbdfSmrg        slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
97505b261ecSmrg    }
97635c4bbdfSmrg#endif                          /* SAVE_FONT1 */
97705b261ecSmrg#if SAVE_FONT2
9786747b715Smrg    if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) {
97935c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
98035c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
98135c4bbdfSmrg        slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
98205b261ecSmrg    }
98335c4bbdfSmrg#endif                          /* SAVE_FONT2 */
98405b261ecSmrg#if SAVE_TEXT
9856747b715Smrg    if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) {
98635c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
98735c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
98835c4bbdfSmrg        slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
98935c4bbdfSmrg        hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
99035c4bbdfSmrg        hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
99135c4bbdfSmrg        slowbcopy_frombus(hwp->Base,
99235c4bbdfSmrg                          (unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
99335c4bbdfSmrg                          TEXT_AMOUNT);
99405b261ecSmrg    }
99535c4bbdfSmrg#endif                          /* SAVE_TEXT */
99605b261ecSmrg
99705b261ecSmrg    /* Restore clobbered registers */
99805b261ecSmrg    hwp->writeAttr(hwp, 0x10, attr10);
99905b261ecSmrg    hwp->writeSeq(hwp, 0x02, seq2);
100005b261ecSmrg    hwp->writeSeq(hwp, 0x04, seq4);
100105b261ecSmrg    hwp->writeGr(hwp, 0x04, gr4);
100205b261ecSmrg    hwp->writeGr(hwp, 0x05, gr5);
100305b261ecSmrg    hwp->writeGr(hwp, 0x06, gr6);
100405b261ecSmrg    hwp->writeMiscOut(hwp, miscOut);
100505b261ecSmrg    hwp->IOBase = savedIOBase;
100605b261ecSmrg
100705b261ecSmrg    vgaHWBlankScreen(scrninfp, TRUE);
100805b261ecSmrg
100905b261ecSmrg    if (doMap)
101035c4bbdfSmrg        vgaHWUnmapMem(scrninfp);
101105b261ecSmrg
101235c4bbdfSmrg#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
101305b261ecSmrg}
101405b261ecSmrg
101505b261ecSmrgvoid
101605b261ecSmrgvgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
101705b261ecSmrg{
101805b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
101905b261ecSmrg    int i;
102005b261ecSmrg
102105b261ecSmrg    save->MiscOutReg = hwp->readMiscOut(hwp);
102205b261ecSmrg    if (save->MiscOutReg & 0x01)
102335c4bbdfSmrg        hwp->IOBase = VGA_IOBASE_COLOR;
102405b261ecSmrg    else
102535c4bbdfSmrg        hwp->IOBase = VGA_IOBASE_MONO;
102605b261ecSmrg
102705b261ecSmrg    for (i = 0; i < save->numCRTC; i++) {
102835c4bbdfSmrg        save->CRTC[i] = hwp->readCrtc(hwp, i);
102935c4bbdfSmrg        DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
103005b261ecSmrg    }
103105b261ecSmrg
103205b261ecSmrg    hwp->enablePalette(hwp);
103305b261ecSmrg    for (i = 0; i < save->numAttribute; i++) {
103435c4bbdfSmrg        save->Attribute[i] = hwp->readAttr(hwp, i);
103535c4bbdfSmrg        DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
103605b261ecSmrg    }
103705b261ecSmrg    hwp->disablePalette(hwp);
103805b261ecSmrg
103905b261ecSmrg    for (i = 0; i < save->numGraphics; i++) {
104035c4bbdfSmrg        save->Graphics[i] = hwp->readGr(hwp, i);
104135c4bbdfSmrg        DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
104205b261ecSmrg    }
104305b261ecSmrg
104405b261ecSmrg    for (i = 1; i < save->numSequencer; i++) {
104535c4bbdfSmrg        save->Sequencer[i] = hwp->readSeq(hwp, i);
104635c4bbdfSmrg        DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
104705b261ecSmrg    }
104805b261ecSmrg}
104905b261ecSmrg
105005b261ecSmrgvoid
105105b261ecSmrgvgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
105205b261ecSmrg{
105305b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
105405b261ecSmrg    Bool readError = FALSE;
105505b261ecSmrg    int i;
105605b261ecSmrg
105705b261ecSmrg#ifdef NEED_SAVED_CMAP
105805b261ecSmrg    /*
105905b261ecSmrg     * Some ET4000 chips from 1991 have a HW bug that prevents the reading
106005b261ecSmrg     * of the color lookup table.  Mask rev 9042EAI is known to have this bug.
106105b261ecSmrg     *
106205b261ecSmrg     * If the colourmap is not readable, we set the saved map to a default
106305b261ecSmrg     * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
106405b261ecSmrg     * Cards" 2nd ed).
106505b261ecSmrg     */
106605b261ecSmrg
106705b261ecSmrg    /* Only save it once */
106805b261ecSmrg    if (hwp->cmapSaved)
106935c4bbdfSmrg        return;
107005b261ecSmrg
107105b261ecSmrg#if 0
107205b261ecSmrg    hwp->enablePalette(hwp);
107305b261ecSmrg#endif
107405b261ecSmrg
107505b261ecSmrg    hwp->writeDacMask(hwp, 0xFF);
107605b261ecSmrg
107705b261ecSmrg    /*
107805b261ecSmrg     * check if we can read the lookup table
107905b261ecSmrg     */
108005b261ecSmrg    hwp->writeDacReadAddr(hwp, 0x00);
108105b261ecSmrg    for (i = 0; i < 6; i++) {
108235c4bbdfSmrg        save->DAC[i] = hwp->readDacData(hwp);
108335c4bbdfSmrg        switch (i % 3) {
108435c4bbdfSmrg        case 0:
108535c4bbdfSmrg            DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
108635c4bbdfSmrg            break;
108735c4bbdfSmrg        case 1:
108835c4bbdfSmrg            DebugF("0x%02x, ", save->DAC[i]);
108935c4bbdfSmrg            break;
109035c4bbdfSmrg        case 2:
109135c4bbdfSmrg            DebugF("0x%02x\n", save->DAC[i]);
109235c4bbdfSmrg        }
109305b261ecSmrg    }
109405b261ecSmrg
109505b261ecSmrg    /*
109605b261ecSmrg     * Check if we can read the palette -
109705b261ecSmrg     * use foreground color to prevent flashing.
109805b261ecSmrg     */
109905b261ecSmrg    hwp->writeDacWriteAddr(hwp, 0x01);
110005b261ecSmrg    for (i = 3; i < 6; i++)
110135c4bbdfSmrg        hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
110205b261ecSmrg    hwp->writeDacReadAddr(hwp, 0x01);
110305b261ecSmrg    for (i = 3; i < 6; i++) {
110435c4bbdfSmrg        if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
110535c4bbdfSmrg            readError = TRUE;
110605b261ecSmrg    }
110705b261ecSmrg    hwp->writeDacWriteAddr(hwp, 0x01);
110805b261ecSmrg    for (i = 3; i < 6; i++)
110935c4bbdfSmrg        hwp->writeDacData(hwp, save->DAC[i]);
111005b261ecSmrg
111105b261ecSmrg    if (readError) {
111235c4bbdfSmrg        /*
111335c4bbdfSmrg         * save the default lookup table
111435c4bbdfSmrg         */
111535c4bbdfSmrg        memmove(save->DAC, defaultDAC, 768);
111635c4bbdfSmrg        xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
111735c4bbdfSmrg                   "Cannot read colourmap from VGA.  Will restore with default\n");
111835c4bbdfSmrg    }
111935c4bbdfSmrg    else {
112035c4bbdfSmrg        /* save the colourmap */
112135c4bbdfSmrg        hwp->writeDacReadAddr(hwp, 0x02);
112235c4bbdfSmrg        for (i = 6; i < 768; i++) {
112335c4bbdfSmrg            save->DAC[i] = hwp->readDacData(hwp);
112435c4bbdfSmrg            DACDelay(hwp);
112535c4bbdfSmrg            switch (i % 3) {
112635c4bbdfSmrg            case 0:
112735c4bbdfSmrg                DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
112835c4bbdfSmrg                break;
112935c4bbdfSmrg            case 1:
113035c4bbdfSmrg                DebugF("0x%02x, ", save->DAC[i]);
113135c4bbdfSmrg                break;
113235c4bbdfSmrg            case 2:
113335c4bbdfSmrg                DebugF("0x%02x\n", save->DAC[i]);
113435c4bbdfSmrg            }
113535c4bbdfSmrg        }
113605b261ecSmrg    }
113705b261ecSmrg
113805b261ecSmrg    hwp->disablePalette(hwp);
113905b261ecSmrg    hwp->cmapSaved = TRUE;
114005b261ecSmrg#endif
114105b261ecSmrg}
114205b261ecSmrg
114305b261ecSmrg/*
114405b261ecSmrg * vgaHWSave --
114505b261ecSmrg *      save the current VGA state
114605b261ecSmrg */
114705b261ecSmrg
114805b261ecSmrgvoid
114905b261ecSmrgvgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
115005b261ecSmrg{
115105b261ecSmrg    if (save == NULL)
115235c4bbdfSmrg        return;
115305b261ecSmrg
115435c4bbdfSmrg    if (flags & VGA_SR_CMAP)
115535c4bbdfSmrg        vgaHWSaveColormap(scrninfp, save);
115605b261ecSmrg
115735c4bbdfSmrg    if (flags & VGA_SR_MODE)
115835c4bbdfSmrg        vgaHWSaveMode(scrninfp, save);
115905b261ecSmrg
116035c4bbdfSmrg    if (flags & VGA_SR_FONTS)
116135c4bbdfSmrg        vgaHWSaveFonts(scrninfp, save);
116205b261ecSmrg}
116305b261ecSmrg
116405b261ecSmrg/*
116505b261ecSmrg * vgaHWInit --
116605b261ecSmrg *      Handle the initialization, etc. of a screen.
116705b261ecSmrg *      Return FALSE on failure.
116805b261ecSmrg */
116905b261ecSmrg
117005b261ecSmrgBool
117105b261ecSmrgvgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
117205b261ecSmrg{
117335c4bbdfSmrg    unsigned int i;
117405b261ecSmrg    vgaHWPtr hwp;
117505b261ecSmrg    vgaRegPtr regp;
117605b261ecSmrg    int depth = scrninfp->depth;
117705b261ecSmrg
117805b261ecSmrg    /*
117905b261ecSmrg     * make sure the vgaHWRec is allocated
118005b261ecSmrg     */
118105b261ecSmrg    if (!vgaHWGetHWRec(scrninfp))
118235c4bbdfSmrg        return FALSE;
118305b261ecSmrg    hwp = VGAHWPTR(scrninfp);
118405b261ecSmrg    regp = &hwp->ModeReg;
118535c4bbdfSmrg
118605b261ecSmrg    /*
118735c4bbdfSmrg     * compute correct Hsync & Vsync polarity
118805b261ecSmrg     */
118905b261ecSmrg    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
119035c4bbdfSmrg        && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
119105b261ecSmrg        regp->MiscOutReg = 0x23;
119235c4bbdfSmrg        if (mode->Flags & V_NHSYNC)
119335c4bbdfSmrg            regp->MiscOutReg |= 0x40;
119435c4bbdfSmrg        if (mode->Flags & V_NVSYNC)
119535c4bbdfSmrg            regp->MiscOutReg |= 0x80;
119605b261ecSmrg    }
119735c4bbdfSmrg    else {
119805b261ecSmrg        int VDisplay = mode->VDisplay;
119935c4bbdfSmrg
120005b261ecSmrg        if (mode->Flags & V_DBLSCAN)
120105b261ecSmrg            VDisplay *= 2;
120205b261ecSmrg        if (mode->VScan > 1)
120305b261ecSmrg            VDisplay *= mode->VScan;
120435c4bbdfSmrg        if (VDisplay < 400)
120535c4bbdfSmrg            regp->MiscOutReg = 0xA3;    /* +hsync -vsync */
120605b261ecSmrg        else if (VDisplay < 480)
120735c4bbdfSmrg            regp->MiscOutReg = 0x63;    /* -hsync +vsync */
120805b261ecSmrg        else if (VDisplay < 768)
120935c4bbdfSmrg            regp->MiscOutReg = 0xE3;    /* -hsync -vsync */
121005b261ecSmrg        else
121135c4bbdfSmrg            regp->MiscOutReg = 0x23;    /* +hsync +vsync */
121205b261ecSmrg    }
121335c4bbdfSmrg
121405b261ecSmrg    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
121505b261ecSmrg
121605b261ecSmrg    /*
121705b261ecSmrg     * Time Sequencer
121805b261ecSmrg     */
121905b261ecSmrg    if (depth == 4)
122005b261ecSmrg        regp->Sequencer[0] = 0x02;
122105b261ecSmrg    else
122205b261ecSmrg        regp->Sequencer[0] = 0x00;
122335c4bbdfSmrg    if (mode->Flags & V_CLKDIV2)
122405b261ecSmrg        regp->Sequencer[1] = 0x09;
122505b261ecSmrg    else
122605b261ecSmrg        regp->Sequencer[1] = 0x01;
122705b261ecSmrg    if (depth == 1)
122805b261ecSmrg        regp->Sequencer[2] = 1 << BIT_PLANE;
122905b261ecSmrg    else
123005b261ecSmrg        regp->Sequencer[2] = 0x0F;
123135c4bbdfSmrg    regp->Sequencer[3] = 0x00;  /* Font select */
123205b261ecSmrg    if (depth < 8)
123335c4bbdfSmrg        regp->Sequencer[4] = 0x06;      /* Misc */
123405b261ecSmrg    else
123535c4bbdfSmrg        regp->Sequencer[4] = 0x0E;      /* Misc */
123605b261ecSmrg
123705b261ecSmrg    /*
123805b261ecSmrg     * CRTC Controller
123905b261ecSmrg     */
124035c4bbdfSmrg    regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5;
124135c4bbdfSmrg    regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1;
124235c4bbdfSmrg    regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1;
124335c4bbdfSmrg    regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
124405b261ecSmrg    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
124505b261ecSmrg    if (i < 0x80)
124635c4bbdfSmrg        regp->CRTC[3] |= i;
124735c4bbdfSmrg    regp->CRTC[4] = (mode->CrtcHSyncStart >> 3);
124835c4bbdfSmrg    regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
124935c4bbdfSmrg        | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
125035c4bbdfSmrg    regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF;
125135c4bbdfSmrg    regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
125235c4bbdfSmrg        | (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
125335c4bbdfSmrg        | ((mode->CrtcVSyncStart & 0x100) >> 6)
125435c4bbdfSmrg        | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
125535c4bbdfSmrg        | 0x10 | (((mode->CrtcVTotal - 2) & 0x200) >> 4)
125635c4bbdfSmrg        | (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
125735c4bbdfSmrg        | ((mode->CrtcVSyncStart & 0x200) >> 2);
125835c4bbdfSmrg    regp->CRTC[8] = 0x00;
125935c4bbdfSmrg    regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
126005b261ecSmrg    if (mode->Flags & V_DBLSCAN)
126135c4bbdfSmrg        regp->CRTC[9] |= 0x80;
126205b261ecSmrg    if (mode->VScan >= 32)
126335c4bbdfSmrg        regp->CRTC[9] |= 0x1F;
126405b261ecSmrg    else if (mode->VScan > 1)
126535c4bbdfSmrg        regp->CRTC[9] |= mode->VScan - 1;
126605b261ecSmrg    regp->CRTC[10] = 0x00;
126705b261ecSmrg    regp->CRTC[11] = 0x00;
126805b261ecSmrg    regp->CRTC[12] = 0x00;
126905b261ecSmrg    regp->CRTC[13] = 0x00;
127005b261ecSmrg    regp->CRTC[14] = 0x00;
127105b261ecSmrg    regp->CRTC[15] = 0x00;
127205b261ecSmrg    regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
127305b261ecSmrg    regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
127405b261ecSmrg    regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
127535c4bbdfSmrg    regp->CRTC[19] = scrninfp->displayWidth >> 4;       /* just a guess */
127605b261ecSmrg    regp->CRTC[20] = 0x00;
127735c4bbdfSmrg    regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
127805b261ecSmrg    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
127905b261ecSmrg    if (depth < 8)
128035c4bbdfSmrg        regp->CRTC[23] = 0xE3;
128105b261ecSmrg    else
128235c4bbdfSmrg        regp->CRTC[23] = 0xC3;
128305b261ecSmrg    regp->CRTC[24] = 0xFF;
128405b261ecSmrg
128505b261ecSmrg    vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
128605b261ecSmrg    vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
128705b261ecSmrg
128805b261ecSmrg    /*
128905b261ecSmrg     * Theory resumes here....
129005b261ecSmrg     */
129105b261ecSmrg
129205b261ecSmrg    /*
129305b261ecSmrg     * Graphics Display Controller
129405b261ecSmrg     */
129505b261ecSmrg    regp->Graphics[0] = 0x00;
129605b261ecSmrg    regp->Graphics[1] = 0x00;
129705b261ecSmrg    regp->Graphics[2] = 0x00;
129805b261ecSmrg    regp->Graphics[3] = 0x00;
129905b261ecSmrg    if (depth == 1) {
130005b261ecSmrg        regp->Graphics[4] = BIT_PLANE;
130105b261ecSmrg        regp->Graphics[5] = 0x00;
130235c4bbdfSmrg    }
130335c4bbdfSmrg    else {
130405b261ecSmrg        regp->Graphics[4] = 0x00;
130505b261ecSmrg        if (depth == 4)
130605b261ecSmrg            regp->Graphics[5] = 0x02;
130705b261ecSmrg        else
130805b261ecSmrg            regp->Graphics[5] = 0x40;
130905b261ecSmrg    }
131005b261ecSmrg    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
131105b261ecSmrg    regp->Graphics[7] = 0x0F;
131205b261ecSmrg    regp->Graphics[8] = 0xFF;
131335c4bbdfSmrg
131405b261ecSmrg    if (depth == 1) {
131505b261ecSmrg        /* Initialise the Mono map according to which bit-plane gets used */
131605b261ecSmrg
13179b06bd19Stsutsui        Bool flipPixels = xf86GetFlipPixels();
13189b06bd19Stsutsui
131935c4bbdfSmrg        for (i = 0; i < 16; i++)
13209b06bd19Stsutsui            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
132105b261ecSmrg                regp->Attribute[i] = WHITE_VALUE;
132205b261ecSmrg            else
132305b261ecSmrg                regp->Attribute[i] = BLACK_VALUE;
132405b261ecSmrg
132535c4bbdfSmrg        regp->Attribute[16] = 0x01;     /* -VGA2- *//* wrong for the ET4000 */
132635c4bbdfSmrg        if (!hwp->ShowOverscan)
132735c4bbdfSmrg            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
132835c4bbdfSmrg    }
132935c4bbdfSmrg    else {
133035c4bbdfSmrg        regp->Attribute[0] = 0x00;      /* standard colormap translation */
133135c4bbdfSmrg        regp->Attribute[1] = 0x01;
133235c4bbdfSmrg        regp->Attribute[2] = 0x02;
133335c4bbdfSmrg        regp->Attribute[3] = 0x03;
133435c4bbdfSmrg        regp->Attribute[4] = 0x04;
133535c4bbdfSmrg        regp->Attribute[5] = 0x05;
133635c4bbdfSmrg        regp->Attribute[6] = 0x06;
133735c4bbdfSmrg        regp->Attribute[7] = 0x07;
133835c4bbdfSmrg        regp->Attribute[8] = 0x08;
133935c4bbdfSmrg        regp->Attribute[9] = 0x09;
134005b261ecSmrg        regp->Attribute[10] = 0x0A;
134105b261ecSmrg        regp->Attribute[11] = 0x0B;
134205b261ecSmrg        regp->Attribute[12] = 0x0C;
134305b261ecSmrg        regp->Attribute[13] = 0x0D;
134405b261ecSmrg        regp->Attribute[14] = 0x0E;
134505b261ecSmrg        regp->Attribute[15] = 0x0F;
134605b261ecSmrg        if (depth == 4)
134705b261ecSmrg            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
134805b261ecSmrg        else
134905b261ecSmrg            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
135005b261ecSmrg        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
135105b261ecSmrg    }
135205b261ecSmrg    regp->Attribute[18] = 0x0F;
135305b261ecSmrg    regp->Attribute[19] = 0x00;
135405b261ecSmrg    regp->Attribute[20] = 0x00;
135505b261ecSmrg
13566747b715Smrg    return TRUE;
135705b261ecSmrg}
135805b261ecSmrg
135905b261ecSmrg    /*
136005b261ecSmrg     * OK, so much for theory.  Now, let's deal with the >real< world...
136105b261ecSmrg     *
136205b261ecSmrg     * The above CRTC settings are precise in theory, except that many, if not
136305b261ecSmrg     * most, VGA clones fail to reset the blanking signal when the character or
136405b261ecSmrg     * line counter reaches [HV]Total.  In this case, the signal is only
136505b261ecSmrg     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
136605b261ecSmrg     * the case may be) at the start of the >next< scanline or frame, which
136705b261ecSmrg     * means only part of the screen shows.  This affects how null overscans
136805b261ecSmrg     * are to be implemented on such adapters.
136905b261ecSmrg     *
137005b261ecSmrg     * Henceforth, VGA cores that implement this broken, but unfortunately
137105b261ecSmrg     * common, behaviour are to be designated as KGA's, in honour of Koen
137205b261ecSmrg     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
137305b261ecSmrg     * a series of events that led to the discovery of this problem.
137405b261ecSmrg     *
137505b261ecSmrg     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
137605b261ecSmrg     * some in both, others in neither.  Don't let anyone tell you there is
137705b261ecSmrg     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
137805b261ecSmrg     * that Hilbert spaces are not yet implemented in this industry.
137905b261ecSmrg     *
138005b261ecSmrg     * The following implements a trick suggested by David Dawes.  This sets
138105b261ecSmrg     * [HV]BlankEnd to zero if the blanking interval does not already contain a
138205b261ecSmrg     * 0-point, and decrements it by one otherwise.  In the latter case, this
138305b261ecSmrg     * will produce a left and/or top overscan which the colourmap code will
138405b261ecSmrg     * (still) need to ensure is as close to black as possible.  This will make
138505b261ecSmrg     * the behaviour consistent across all chipsets, while allowing all
138605b261ecSmrg     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
138705b261ecSmrg     * following in their own copy of this code.
138805b261ecSmrg     *
138905b261ecSmrg     * --  TSI @ UQV,  1998.08.21
139005b261ecSmrg     */
139105b261ecSmrg
139205b261ecSmrgCARD32
139335c4bbdfSmrgvgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
139435c4bbdfSmrg               unsigned int Flags)
139505b261ecSmrg{
139605b261ecSmrg    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
139705b261ecSmrg    CARD32 ExtBits;
139805b261ecSmrg    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
139905b261ecSmrg
140035c4bbdfSmrg    regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
140135c4bbdfSmrg        | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
140235c4bbdfSmrg    regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
140335c4bbdfSmrg        | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
140435c4bbdfSmrg    ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
140505b261ecSmrg
140605b261ecSmrg    /* First the horizontal case */
140705b261ecSmrg    if ((Flags & KGA_FIX_OVERSCAN)
140835c4bbdfSmrg        && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
140935c4bbdfSmrg        int i = (regp->CRTC[3] & 0x1F)
141035c4bbdfSmrg            | ((regp->CRTC[5] & 0x80) >> 2)
141135c4bbdfSmrg            | ExtBits;
141235c4bbdfSmrg
141335c4bbdfSmrg        if (Flags & KGA_ENABLE_ON_ZERO) {
141435c4bbdfSmrg            if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
141535c4bbdfSmrg                        & (0x3F | ExtBitMask)))
141635c4bbdfSmrg                && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
141735c4bbdfSmrg                i = 0;
141835c4bbdfSmrg        }
141935c4bbdfSmrg        else if (Flags & KGA_BE_TOT_DEC)
142035c4bbdfSmrg            i--;
142135c4bbdfSmrg        regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
142235c4bbdfSmrg        regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
142335c4bbdfSmrg        ExtBits = i & ExtBitMask;
142405b261ecSmrg    }
142505b261ecSmrg    return ExtBits >> 6;
142605b261ecSmrg}
142705b261ecSmrg
142805b261ecSmrg    /*
142905b261ecSmrg     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
143005b261ecSmrg     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
143105b261ecSmrg     * very first scanline in a double- or multi-scanned mode.  This last case
143205b261ecSmrg     * needs further investigation.
143305b261ecSmrg     */
143405b261ecSmrgCARD32
143535c4bbdfSmrgvgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
143635c4bbdfSmrg               unsigned int Flags)
143705b261ecSmrg{
143805b261ecSmrg    CARD32 ExtBits;
143905b261ecSmrg    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
144005b261ecSmrg    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
144135c4bbdfSmrg
144235c4bbdfSmrg    /* If width is not known nBits should be 0. In this
144305b261ecSmrg     * case BitMask is set to 0 so we can check for it. */
144405b261ecSmrg    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
144535c4bbdfSmrg    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
144635c4bbdfSmrg
144705b261ecSmrg    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
144835c4bbdfSmrg    ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
144905b261ecSmrg
145035c4bbdfSmrg    if ((Flags & KGA_FIX_OVERSCAN)
145135c4bbdfSmrg        && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
145235c4bbdfSmrg        /* Null top overscan */
145305b261ecSmrg    {
145435c4bbdfSmrg        int i = regp->CRTC[22] | ExtBits;
145535c4bbdfSmrg
145635c4bbdfSmrg        if (Flags & KGA_ENABLE_ON_ZERO) {
145735c4bbdfSmrg            if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
145835c4bbdfSmrg                 || ((i > VBlankStart) &&       /* 8-bit case */
145935c4bbdfSmrg                     ((i & 0x7F) > (VBlankStart & 0x7F)))) &&   /* 7-bit case */
146035c4bbdfSmrg                !(regp->CRTC[9] & 0x9F))        /* 1 scanline/row */
146135c4bbdfSmrg                i = 0;
146235c4bbdfSmrg            else
146335c4bbdfSmrg                i = (i - 1);
146435c4bbdfSmrg        }
146535c4bbdfSmrg        else if (Flags & KGA_BE_TOT_DEC)
146635c4bbdfSmrg            i = (i - 1);
146735c4bbdfSmrg
146835c4bbdfSmrg        regp->CRTC[22] = i & 0xFF;
146935c4bbdfSmrg        ExtBits = i & 0xFF00;
147005b261ecSmrg    }
147105b261ecSmrg    return ExtBits >> 8;
147205b261ecSmrg}
147305b261ecSmrg
147405b261ecSmrg/*
147505b261ecSmrg * these are some more hardware specific helpers, formerly in vga.c
147605b261ecSmrg */
147705b261ecSmrgstatic void
147805b261ecSmrgvgaHWGetHWRecPrivate(void)
147905b261ecSmrg{
148005b261ecSmrg    if (vgaHWPrivateIndex < 0)
148135c4bbdfSmrg        vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
148205b261ecSmrg    return;
148305b261ecSmrg}
148405b261ecSmrg
148505b261ecSmrgstatic void
148605b261ecSmrgvgaHWFreeRegs(vgaRegPtr regp)
148705b261ecSmrg{
14886747b715Smrg    free(regp->CRTC);
148905b261ecSmrg
149035c4bbdfSmrg    regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
149105b261ecSmrg
149205b261ecSmrg    regp->numCRTC =
149335c4bbdfSmrg        regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
149405b261ecSmrg}
149505b261ecSmrg
149605b261ecSmrgstatic Bool
149705b261ecSmrgvgaHWAllocRegs(vgaRegPtr regp)
149805b261ecSmrg{
149905b261ecSmrg    unsigned char *buf;
150005b261ecSmrg
150105b261ecSmrg    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
150205b261ecSmrg         regp->numAttribute) == 0)
150305b261ecSmrg        return FALSE;
150405b261ecSmrg
15056747b715Smrg    buf = calloc(regp->numCRTC +
150635c4bbdfSmrg                 regp->numSequencer +
150735c4bbdfSmrg                 regp->numGraphics + regp->numAttribute, 1);
150805b261ecSmrg    if (!buf)
150935c4bbdfSmrg        return FALSE;
151005b261ecSmrg
151105b261ecSmrg    regp->CRTC = buf;
151205b261ecSmrg    regp->Sequencer = regp->CRTC + regp->numCRTC;
151305b261ecSmrg    regp->Graphics = regp->Sequencer + regp->numSequencer;
151405b261ecSmrg    regp->Attribute = regp->Graphics + regp->numGraphics;
151505b261ecSmrg
151605b261ecSmrg    return TRUE;
151705b261ecSmrg}
151805b261ecSmrg
151905b261ecSmrgBool
152005b261ecSmrgvgaHWAllocDefaultRegs(vgaRegPtr regp)
152105b261ecSmrg{
152205b261ecSmrg    regp->numCRTC = VGA_NUM_CRTC;
152305b261ecSmrg    regp->numSequencer = VGA_NUM_SEQ;
152405b261ecSmrg    regp->numGraphics = VGA_NUM_GFX;
152505b261ecSmrg    regp->numAttribute = VGA_NUM_ATTR;
152605b261ecSmrg
152705b261ecSmrg    return vgaHWAllocRegs(regp);
152805b261ecSmrg}
152905b261ecSmrg
153005b261ecSmrgBool
153105b261ecSmrgvgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
153235c4bbdfSmrg                  int numGraphics, int numAttribute)
153305b261ecSmrg{
153405b261ecSmrg#define VGAHWMINNUM(regtype) \
153505b261ecSmrg	((newMode.num##regtype < regp->num##regtype) ? \
153605b261ecSmrg	 (newMode.num##regtype) : (regp->num##regtype))
153705b261ecSmrg#define VGAHWCOPYREGSET(regtype) \
153805b261ecSmrg	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
153905b261ecSmrg
154005b261ecSmrg    vgaRegRec newMode, newSaved;
154105b261ecSmrg    vgaRegPtr regp;
154205b261ecSmrg
154305b261ecSmrg    regp = &VGAHWPTR(scrp)->ModeReg;
154435c4bbdfSmrg    memcpy(&newMode, regp, sizeof(vgaRegRec));
154505b261ecSmrg
154605b261ecSmrg    /* allocate space for new registers */
154705b261ecSmrg
154805b261ecSmrg    regp = &newMode;
154905b261ecSmrg    regp->numCRTC = numCRTC;
155005b261ecSmrg    regp->numSequencer = numSequencer;
155105b261ecSmrg    regp->numGraphics = numGraphics;
155205b261ecSmrg    regp->numAttribute = numAttribute;
155305b261ecSmrg    if (!vgaHWAllocRegs(regp))
155435c4bbdfSmrg        return FALSE;
155505b261ecSmrg
155605b261ecSmrg    regp = &VGAHWPTR(scrp)->SavedReg;
155735c4bbdfSmrg    memcpy(&newSaved, regp, sizeof(vgaRegRec));
155805b261ecSmrg
155905b261ecSmrg    regp = &newSaved;
156005b261ecSmrg    regp->numCRTC = numCRTC;
156105b261ecSmrg    regp->numSequencer = numSequencer;
156205b261ecSmrg    regp->numGraphics = numGraphics;
156305b261ecSmrg    regp->numAttribute = numAttribute;
156405b261ecSmrg    if (!vgaHWAllocRegs(regp)) {
156505b261ecSmrg        vgaHWFreeRegs(&newMode);
156635c4bbdfSmrg        return FALSE;
156705b261ecSmrg    }
156805b261ecSmrg
156905b261ecSmrg    /* allocations succeeded, copy register data into new space */
157005b261ecSmrg
157105b261ecSmrg    regp = &VGAHWPTR(scrp)->ModeReg;
157205b261ecSmrg    VGAHWCOPYREGSET(CRTC);
157305b261ecSmrg    VGAHWCOPYREGSET(Sequencer);
157405b261ecSmrg    VGAHWCOPYREGSET(Graphics);
157505b261ecSmrg    VGAHWCOPYREGSET(Attribute);
157605b261ecSmrg
157705b261ecSmrg    regp = &VGAHWPTR(scrp)->SavedReg;
157805b261ecSmrg    VGAHWCOPYREGSET(CRTC);
157905b261ecSmrg    VGAHWCOPYREGSET(Sequencer);
158005b261ecSmrg    VGAHWCOPYREGSET(Graphics);
158105b261ecSmrg    VGAHWCOPYREGSET(Attribute);
158205b261ecSmrg
158305b261ecSmrg    /* free old register arrays */
158405b261ecSmrg
158505b261ecSmrg    regp = &VGAHWPTR(scrp)->ModeReg;
158605b261ecSmrg    vgaHWFreeRegs(regp);
158705b261ecSmrg    memcpy(regp, &newMode, sizeof(vgaRegRec));
158805b261ecSmrg
158905b261ecSmrg    regp = &VGAHWPTR(scrp)->SavedReg;
159005b261ecSmrg    vgaHWFreeRegs(regp);
159105b261ecSmrg    memcpy(regp, &newSaved, sizeof(vgaRegRec));
159205b261ecSmrg
159305b261ecSmrg    return TRUE;
159405b261ecSmrg
159505b261ecSmrg#undef VGAHWMINNUM
159605b261ecSmrg#undef VGAHWCOPYREGSET
159705b261ecSmrg}
159805b261ecSmrg
159905b261ecSmrgBool
160005b261ecSmrgvgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
160105b261ecSmrg{
160205b261ecSmrg    vgaHWFreeRegs(dst);
160305b261ecSmrg
160405b261ecSmrg    memcpy(dst, src, sizeof(vgaRegRec));
160505b261ecSmrg
160605b261ecSmrg    if (!vgaHWAllocRegs(dst))
160735c4bbdfSmrg        return FALSE;
160805b261ecSmrg
160905b261ecSmrg    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
161005b261ecSmrg    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
161105b261ecSmrg    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
161205b261ecSmrg    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
161305b261ecSmrg
161405b261ecSmrg    return TRUE;
161505b261ecSmrg}
161605b261ecSmrg
161705b261ecSmrgBool
161805b261ecSmrgvgaHWGetHWRec(ScrnInfoPtr scrp)
161905b261ecSmrg{
162005b261ecSmrg    vgaRegPtr regp;
162105b261ecSmrg    vgaHWPtr hwp;
162205b261ecSmrg    int i;
162335c4bbdfSmrg
162405b261ecSmrg    /*
162505b261ecSmrg     * Let's make sure that the private exists and allocate one.
162605b261ecSmrg     */
162705b261ecSmrg    vgaHWGetHWRecPrivate();
162805b261ecSmrg    /*
162905b261ecSmrg     * New privates are always set to NULL, so we can check if the allocation
163005b261ecSmrg     * has already been done.
163105b261ecSmrg     */
163205b261ecSmrg    if (VGAHWPTR(scrp))
163335c4bbdfSmrg        return TRUE;
163405b261ecSmrg    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
163505b261ecSmrg    regp = &VGAHWPTR(scrp)->ModeReg;
163605b261ecSmrg
163705b261ecSmrg    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
163835c4bbdfSmrg        (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
16396747b715Smrg        free(hwp);
164035c4bbdfSmrg        return FALSE;
164105b261ecSmrg    }
164205b261ecSmrg
164305b261ecSmrg    if (scrp->bitsPerPixel == 1) {
164435c4bbdfSmrg        rgb blackColour = scrp->display->blackColour,
164535c4bbdfSmrg            whiteColour = scrp->display->whiteColour;
164635c4bbdfSmrg
164735c4bbdfSmrg        if (blackColour.red > 0x3F)
164835c4bbdfSmrg            blackColour.red = 0x3F;
164935c4bbdfSmrg        if (blackColour.green > 0x3F)
165035c4bbdfSmrg            blackColour.green = 0x3F;
165135c4bbdfSmrg        if (blackColour.blue > 0x3F)
165235c4bbdfSmrg            blackColour.blue = 0x3F;
165335c4bbdfSmrg
165435c4bbdfSmrg        if (whiteColour.red > 0x3F)
165535c4bbdfSmrg            whiteColour.red = 0x3F;
165635c4bbdfSmrg        if (whiteColour.green > 0x3F)
165735c4bbdfSmrg            whiteColour.green = 0x3F;
165835c4bbdfSmrg        if (whiteColour.blue > 0x3F)
165935c4bbdfSmrg            whiteColour.blue = 0x3F;
166035c4bbdfSmrg
166135c4bbdfSmrg        if ((blackColour.red == whiteColour.red) &&
166235c4bbdfSmrg            (blackColour.green == whiteColour.green) &&
166335c4bbdfSmrg            (blackColour.blue == whiteColour.blue)) {
166435c4bbdfSmrg            blackColour.red ^= 0x3F;
166535c4bbdfSmrg            blackColour.green ^= 0x3F;
166635c4bbdfSmrg            blackColour.blue ^= 0x3F;
166735c4bbdfSmrg        }
166805b261ecSmrg
166905b261ecSmrg        /*
167005b261ecSmrg         * initialize default colormap for monochrome
167105b261ecSmrg         */
167235c4bbdfSmrg        for (i = 0; i < 3; i++)
167335c4bbdfSmrg            regp->DAC[i] = 0x00;
167435c4bbdfSmrg        for (i = 3; i < 768; i++)
167535c4bbdfSmrg            regp->DAC[i] = 0x3F;
167605b261ecSmrg        i = BLACK_VALUE * 3;
167705b261ecSmrg        regp->DAC[i++] = blackColour.red;
167805b261ecSmrg        regp->DAC[i++] = blackColour.green;
167905b261ecSmrg        regp->DAC[i] = blackColour.blue;
168005b261ecSmrg        i = WHITE_VALUE * 3;
168105b261ecSmrg        regp->DAC[i++] = whiteColour.red;
168205b261ecSmrg        regp->DAC[i++] = whiteColour.green;
168305b261ecSmrg        regp->DAC[i] = whiteColour.blue;
168405b261ecSmrg        i = OVERSCAN_VALUE * 3;
168505b261ecSmrg        regp->DAC[i++] = 0x00;
168605b261ecSmrg        regp->DAC[i++] = 0x00;
168705b261ecSmrg        regp->DAC[i] = 0x00;
168835c4bbdfSmrg    }
168935c4bbdfSmrg    else {
169035c4bbdfSmrg        /* Set all colours to black */
169135c4bbdfSmrg        for (i = 0; i < 768; i++)
169235c4bbdfSmrg            regp->DAC[i] = 0x00;
169305b261ecSmrg        /* ... and the overscan */
169405b261ecSmrg        if (scrp->depth >= 4)
169505b261ecSmrg            regp->Attribute[OVERSCAN] = 0xFF;
169605b261ecSmrg    }
169705b261ecSmrg    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
169835c4bbdfSmrg        xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
169935c4bbdfSmrg        xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
170035c4bbdfSmrg        regp->DAC[765] = 0x3F;
170135c4bbdfSmrg        regp->DAC[766] = 0x00;
170235c4bbdfSmrg        regp->DAC[767] = 0x3F;
170335c4bbdfSmrg        regp->Attribute[OVERSCAN] = 0xFF;
170435c4bbdfSmrg        hwp->ShowOverscan = TRUE;
170535c4bbdfSmrg    }
170635c4bbdfSmrg    else
170735c4bbdfSmrg        hwp->ShowOverscan = FALSE;
170805b261ecSmrg
170905b261ecSmrg    hwp->paletteEnabled = FALSE;
171005b261ecSmrg    hwp->cmapSaved = FALSE;
171105b261ecSmrg    hwp->MapSize = 0;
171205b261ecSmrg    hwp->pScrn = scrp;
171305b261ecSmrg
17144642e01fSmrg    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
171505b261ecSmrg
171605b261ecSmrg    return TRUE;
171705b261ecSmrg}
171805b261ecSmrg
171905b261ecSmrgvoid
172005b261ecSmrgvgaHWFreeHWRec(ScrnInfoPtr scrp)
172105b261ecSmrg{
172205b261ecSmrg    if (vgaHWPrivateIndex >= 0) {
172335c4bbdfSmrg        vgaHWPtr hwp = VGAHWPTR(scrp);
172435c4bbdfSmrg
172535c4bbdfSmrg        if (!hwp)
172635c4bbdfSmrg            return;
172705b261ecSmrg
172835c4bbdfSmrg        pci_device_close_io(hwp->dev, hwp->io);
172905b261ecSmrg
173035c4bbdfSmrg        free(hwp->FontInfo1);
173135c4bbdfSmrg        free(hwp->FontInfo2);
173235c4bbdfSmrg        free(hwp->TextInfo);
173305b261ecSmrg
173435c4bbdfSmrg        vgaHWFreeRegs(&hwp->ModeReg);
173535c4bbdfSmrg        vgaHWFreeRegs(&hwp->SavedReg);
173605b261ecSmrg
173735c4bbdfSmrg        free(hwp);
173835c4bbdfSmrg        VGAHWPTRLVAL(scrp) = NULL;
173905b261ecSmrg    }
174005b261ecSmrg}
174105b261ecSmrg
174205b261ecSmrgBool
174305b261ecSmrgvgaHWMapMem(ScrnInfoPtr scrp)
174405b261ecSmrg{
174505b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrp);
174635c4bbdfSmrg
174705b261ecSmrg    if (hwp->Base)
174835c4bbdfSmrg        return TRUE;
174905b261ecSmrg
175005b261ecSmrg    /* If not set, initialise with the defaults */
175105b261ecSmrg    if (hwp->MapSize == 0)
175235c4bbdfSmrg        hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
175305b261ecSmrg    if (hwp->MapPhys == 0)
175435c4bbdfSmrg        hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
175505b261ecSmrg
175605b261ecSmrg    /*
175705b261ecSmrg     * Map as VIDMEM_MMIO_32BIT because WC
175805b261ecSmrg     * is bad when there is page flipping.
175905b261ecSmrg     * XXX This is not correct but we do it
176005b261ecSmrg     * for now.
176105b261ecSmrg     */
17626747b715Smrg    DebugF("Mapping VGAMem\n");
176335c4bbdfSmrg    pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
176435c4bbdfSmrg                          PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
176505b261ecSmrg    return hwp->Base != NULL;
176605b261ecSmrg}
176705b261ecSmrg
176805b261ecSmrgvoid
176905b261ecSmrgvgaHWUnmapMem(ScrnInfoPtr scrp)
177005b261ecSmrg{
177105b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(scrp);
177205b261ecSmrg
177305b261ecSmrg    if (hwp->Base == NULL)
177435c4bbdfSmrg        return;
177535c4bbdfSmrg
17766747b715Smrg    DebugF("Unmapping VGAMem\n");
177735c4bbdfSmrg    pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
177805b261ecSmrg    hwp->Base = NULL;
177905b261ecSmrg}
178005b261ecSmrg
178105b261ecSmrgint
17826747b715SmrgvgaHWGetIndex(void)
178305b261ecSmrg{
178405b261ecSmrg    return vgaHWPrivateIndex;
178505b261ecSmrg}
178605b261ecSmrg
178705b261ecSmrgvoid
178805b261ecSmrgvgaHWGetIOBase(vgaHWPtr hwp)
178905b261ecSmrg{
179005b261ecSmrg    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
179135c4bbdfSmrg        VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
179205b261ecSmrg    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
179335c4bbdfSmrg                   "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
179405b261ecSmrg}
179505b261ecSmrg
179605b261ecSmrgvoid
179705b261ecSmrgvgaHWLock(vgaHWPtr hwp)
179805b261ecSmrg{
179905b261ecSmrg    /* Protect CRTC[0-7] */
180005b261ecSmrg    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
180105b261ecSmrg}
180205b261ecSmrg
180305b261ecSmrgvoid
180405b261ecSmrgvgaHWUnlock(vgaHWPtr hwp)
180505b261ecSmrg{
180605b261ecSmrg    /* Unprotect CRTC[0-7] */
180735c4bbdfSmrg    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
180805b261ecSmrg}
180905b261ecSmrg
181005b261ecSmrgvoid
181105b261ecSmrgvgaHWEnable(vgaHWPtr hwp)
181205b261ecSmrg{
181305b261ecSmrg    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
181405b261ecSmrg}
181505b261ecSmrg
181605b261ecSmrgvoid
181705b261ecSmrgvgaHWDisable(vgaHWPtr hwp)
181805b261ecSmrg{
181905b261ecSmrg    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
182005b261ecSmrg}
182105b261ecSmrg
182205b261ecSmrgstatic void
182335c4bbdfSmrgvgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
182435c4bbdfSmrg                 VisualPtr pVisual)
182505b261ecSmrg{
182605b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
182705b261ecSmrg    int i, index;
182805b261ecSmrg
182905b261ecSmrg    for (i = 0; i < numColors; i++) {
183035c4bbdfSmrg        index = indices[i];
183135c4bbdfSmrg        hwp->writeDacWriteAddr(hwp, index);
183235c4bbdfSmrg        DACDelay(hwp);
183335c4bbdfSmrg        hwp->writeDacData(hwp, colors[index].red);
183435c4bbdfSmrg        DACDelay(hwp);
183535c4bbdfSmrg        hwp->writeDacData(hwp, colors[index].green);
183635c4bbdfSmrg        DACDelay(hwp);
183735c4bbdfSmrg        hwp->writeDacData(hwp, colors[index].blue);
183835c4bbdfSmrg        DACDelay(hwp);
183905b261ecSmrg    }
184005b261ecSmrg
184105b261ecSmrg    /* This shouldn't be necessary, but we'll play safe. */
184205b261ecSmrg    hwp->disablePalette(hwp);
184305b261ecSmrg}
184405b261ecSmrg
184505b261ecSmrgstatic void
184605b261ecSmrgvgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
184705b261ecSmrg{
184805b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
184905b261ecSmrg
185005b261ecSmrg    if (overscan < 0 || overscan > 255)
185135c4bbdfSmrg        return;
185205b261ecSmrg
185305b261ecSmrg    hwp->enablePalette(hwp);
185405b261ecSmrg    hwp->writeAttr(hwp, OVERSCAN, overscan);
185505b261ecSmrg
185605b261ecSmrg#ifdef DEBUGOVERSCAN
185705b261ecSmrg    {
185835c4bbdfSmrg        int ov = hwp->readAttr(hwp, OVERSCAN);
185935c4bbdfSmrg        int red, green, blue;
186035c4bbdfSmrg
186135c4bbdfSmrg        hwp->writeDacReadAddr(hwp, ov);
186235c4bbdfSmrg        red = hwp->readDacData(hwp);
186335c4bbdfSmrg        green = hwp->readDacData(hwp);
186435c4bbdfSmrg        blue = hwp->readDacData(hwp);
186535c4bbdfSmrg        ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
186635c4bbdfSmrg               ov, red, green, blue);
186705b261ecSmrg    }
186805b261ecSmrg#endif
186905b261ecSmrg
187005b261ecSmrg    hwp->disablePalette(hwp);
187105b261ecSmrg}
187205b261ecSmrg
187305b261ecSmrgBool
187405b261ecSmrgvgaHWHandleColormaps(ScreenPtr pScreen)
187505b261ecSmrg{
187635c4bbdfSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
187705b261ecSmrg
187805b261ecSmrg    if (pScrn->depth > 1 && pScrn->depth <= 8) {
187935c4bbdfSmrg        return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
188035c4bbdfSmrg                                   pScrn->rgbBits, vgaHWLoadPalette,
188135c4bbdfSmrg                                   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
188235c4bbdfSmrg                                   CMAP_RELOAD_ON_MODE_SWITCH);
188305b261ecSmrg    }
188405b261ecSmrg    return TRUE;
188505b261ecSmrg}
188605b261ecSmrg
188705b261ecSmrg/* ----------------------- DDC support ------------------------*/
188835c4bbdfSmrg/*
188905b261ecSmrg * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
189005b261ecSmrg * to read out EDID at a faster rate. Allowed maximum is 25kHz with
189105b261ecSmrg * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
189205b261ecSmrg * readback, enable access to cr00-cr07.
189305b261ecSmrg */
189405b261ecSmrg
189505b261ecSmrg/* vertical timings */
189605b261ecSmrg#define DISPLAY_END 0x04
189705b261ecSmrg#define BLANK_START DISPLAY_END
189805b261ecSmrg#define SYNC_START BLANK_START
189905b261ecSmrg#define SYNC_END 0x09
190005b261ecSmrg#define BLANK_END SYNC_END
190105b261ecSmrg#define V_TOTAL BLANK_END
190205b261ecSmrg/* this function doesn't have to be reentrant for our purposes */
190305b261ecSmrgstruct _vgaDdcSave {
190405b261ecSmrg    unsigned char cr03;
190505b261ecSmrg    unsigned char cr06;
190605b261ecSmrg    unsigned char cr07;
190705b261ecSmrg    unsigned char cr09;
190805b261ecSmrg    unsigned char cr10;
190905b261ecSmrg    unsigned char cr11;
191005b261ecSmrg    unsigned char cr12;
191105b261ecSmrg    unsigned char cr15;
191205b261ecSmrg    unsigned char cr16;
191305b261ecSmrg    unsigned char msr;
191405b261ecSmrg};
191505b261ecSmrg
191605b261ecSmrgvoid
191705b261ecSmrgvgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
191805b261ecSmrg{
191905b261ecSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
192005b261ecSmrg    unsigned char tmp;
192135c4bbdfSmrg    struct _vgaDdcSave *save;
192235c4bbdfSmrg
192305b261ecSmrg    switch (speed) {
192405b261ecSmrg    case DDC_FAST:
192535c4bbdfSmrg
192635c4bbdfSmrg        if (hwp->ddc != NULL)
192735c4bbdfSmrg            break;
192835c4bbdfSmrg        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
192935c4bbdfSmrg        save = (struct _vgaDdcSave *) hwp->ddc;
193035c4bbdfSmrg        /* Lightpen register disable - allow access to cr10 & 11; just in case */
193135c4bbdfSmrg        save->cr03 = hwp->readCrtc(hwp, 0x03);
193235c4bbdfSmrg        hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
193335c4bbdfSmrg        save->cr12 = hwp->readCrtc(hwp, 0x12);
193435c4bbdfSmrg        hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
193535c4bbdfSmrg        save->cr15 = hwp->readCrtc(hwp, 0x15);
193635c4bbdfSmrg        hwp->writeCrtc(hwp, 0x15, BLANK_START);
193735c4bbdfSmrg        save->cr10 = hwp->readCrtc(hwp, 0x10);
193835c4bbdfSmrg        hwp->writeCrtc(hwp, 0x10, SYNC_START);
193935c4bbdfSmrg        save->cr11 = hwp->readCrtc(hwp, 0x11);
194035c4bbdfSmrg        /* unprotect group 1 registers; just in case ... */
194135c4bbdfSmrg        hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
194235c4bbdfSmrg        save->cr16 = hwp->readCrtc(hwp, 0x16);
194335c4bbdfSmrg        hwp->writeCrtc(hwp, 0x16, BLANK_END);
194435c4bbdfSmrg        save->cr06 = hwp->readCrtc(hwp, 0x06);
194535c4bbdfSmrg        hwp->writeCrtc(hwp, 0x06, V_TOTAL);
194635c4bbdfSmrg        /* all values have less than 8 bit - mask out 9th and 10th bits */
194735c4bbdfSmrg        save->cr09 = hwp->readCrtc(hwp, 0x09);
194835c4bbdfSmrg        hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
194935c4bbdfSmrg        save->cr07 = hwp->readCrtc(hwp, 0x07);
195035c4bbdfSmrg        hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
1951ed6184dfSmrg        /* vsync polarity negative & ensure a 25MHz clock */
195235c4bbdfSmrg        save->msr = hwp->readMiscOut(hwp);
195335c4bbdfSmrg        hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
195435c4bbdfSmrg        break;
195505b261ecSmrg    case DDC_SLOW:
195635c4bbdfSmrg        if (hwp->ddc == NULL)
195735c4bbdfSmrg            break;
195835c4bbdfSmrg        save = (struct _vgaDdcSave *) hwp->ddc;
195935c4bbdfSmrg        hwp->writeMiscOut(hwp, save->msr);
196035c4bbdfSmrg        hwp->writeCrtc(hwp, 0x07, save->cr07);
196135c4bbdfSmrg        tmp = hwp->readCrtc(hwp, 0x09);
196235c4bbdfSmrg        hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
196335c4bbdfSmrg        hwp->writeCrtc(hwp, 0x06, save->cr06);
196435c4bbdfSmrg        hwp->writeCrtc(hwp, 0x16, save->cr16);
196535c4bbdfSmrg        hwp->writeCrtc(hwp, 0x11, save->cr11);
196635c4bbdfSmrg        hwp->writeCrtc(hwp, 0x10, save->cr10);
196735c4bbdfSmrg        hwp->writeCrtc(hwp, 0x15, save->cr15);
196835c4bbdfSmrg        hwp->writeCrtc(hwp, 0x12, save->cr12);
196935c4bbdfSmrg        hwp->writeCrtc(hwp, 0x03, save->cr03);
197035c4bbdfSmrg        free(save);
197135c4bbdfSmrg        hwp->ddc = NULL;
197235c4bbdfSmrg        break;
197305b261ecSmrg    default:
197435c4bbdfSmrg        break;
197505b261ecSmrg    }
197605b261ecSmrg}
197705b261ecSmrg
19786747b715SmrgDDC1SetSpeedProc
19796747b715SmrgvgaHWddc1SetSpeedWeak(void)
19806747b715Smrg{
19816747b715Smrg    return vgaHWddc1SetSpeed;
19826747b715Smrg}
198305b261ecSmrg
198435c4bbdfSmrgSaveScreenProcPtr
198535c4bbdfSmrgvgaHWSaveScreenWeak(void)
19866747b715Smrg{
19876747b715Smrg    return vgaHWSaveScreen;
19886747b715Smrg}
198935c4bbdfSmrg
199035c4bbdfSmrg/*
199135c4bbdfSmrg * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
199235c4bbdfSmrg */
199335c4bbdfSmrgvoid
199435c4bbdfSmrgxf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
199535c4bbdfSmrg              void (*ProtectRegs) (ScrnInfoPtr, Bool),
199635c4bbdfSmrg              void (*BlankScreen) (ScrnInfoPtr, Bool),
199735c4bbdfSmrg              unsigned long vertsyncreg, int maskval, int knownclkindex,
199835c4bbdfSmrg              int knownclkvalue)
199935c4bbdfSmrg{
200035c4bbdfSmrg    register int status = vertsyncreg;
200135c4bbdfSmrg    unsigned long i, cnt, rcnt, sync;
200235c4bbdfSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
200335c4bbdfSmrg
200435c4bbdfSmrg    /* First save registers that get written on */
200535c4bbdfSmrg    (*ClockFunc) (pScrn, CLK_REG_SAVE);
200635c4bbdfSmrg
200735c4bbdfSmrg    if (num > MAXCLOCKS)
200835c4bbdfSmrg        num = MAXCLOCKS;
200935c4bbdfSmrg
201035c4bbdfSmrg    for (i = 0; i < num; i++) {
201135c4bbdfSmrg        if (ProtectRegs)
201235c4bbdfSmrg            (*ProtectRegs) (pScrn, TRUE);
201335c4bbdfSmrg        if (!(*ClockFunc) (pScrn, i)) {
201435c4bbdfSmrg            pScrn->clock[i] = -1;
201535c4bbdfSmrg            continue;
201635c4bbdfSmrg        }
201735c4bbdfSmrg        if (ProtectRegs)
201835c4bbdfSmrg            (*ProtectRegs) (pScrn, FALSE);
201935c4bbdfSmrg        if (BlankScreen)
202035c4bbdfSmrg            (*BlankScreen) (pScrn, FALSE);
202135c4bbdfSmrg
202235c4bbdfSmrg        usleep(50000);          /* let VCO stabilise */
202335c4bbdfSmrg
202435c4bbdfSmrg        cnt = 0;
202535c4bbdfSmrg        sync = 200000;
202635c4bbdfSmrg
202735c4bbdfSmrg        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
202835c4bbdfSmrg            if (sync-- == 0)
202935c4bbdfSmrg                goto finish;
203035c4bbdfSmrg        /* Something appears to be happening, so reset sync count */
203135c4bbdfSmrg        sync = 200000;
203235c4bbdfSmrg        while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
203335c4bbdfSmrg            if (sync-- == 0)
203435c4bbdfSmrg                goto finish;
203535c4bbdfSmrg        /* Something appears to be happening, so reset sync count */
203635c4bbdfSmrg        sync = 200000;
203735c4bbdfSmrg        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
203835c4bbdfSmrg            if (sync-- == 0)
203935c4bbdfSmrg                goto finish;
204035c4bbdfSmrg
204135c4bbdfSmrg        for (rcnt = 0; rcnt < 5; rcnt++) {
204235c4bbdfSmrg            while (!(pci_io_read8(hwp->io, status) & maskval))
204335c4bbdfSmrg                cnt++;
204435c4bbdfSmrg            while ((pci_io_read8(hwp->io, status) & maskval))
204535c4bbdfSmrg                cnt++;
204635c4bbdfSmrg        }
204735c4bbdfSmrg
204835c4bbdfSmrg finish:
204935c4bbdfSmrg        pScrn->clock[i] = cnt ? cnt : -1;
205035c4bbdfSmrg        if (BlankScreen)
205135c4bbdfSmrg            (*BlankScreen) (pScrn, TRUE);
205235c4bbdfSmrg    }
205335c4bbdfSmrg
205435c4bbdfSmrg    for (i = 0; i < num; i++) {
205535c4bbdfSmrg        if (i != knownclkindex) {
205635c4bbdfSmrg            if (pScrn->clock[i] == -1) {
205735c4bbdfSmrg                pScrn->clock[i] = 0;
205835c4bbdfSmrg            }
205935c4bbdfSmrg            else {
206035c4bbdfSmrg                pScrn->clock[i] = (int) (0.5 +
206135c4bbdfSmrg                                         (((float) knownclkvalue) *
206235c4bbdfSmrg                                          pScrn->clock[knownclkindex]) /
206335c4bbdfSmrg                                         (pScrn->clock[i]));
206435c4bbdfSmrg                /* Round to nearest 10KHz */
206535c4bbdfSmrg                pScrn->clock[i] += 5;
206635c4bbdfSmrg                pScrn->clock[i] /= 10;
206735c4bbdfSmrg                pScrn->clock[i] *= 10;
206835c4bbdfSmrg            }
206935c4bbdfSmrg        }
207035c4bbdfSmrg    }
207135c4bbdfSmrg
207235c4bbdfSmrg    pScrn->clock[knownclkindex] = knownclkvalue;
207335c4bbdfSmrg    pScrn->numClocks = num;
207435c4bbdfSmrg
207535c4bbdfSmrg    /* Restore registers that were written on */
207635c4bbdfSmrg    (*ClockFunc) (pScrn, CLK_REG_RESTORE);
207735c4bbdfSmrg}
2078