vgaHW.c revision 35c4bbdf
11.5Sandvar
21.2Sskrll/*
31.1Smatt *
41.1Smatt * Copyright 1991-1999 by The XFree86 Project, Inc.
51.1Smatt *
61.1Smatt * Loosely based on code bearing the following copyright:
71.1Smatt *
81.1Smatt *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
91.1Smatt *
101.1Smatt */
111.1Smatt
121.1Smatt#define _NEED_SYSI86
131.1Smatt
141.1Smatt#ifdef HAVE_XORG_CONFIG_H
151.1Smatt#include <xorg-config.h>
161.1Smatt#endif
171.1Smatt
181.1Smatt#include <stdlib.h>
191.1Smatt#include <string.h>
201.1Smatt#include <unistd.h>
211.1Smatt
221.1Smatt#include <X11/X.h>
231.1Smatt#include "misc.h"
241.1Smatt
251.1Smatt#include "xf86.h"
261.1Smatt#include "xf86_OSproc.h"
271.1Smatt#include "vgaHW.h"
281.1Smatt
291.1Smatt#include "compiler.h"
301.1Smatt
311.1Smatt#include "xf86cmap.h"
321.1Smatt
331.1Smatt#include "Pci.h"
341.1Smatt
351.3Sdholland#ifndef SAVE_FONT1
361.3Sdholland#define SAVE_FONT1 1
371.3Sdholland#endif
381.3Sdholland
391.3Sdholland/*
401.1Smatt * These used to be OS-specific, which made this module have an undesirable
411.1Smatt * OS dependency.  Define them by default for all platforms.
421.3Sdholland */
431.1Smatt#ifndef NEED_SAVED_CMAP
441.1Smatt#define NEED_SAVED_CMAP
451.1Smatt#endif
461.1Smatt#ifndef SAVE_TEXT
471.1Smatt#define SAVE_TEXT 1
481.1Smatt#endif
491.1Smatt#ifndef SAVE_FONT2
501.1Smatt#define SAVE_FONT2 1
511.3Sdholland#endif
521.3Sdholland
531.3Sdholland/* bytes per plane to save for text */
541.3Sdholland#define TEXT_AMOUNT 16384
551.3Sdholland
561.3Sdholland/* bytes per plane to save for font data */
571.3Sdholland#define FONT_AMOUNT (8*8192)
581.3Sdholland
591.3Sdholland#if 0
601.3Sdholland/* Override all of these for now */
611.1Smatt#undef SAVE_FONT1
621.3Sdholland#define SAVE_FONT1 1
631.3Sdholland#undef SAVE_FONT2
641.3Sdholland#define SAVE_FONT2 1
651.3Sdholland#undef SAVE_TEST
661.3Sdholland#define SAVE_TEST 1
671.3Sdholland#undef FONT_AMOUNT
681.3Sdholland#define FONT_AMOUNT 65536
691.3Sdholland#undef TEXT_AMOUNT
701.3Sdholland#define TEXT_AMOUNT 65536
711.1Smatt#endif
721.1Smatt
731.1Smatt/* DAC indices for white and black */
741.1Smatt#define WHITE_VALUE 0x3F
751.1Smatt#define BLACK_VALUE 0x00
761.1Smatt#define OVERSCAN_VALUE 0x01
771.1Smatt
781.1Smatt/* Use a private definition of this here */
791.3Sdholland#undef VGAHWPTR
801.1Smatt#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
811.3Sdholland#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
821.1Smatt
831.1Smattstatic int vgaHWPrivateIndex = -1;
841.1Smatt
851.1Smatt#define DAC_TEST_MASK 0x3F
861.1Smatt
871.1Smatt#ifdef NEED_SAVED_CMAP
881.3Sdholland/* This default colourmap is used only when it can't be read from the VGA */
891.3Sdholland
901.1Smattstatic CARD8 defaultDAC[768] = {
911.3Sdholland    0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
921.3Sdholland    42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
931.3Sdholland    21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
941.3Sdholland    63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
951.3Sdholland    0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11,
961.3Sdholland    14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24,
971.3Sdholland    28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40,
981.3Sdholland    45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63,
991.3Sdholland    0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63,
1001.3Sdholland    63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16,
1011.3Sdholland    63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0,
1021.1Smatt    63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0,
1031.1Smatt    0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47,
1041.1Smatt    0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63,
1051.1Smatt    31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63,
1061.1Smatt    63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39,
1071.1Smatt    63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31,
1081.1Smatt    63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31,
1091.3Sdholland    31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55,
1101.1Smatt    31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63,
1111.1Smatt    45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63,
1121.1Smatt    63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49,
1131.1Smatt    63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45,
1141.1Smatt    63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45,
1151.1Smatt    45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58,
1161.1Smatt    45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63,
1171.1Smatt    0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28,
1181.3Sdholland    28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7,
1191.1Smatt    28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0,
1201.3Sdholland    28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0,
1211.3Sdholland    0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21,
1221.3Sdholland    0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28,
1231.3Sdholland    14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28,
1241.3Sdholland    28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17,
1251.3Sdholland    28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14,
1261.3Sdholland    28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14,
1271.3Sdholland    14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24,
1281.3Sdholland    14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28,
1291.3Sdholland    20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28,
1301.1Smatt    28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22,
1311.1Smatt    28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20,
1321.1Smatt    28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20,
1331.1Smatt    20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26,
1341.1Smatt    20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28,
1351.3Sdholland    0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16,
1361.1Smatt    16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4,
1371.3Sdholland    16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0,
1381.3Sdholland    16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0,
1391.3Sdholland    0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12,
1401.3Sdholland    0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16,
1411.3Sdholland    8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16,
1421.3Sdholland    16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10,
1431.3Sdholland    16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8,
1441.1Smatt    16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8,
1451.1Smatt    8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14,
1461.3Sdholland    8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16,
1471.3Sdholland    11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16,
1481.3Sdholland    16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12,
1491.3Sdholland    16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11,
1501.3Sdholland    16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11,
1511.1Smatt    11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15,
1521.1Smatt    11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16,
1531.3Sdholland    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1541.3Sdholland    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1551.3Sdholland};
1561.3Sdholland#endif                          /* NEED_SAVED_CMAP */
1571.3Sdholland
1581.3Sdholland/*
1591.3Sdholland * Standard VGA versions of the register access functions.
1601.3Sdholland */
1611.3Sdhollandstatic void
1621.3SdhollandstdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
1631.3Sdholland{
1641.3Sdholland    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
1651.3Sdholland    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
1661.3Sdholland}
1671.3Sdholland
1681.3Sdhollandstatic CARD8
1691.3SdhollandstdReadCrtc(vgaHWPtr hwp, CARD8 index)
1701.3Sdholland{
1711.3Sdholland    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
1721.3Sdholland    return pci_io_read8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET);
1731.3Sdholland}
1741.3Sdholland
1751.3Sdhollandstatic void
1761.3SdhollandstdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
1771.3Sdholland{
1781.3Sdholland    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
1791.3Sdholland    pci_io_write8(hwp->io, VGA_GRAPH_DATA, value);
1801.3Sdholland}
1811.3Sdholland
1821.3Sdhollandstatic CARD8
1831.3SdhollandstdReadGr(vgaHWPtr hwp, CARD8 index)
1841.3Sdholland{
1851.3Sdholland    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
1861.3Sdholland    return pci_io_read8(hwp->io, VGA_GRAPH_DATA);
1871.3Sdholland}
1881.3Sdholland
1891.3Sdhollandstatic void
1901.3SdhollandstdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
1911.3Sdholland{
1921.3Sdholland    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
1931.3Sdholland    pci_io_write8(hwp->io, VGA_SEQ_DATA, value);
1941.3Sdholland}
1951.3Sdholland
1961.3Sdhollandstatic CARD8
1971.3SdhollandstdReadSeq(vgaHWPtr hwp, CARD8 index)
1981.3Sdholland{
1991.3Sdholland    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
2001.3Sdholland    return pci_io_read8(hwp->io, VGA_SEQ_DATA);
2011.3Sdholland}
2021.3Sdholland
2031.3Sdhollandstatic CARD8
2041.3SdhollandstdReadST00(vgaHWPtr hwp)
2051.3Sdholland{
2061.3Sdholland    return pci_io_read8(hwp->io, VGA_IN_STAT_0);
2071.3Sdholland}
2081.3Sdholland
2091.3Sdhollandstatic CARD8
2101.3SdhollandstdReadST01(vgaHWPtr hwp)
2111.3Sdholland{
2121.3Sdholland    return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
2131.3Sdholland}
2141.3Sdholland
2151.3Sdhollandstatic CARD8
2161.3SdhollandstdReadFCR(vgaHWPtr hwp)
2171.3Sdholland{
2181.3Sdholland    return pci_io_read8(hwp->io, VGA_FEATURE_R);
2191.3Sdholland}
2201.3Sdholland
2211.3Sdhollandstatic void
2221.3SdhollandstdWriteFCR(vgaHWPtr hwp, CARD8 value)
2231.3Sdholland{
2241.3Sdholland    pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
2251.3Sdholland}
2261.3Sdholland
2271.3Sdhollandstatic void
2281.3SdhollandstdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
2291.3Sdholland{
2301.3Sdholland    if (hwp->paletteEnabled)
2311.3Sdholland        index &= ~0x20;
2321.3Sdholland    else
2331.3Sdholland        index |= 0x20;
2341.3Sdholland
2351.3Sdholland    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
2361.3Sdholland    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
2371.3Sdholland    pci_io_write8(hwp->io, VGA_ATTR_DATA_W, value);
2381.3Sdholland}
2391.3Sdholland
2401.3Sdhollandstatic CARD8
2411.3SdhollandstdReadAttr(vgaHWPtr hwp, CARD8 index)
2421.3Sdholland{
2431.3Sdholland    if (hwp->paletteEnabled)
2441.4Sdholland        index &= ~0x20;
2451.4Sdholland    else
2461.4Sdholland        index |= 0x20;
2471.4Sdholland
2481.3Sdholland    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
2491.3Sdholland    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
2501.3Sdholland    return pci_io_read8(hwp->io, VGA_ATTR_DATA_R);
2511.3Sdholland}
2521.3Sdholland
2531.4Sdhollandstatic void
2541.3SdhollandstdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
2551.3Sdholland{
2561.3Sdholland    pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
2571.3Sdholland}
2581.3Sdholland
2591.3Sdhollandstatic CARD8
2601.3SdhollandstdReadMiscOut(vgaHWPtr hwp)
2611.3Sdholland{
2621.3Sdholland    return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
2631.3Sdholland}
2641.3Sdholland
2651.3Sdhollandstatic void
2661.3SdhollandstdEnablePalette(vgaHWPtr hwp)
2671.3Sdholland{
2681.3Sdholland    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
2691.3Sdholland    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x00);
2701.3Sdholland    hwp->paletteEnabled = TRUE;
2711.3Sdholland}
2721.3Sdholland
2731.3Sdhollandstatic void
2741.3SdhollandstdDisablePalette(vgaHWPtr hwp)
2751.3Sdholland{
2761.3Sdholland    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
2771.3Sdholland    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x20);
2781.3Sdholland    hwp->paletteEnabled = FALSE;
2791.3Sdholland}
2801.3Sdholland
2811.3Sdhollandstatic void
2821.3SdhollandstdWriteDacMask(vgaHWPtr hwp, CARD8 value)
2831.3Sdholland{
2841.3Sdholland    pci_io_write8(hwp->io, VGA_DAC_MASK, value);
2851.3Sdholland}
2861.3Sdholland
2871.3Sdhollandstatic CARD8
2881.3SdhollandstdReadDacMask(vgaHWPtr hwp)
2891.3Sdholland{
2901.3Sdholland    return pci_io_read8(hwp->io, VGA_DAC_MASK);
2911.3Sdholland}
2921.3Sdholland
2931.3Sdhollandstatic void
2941.3SdhollandstdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
2951.3Sdholland{
2961.3Sdholland    pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
2971.3Sdholland}
2981.3Sdholland
2991.3Sdhollandstatic void
3001.3SdhollandstdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
3011.3Sdholland{
3021.3Sdholland    pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
3031.3Sdholland}
3041.3Sdholland
3051.3Sdhollandstatic void
3061.3SdhollandstdWriteDacData(vgaHWPtr hwp, CARD8 value)
3071.3Sdholland{
3081.3Sdholland    pci_io_write8(hwp->io, VGA_DAC_DATA, value);
3091.3Sdholland}
3101.3Sdholland
3111.3Sdhollandstatic CARD8
3121.3SdhollandstdReadDacData(vgaHWPtr hwp)
3131.3Sdholland{
3141.3Sdholland    return pci_io_read8(hwp->io, VGA_DAC_DATA);
3151.3Sdholland}
3161.3Sdholland
3171.3Sdhollandstatic CARD8
3181.3SdhollandstdReadEnable(vgaHWPtr hwp)
3191.5Sandvar{
3201.3Sdholland    return pci_io_read8(hwp->io, VGA_ENABLE);
3211.3Sdholland}
3221.3Sdholland
3231.3Sdhollandstatic void
3241.3SdhollandstdWriteEnable(vgaHWPtr hwp, CARD8 value)
3251.3Sdholland{
3261.3Sdholland    pci_io_write8(hwp->io, VGA_ENABLE, value);
3271.3Sdholland}
3281.3Sdholland
3291.3Sdhollandvoid
3301.3SdhollandvgaHWSetStdFuncs(vgaHWPtr hwp)
3311.3Sdholland{
3321.3Sdholland    hwp->writeCrtc = stdWriteCrtc;
3331.3Sdholland    hwp->readCrtc = stdReadCrtc;
3341.3Sdholland    hwp->writeGr = stdWriteGr;
3351.3Sdholland    hwp->readGr = stdReadGr;
3361.3Sdholland    hwp->readST00 = stdReadST00;
3371.3Sdholland    hwp->readST01 = stdReadST01;
3381.3Sdholland    hwp->readFCR = stdReadFCR;
3391.3Sdholland    hwp->writeFCR = stdWriteFCR;
3401.3Sdholland    hwp->writeAttr = stdWriteAttr;
3411.3Sdholland    hwp->readAttr = stdReadAttr;
3421.3Sdholland    hwp->writeSeq = stdWriteSeq;
3431.3Sdholland    hwp->readSeq = stdReadSeq;
3441.3Sdholland    hwp->writeMiscOut = stdWriteMiscOut;
3451.3Sdholland    hwp->readMiscOut = stdReadMiscOut;
3461.3Sdholland    hwp->enablePalette = stdEnablePalette;
3471.3Sdholland    hwp->disablePalette = stdDisablePalette;
3481.3Sdholland    hwp->writeDacMask = stdWriteDacMask;
3491.3Sdholland    hwp->readDacMask = stdReadDacMask;
3501.3Sdholland    hwp->writeDacWriteAddr = stdWriteDacWriteAddr;
3511.3Sdholland    hwp->writeDacReadAddr = stdWriteDacReadAddr;
3521.3Sdholland    hwp->writeDacData = stdWriteDacData;
3531.1Smatt    hwp->readDacData = stdReadDacData;
3541.1Smatt    hwp->readEnable = stdReadEnable;
3551.1Smatt    hwp->writeEnable = stdWriteEnable;
3561.1Smatt
3571.1Smatt    hwp->io = pci_legacy_open_io(hwp->dev, 0, 64 * 1024);
3581.1Smatt}
3591.1Smatt
3601.1Smatt/*
3611.1Smatt * MMIO versions of the register access functions.  These require
3621.1Smatt * hwp->MemBase to be set in such a way that when the standard VGA port
3631.1Smatt * adderss is added the correct memory address results.
3641.1Smatt */
3651.1Smatt
3661.1Smatt#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
3671.1Smatt#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
3681.1Smatt
3691.1Smattstatic void
3701.1SmattmmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
3711.1Smatt{
3721.1Smatt    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
3731.3Sdholland    moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
3741.3Sdholland}
3751.1Smatt
3761.1Smattstatic CARD8
3771.1SmattmmioReadCrtc(vgaHWPtr hwp, CARD8 index)
3781.1Smatt{
3791.1Smatt    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
3801.1Smatt    return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
3811.1Smatt}
3821.1Smatt
3831.1Smattstatic void
3841.1SmattmmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
3851.1Smatt{
3861.1Smatt    moutb(VGA_GRAPH_INDEX, index);
3871.1Smatt    moutb(VGA_GRAPH_DATA, value);
3881.1Smatt}
3891.3Sdholland
3901.3Sdhollandstatic CARD8
3911.3SdhollandmmioReadGr(vgaHWPtr hwp, CARD8 index)
3921.3Sdholland{
3931.3Sdholland    moutb(VGA_GRAPH_INDEX, index);
3941.3Sdholland    return minb(VGA_GRAPH_DATA);
3951.3Sdholland}
3961.3Sdholland
3971.3Sdhollandstatic void
3981.3SdhollandmmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
3991.3Sdholland{
4001.3Sdholland    moutb(VGA_SEQ_INDEX, index);
4011.3Sdholland    moutb(VGA_SEQ_DATA, value);
4021.3Sdholland}
4031.3Sdholland
4041.3Sdhollandstatic CARD8
4051.3SdhollandmmioReadSeq(vgaHWPtr hwp, CARD8 index)
4061.3Sdholland{
4071.3Sdholland    moutb(VGA_SEQ_INDEX, index);
4081.3Sdholland    return minb(VGA_SEQ_DATA);
4091.3Sdholland}
4101.3Sdholland
4111.3Sdhollandstatic CARD8
4121.3SdhollandmmioReadST00(vgaHWPtr hwp)
4131.3Sdholland{
4141.3Sdholland    return minb(VGA_IN_STAT_0);
4151.3Sdholland}
4161.3Sdholland
4171.3Sdhollandstatic CARD8
4181.3SdhollandmmioReadST01(vgaHWPtr hwp)
4191.3Sdholland{
4201.3Sdholland    return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
4211.3Sdholland}
4221.3Sdholland
4231.3Sdhollandstatic CARD8
4241.3SdhollandmmioReadFCR(vgaHWPtr hwp)
4251.4Sdholland{
4261.4Sdholland    return minb(VGA_FEATURE_R);
4271.4Sdholland}
4281.4Sdholland
4291.4Sdhollandstatic void
4301.4SdhollandmmioWriteFCR(vgaHWPtr hwp, CARD8 value)
4311.3Sdholland{
4321.3Sdholland    moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
4331.3Sdholland}
4341.3Sdholland
4351.3Sdhollandstatic void
4361.3SdhollandmmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
4371.3Sdholland{
4381.3Sdholland    if (hwp->paletteEnabled)
4391.3Sdholland        index &= ~0x20;
4401.3Sdholland    else
4411.3Sdholland        index |= 0x20;
4421.3Sdholland
4431.3Sdholland    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
4441.3Sdholland    moutb(VGA_ATTR_INDEX, index);
4451.3Sdholland    moutb(VGA_ATTR_DATA_W, value);
4461.3Sdholland}
4471.3Sdholland
4481.3Sdhollandstatic CARD8
4491.3SdhollandmmioReadAttr(vgaHWPtr hwp, CARD8 index)
4501.3Sdholland{
4511.3Sdholland    if (hwp->paletteEnabled)
4521.3Sdholland        index &= ~0x20;
4531.3Sdholland    else
4541.3Sdholland        index |= 0x20;
4551.3Sdholland
4561.3Sdholland    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
4571.3Sdholland    moutb(VGA_ATTR_INDEX, index);
4581.3Sdholland    return minb(VGA_ATTR_DATA_R);
4591.3Sdholland}
4601.1Smatt
4611.1Smattstatic void
4621.1SmattmmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
4631.1Smatt{
4641.1Smatt    moutb(VGA_MISC_OUT_W, value);
4651.1Smatt}
4661.1Smatt
4671.1Smattstatic CARD8
4681.3SdhollandmmioReadMiscOut(vgaHWPtr hwp)
4691.1Smatt{
4701.1Smatt    return minb(VGA_MISC_OUT_R);
4711.3Sdholland}
4721.1Smatt
4731.3Sdhollandstatic void
4741.1SmattmmioEnablePalette(vgaHWPtr hwp)
4751.1Smatt{
4761.1Smatt    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
4771.3Sdholland    moutb(VGA_ATTR_INDEX, 0x00);
4781.1Smatt    hwp->paletteEnabled = TRUE;
4791.1Smatt}
4801.1Smatt
4811.1Smattstatic void
4821.1SmattmmioDisablePalette(vgaHWPtr hwp)
4831.3Sdholland{
4841.1Smatt    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
4851.1Smatt    moutb(VGA_ATTR_INDEX, 0x20);
4861.3Sdholland    hwp->paletteEnabled = FALSE;
4871.1Smatt}
4881.3Sdholland
4891.1Smattstatic void
4901.3SdhollandmmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
4911.1Smatt{
4921.3Sdholland    moutb(VGA_DAC_MASK, value);
4931.3Sdholland}
4941.3Sdholland
4951.3Sdhollandstatic CARD8
4961.3SdhollandmmioReadDacMask(vgaHWPtr hwp)
4971.3Sdholland{
4981.3Sdholland    return minb(VGA_DAC_MASK);
4991.3Sdholland}
5001.3Sdholland
5011.3Sdhollandstatic void
5021.3SdhollandmmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
5031.3Sdholland{
5041.3Sdholland    moutb(VGA_DAC_READ_ADDR, value);
5051.3Sdholland}
5061.3Sdholland
5071.3Sdhollandstatic void
5081.3SdhollandmmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
5091.3Sdholland{
5101.3Sdholland    moutb(VGA_DAC_WRITE_ADDR, value);
5111.3Sdholland}
5121.3Sdholland
5131.3Sdhollandstatic void
5141.3SdhollandmmioWriteDacData(vgaHWPtr hwp, CARD8 value)
5151.3Sdholland{
5161.3Sdholland    moutb(VGA_DAC_DATA, value);
5171.3Sdholland}
5181.3Sdholland
5191.3Sdhollandstatic CARD8
5201.3SdhollandmmioReadDacData(vgaHWPtr hwp)
5211.3Sdholland{
5221.3Sdholland    return minb(VGA_DAC_DATA);
5231.3Sdholland}
5241.3Sdholland
5251.3Sdhollandstatic CARD8
5261.3SdhollandmmioReadEnable(vgaHWPtr hwp)
5271.3Sdholland{
5281.3Sdholland    return minb(VGA_ENABLE);
5291.3Sdholland}
5301.3Sdholland
5311.3Sdhollandstatic void
5321.3SdhollandmmioWriteEnable(vgaHWPtr hwp, CARD8 value)
5331.3Sdholland{
5341.3Sdholland    moutb(VGA_ENABLE, value);
5351.3Sdholland}
5361.3Sdholland
5371.3Sdhollandvoid
5381.3SdhollandvgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
5391.3Sdholland{
5401.3Sdholland    hwp->writeCrtc = mmioWriteCrtc;
5411.3Sdholland    hwp->readCrtc = mmioReadCrtc;
5421.3Sdholland    hwp->writeGr = mmioWriteGr;
5431.3Sdholland    hwp->readGr = mmioReadGr;
5441.3Sdholland    hwp->readST00 = mmioReadST00;
5451.3Sdholland    hwp->readST01 = mmioReadST01;
5461.3Sdholland    hwp->readFCR = mmioReadFCR;
5471.3Sdholland    hwp->writeFCR = mmioWriteFCR;
5481.3Sdholland    hwp->writeAttr = mmioWriteAttr;
5491.3Sdholland    hwp->readAttr = mmioReadAttr;
5501.3Sdholland    hwp->writeSeq = mmioWriteSeq;
5511.3Sdholland    hwp->readSeq = mmioReadSeq;
5521.3Sdholland    hwp->writeMiscOut = mmioWriteMiscOut;
5531.3Sdholland    hwp->readMiscOut = mmioReadMiscOut;
5541.3Sdholland    hwp->enablePalette = mmioEnablePalette;
5551.3Sdholland    hwp->disablePalette = mmioDisablePalette;
5561.3Sdholland    hwp->writeDacMask = mmioWriteDacMask;
5571.3Sdholland    hwp->readDacMask = mmioReadDacMask;
5581.3Sdholland    hwp->writeDacWriteAddr = mmioWriteDacWriteAddr;
5591.3Sdholland    hwp->writeDacReadAddr = mmioWriteDacReadAddr;
5601.3Sdholland    hwp->writeDacData = mmioWriteDacData;
5611.3Sdholland    hwp->readDacData = mmioReadDacData;
5621.3Sdholland    hwp->MMIOBase = base;
5631.3Sdholland    hwp->MMIOOffset = offset;
5641.1Smatt    hwp->readEnable = mmioReadEnable;
5651.3Sdholland    hwp->writeEnable = mmioWriteEnable;
5661.1Smatt}
5671.1Smatt
5681.1Smatt/*
5691.1Smatt * vgaHWProtect --
5701.1Smatt *	Protect VGA registers and memory from corruption during loads.
5711.1Smatt */
5721.1Smatt
5731.3Sdhollandvoid
5741.3SdhollandvgaHWProtect(ScrnInfoPtr pScrn, Bool on)
5751.3Sdholland{
5761.3Sdholland    vgaHWPtr hwp = VGAHWPTR(pScrn);
5771.3Sdholland
5781.3Sdholland    unsigned char tmp;
5791.3Sdholland
5801.3Sdholland    if (pScrn->vtSema) {
5811.3Sdholland        if (on) {
5821.3Sdholland            /*
5831.3Sdholland             * Turn off screen and disable sequencer.
5841.3Sdholland             */
5851.3Sdholland            tmp = hwp->readSeq(hwp, 0x01);
5861.3Sdholland
5871.3Sdholland            vgaHWSeqReset(hwp, TRUE);   /* start synchronous reset */
5881.3Sdholland            hwp->writeSeq(hwp, 0x01, tmp | 0x20);       /* disable the display */
5891.3Sdholland
5901.3Sdholland            hwp->enablePalette(hwp);
5911.3Sdholland        }
5921.3Sdholland        else {
5931.3Sdholland            /*
5941.3Sdholland             * Reenable sequencer, then turn on screen.
5951.3Sdholland             */
5961.3Sdholland
5971.3Sdholland            tmp = hwp->readSeq(hwp, 0x01);
5981.3Sdholland
5991.3Sdholland            hwp->writeSeq(hwp, 0x01, tmp & ~0x20);      /* reenable display */
6001.3Sdholland            vgaHWSeqReset(hwp, FALSE);  /* clear synchronousreset */
6011.3Sdholland
6021.3Sdholland            hwp->disablePalette(hwp);
6031.3Sdholland        }
6041.3Sdholland    }
6051.3Sdholland}
6061.3Sdholland
6071.3SdhollandvgaHWProtectProc *
6081.3SdhollandvgaHWProtectWeak(void)
6091.3Sdholland{
6101.3Sdholland    return vgaHWProtect;
6111.3Sdholland}
6121.3Sdholland
6131.3Sdholland/*
6141.3Sdholland * vgaHWBlankScreen -- blank the screen.
6151.3Sdholland */
6161.3Sdholland
6171.3Sdhollandvoid
6181.3SdhollandvgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
6191.3Sdholland{
6201.3Sdholland    vgaHWPtr hwp = VGAHWPTR(pScrn);
6211.3Sdholland    unsigned char scrn;
6221.3Sdholland
6231.3Sdholland    scrn = hwp->readSeq(hwp, 0x01);
6241.3Sdholland
6251.3Sdholland    if (on) {
6261.3Sdholland        scrn &= ~0x20;          /* enable screen */
6271.3Sdholland    }
6281.3Sdholland    else {
6291.3Sdholland        scrn |= 0x20;           /* blank screen */
6301.3Sdholland    }
6311.3Sdholland
6321.3Sdholland    vgaHWSeqReset(hwp, TRUE);
6331.3Sdholland    hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
6341.3Sdholland    vgaHWSeqReset(hwp, FALSE);
6351.3Sdholland}
6361.3Sdholland
6371.3SdhollandvgaHWBlankScreenProc *
6381.3SdhollandvgaHWBlankScreenWeak(void)
6391.3Sdholland{
6401.3Sdholland    return vgaHWBlankScreen;
6411.3Sdholland}
6421.3Sdholland
6431.3Sdholland/*
6441.3Sdholland * vgaHWSaveScreen -- blank the screen.
6451.3Sdholland */
6461.3Sdholland
6471.3SdhollandBool
6481.3SdhollandvgaHWSaveScreen(ScreenPtr pScreen, int mode)
6491.3Sdholland{
6501.3Sdholland    ScrnInfoPtr pScrn = NULL;
6511.3Sdholland    Bool on;
6521.3Sdholland
6531.4Sdholland    if (pScreen != NULL)
6541.3Sdholland        pScrn = xf86ScreenToScrn(pScreen);
6551.3Sdholland
6561.3Sdholland    on = xf86IsUnblank(mode);
6571.3Sdholland
6581.3Sdholland#if 0
6591.3Sdholland    if (on)
6601.3Sdholland        SetTimeSinceLastInputEvent();
6611.3Sdholland#endif
6621.3Sdholland
6631.3Sdholland    if ((pScrn != NULL) && pScrn->vtSema) {
6641.3Sdholland        vgaHWBlankScreen(pScrn, on);
6651.3Sdholland    }
6661.3Sdholland    return TRUE;
6671.3Sdholland}
6681.3Sdholland
6691.3Sdholland/*
6701.3Sdholland * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
6711.3Sdholland *
6721.3Sdholland * This generic VGA function can only set the Off and On modes.  If the
6731.3Sdholland * Standby and Suspend modes are to be supported, a chip specific replacement
6741.3Sdholland * for this function must be written.
6751.3Sdholland */
6761.3Sdholland
6771.3Sdhollandvoid
6781.3SdhollandvgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
6791.3Sdholland{
6801.3Sdholland    unsigned char seq1 = 0, crtc17 = 0;
6811.3Sdholland    vgaHWPtr hwp = VGAHWPTR(pScrn);
6821.3Sdholland
6831.3Sdholland    if (!pScrn->vtSema)
6841.3Sdholland        return;
6851.3Sdholland
6861.3Sdholland    switch (PowerManagementMode) {
6871.3Sdholland    case DPMSModeOn:
6881.3Sdholland        /* Screen: On; HSync: On, VSync: On */
6891.3Sdholland        seq1 = 0x00;
6901.3Sdholland        crtc17 = 0x80;
6911.3Sdholland        break;
6921.3Sdholland    case DPMSModeStandby:
6931.3Sdholland        /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
6941.3Sdholland        seq1 = 0x20;
6951.3Sdholland        crtc17 = 0x80;
6961.3Sdholland        break;
6971.3Sdholland    case DPMSModeSuspend:
6981.3Sdholland        /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
6991.3Sdholland        seq1 = 0x20;
7001.3Sdholland        crtc17 = 0x80;
7011.3Sdholland        break;
7021.3Sdholland    case DPMSModeOff:
7031.3Sdholland        /* Screen: Off; HSync: Off, VSync: Off */
7041.3Sdholland        seq1 = 0x20;
7051.3Sdholland        crtc17 = 0x00;
7061.3Sdholland        break;
7071.3Sdholland    }
7081.3Sdholland    hwp->writeSeq(hwp, 0x00, 0x01);     /* Synchronous Reset */
7091.3Sdholland    seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
7101.3Sdholland    hwp->writeSeq(hwp, 0x01, seq1);
7111.3Sdholland    crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
7121.3Sdholland    usleep(10000);
7131.3Sdholland    hwp->writeCrtc(hwp, 0x17, crtc17);
7141.3Sdholland    hwp->writeSeq(hwp, 0x00, 0x03);     /* End Reset */
7151.3Sdholland}
7161.3Sdholland
7171.3Sdholland/*
7181.3Sdholland * vgaHWSeqReset
7191.3Sdholland *      perform a sequencer reset.
7201.3Sdholland */
7211.3Sdholland
7221.3Sdhollandvoid
7231.3SdhollandvgaHWSeqReset(vgaHWPtr hwp, Bool start)
7241.3Sdholland{
7251.3Sdholland    if (start)
7261.3Sdholland        hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
7271.3Sdholland    else
7281.3Sdholland        hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
7291.3Sdholland}
7301.3Sdholland
7311.3Sdhollandvoid
7321.3SdhollandvgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
7331.3Sdholland{
7341.3Sdholland#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
7351.3Sdholland    vgaHWPtr hwp = VGAHWPTR(scrninfp);
7361.3Sdholland    int savedIOBase;
7371.3Sdholland    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
7381.3Sdholland    Bool doMap = FALSE;
7391.3Sdholland
7401.3Sdholland    /* If nothing to do, return now */
7411.3Sdholland    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
7421.3Sdholland        return;
7431.3Sdholland
7441.3Sdholland    if (hwp->Base == NULL) {
7451.3Sdholland        doMap = TRUE;
7461.3Sdholland        if (!vgaHWMapMem(scrninfp)) {
7471.3Sdholland            xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
7481.3Sdholland                       "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
7491.3Sdholland            return;
7501.3Sdholland        }
7511.3Sdholland    }
7521.3Sdholland
7531.3Sdholland    /* save the registers that are needed here */
7541.3Sdholland    miscOut = hwp->readMiscOut(hwp);
7551.3Sdholland    attr10 = hwp->readAttr(hwp, 0x10);
7561.3Sdholland    gr1 = hwp->readGr(hwp, 0x01);
7571.3Sdholland    gr3 = hwp->readGr(hwp, 0x03);
7581.3Sdholland    gr4 = hwp->readGr(hwp, 0x04);
7591.3Sdholland    gr5 = hwp->readGr(hwp, 0x05);
7601.3Sdholland    gr6 = hwp->readGr(hwp, 0x06);
7611.3Sdholland    gr8 = hwp->readGr(hwp, 0x08);
7621.3Sdholland    seq2 = hwp->readSeq(hwp, 0x02);
7631.3Sdholland    seq4 = hwp->readSeq(hwp, 0x04);
7641.3Sdholland
7651.3Sdholland    /* save hwp->IOBase and temporarily set it for colour mode */
7661.3Sdholland    savedIOBase = hwp->IOBase;
7671.3Sdholland    hwp->IOBase = VGA_IOBASE_COLOR;
7681.3Sdholland
7691.3Sdholland    /* Force into colour mode */
7701.3Sdholland    hwp->writeMiscOut(hwp, miscOut | 0x01);
7711.3Sdholland
7721.3Sdholland    vgaHWBlankScreen(scrninfp, FALSE);
7731.3Sdholland
7741.1Smatt    /*
7751.1Smatt     * here we temporarily switch to 16 colour planar mode, to simply
776     * copy the font-info and saved text.
777     *
778     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
779     */
780#if 0
781    hwp->writeAttr(hwp, 0x10, 0x01);    /* graphics mode */
782#endif
783
784    hwp->writeSeq(hwp, 0x04, 0x06);     /* enable plane graphics */
785    hwp->writeGr(hwp, 0x05, 0x00);      /* write mode 0, read mode 0 */
786    hwp->writeGr(hwp, 0x06, 0x05);      /* set graphics */
787
788    if (scrninfp->depth == 4) {
789        /* GJA */
790        hwp->writeGr(hwp, 0x03, 0x00);  /* don't rotate, write unmodified */
791        hwp->writeGr(hwp, 0x08, 0xFF);  /* write all bits in a byte */
792        hwp->writeGr(hwp, 0x01, 0x00);  /* all planes come from CPU */
793    }
794
795#if SAVE_FONT1
796    if (hwp->FontInfo1) {
797        hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
798        hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
799        slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
800    }
801#endif
802
803#if SAVE_FONT2
804    if (hwp->FontInfo2) {
805        hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
806        hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
807        slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
808    }
809#endif
810
811#if SAVE_TEXT
812    if (hwp->TextInfo) {
813        hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
814        hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
815        slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
816        hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
817        hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
818        slowbcopy_tobus((unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
819                        hwp->Base, TEXT_AMOUNT);
820    }
821#endif
822
823    vgaHWBlankScreen(scrninfp, TRUE);
824
825    /* restore the registers that were changed */
826    hwp->writeMiscOut(hwp, miscOut);
827    hwp->writeAttr(hwp, 0x10, attr10);
828    hwp->writeGr(hwp, 0x01, gr1);
829    hwp->writeGr(hwp, 0x03, gr3);
830    hwp->writeGr(hwp, 0x04, gr4);
831    hwp->writeGr(hwp, 0x05, gr5);
832    hwp->writeGr(hwp, 0x06, gr6);
833    hwp->writeGr(hwp, 0x08, gr8);
834    hwp->writeSeq(hwp, 0x02, seq2);
835    hwp->writeSeq(hwp, 0x04, seq4);
836    hwp->IOBase = savedIOBase;
837
838    if (doMap)
839        vgaHWUnmapMem(scrninfp);
840
841#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
842}
843
844void
845vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
846{
847    vgaHWPtr hwp = VGAHWPTR(scrninfp);
848    int i;
849
850    if (restore->MiscOutReg & 0x01)
851        hwp->IOBase = VGA_IOBASE_COLOR;
852    else
853        hwp->IOBase = VGA_IOBASE_MONO;
854
855    hwp->writeMiscOut(hwp, restore->MiscOutReg);
856
857    for (i = 1; i < restore->numSequencer; i++)
858        hwp->writeSeq(hwp, i, restore->Sequencer[i]);
859
860    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
861    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
862
863    for (i = 0; i < restore->numCRTC; i++)
864        hwp->writeCrtc(hwp, i, restore->CRTC[i]);
865
866    for (i = 0; i < restore->numGraphics; i++)
867        hwp->writeGr(hwp, i, restore->Graphics[i]);
868
869    hwp->enablePalette(hwp);
870    for (i = 0; i < restore->numAttribute; i++)
871        hwp->writeAttr(hwp, i, restore->Attribute[i]);
872    hwp->disablePalette(hwp);
873}
874
875void
876vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
877{
878    vgaHWPtr hwp = VGAHWPTR(scrninfp);
879    int i;
880
881#if 0
882    hwp->enablePalette(hwp);
883#endif
884
885    hwp->writeDacMask(hwp, 0xFF);
886    hwp->writeDacWriteAddr(hwp, 0x00);
887    for (i = 0; i < 768; i++) {
888        hwp->writeDacData(hwp, restore->DAC[i]);
889        DACDelay(hwp);
890    }
891
892    hwp->disablePalette(hwp);
893}
894
895/*
896 * vgaHWRestore --
897 *      restore the VGA state
898 */
899
900void
901vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
902{
903    if (flags & VGA_SR_MODE)
904        vgaHWRestoreMode(scrninfp, restore);
905
906    if (flags & VGA_SR_FONTS)
907        vgaHWRestoreFonts(scrninfp, restore);
908
909    if (flags & VGA_SR_CMAP)
910        vgaHWRestoreColormap(scrninfp, restore);
911}
912
913void
914vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
915{
916#if  SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
917    vgaHWPtr hwp = VGAHWPTR(scrninfp);
918    int savedIOBase;
919    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
920    Bool doMap = FALSE;
921
922    if (hwp->Base == NULL) {
923        doMap = TRUE;
924        if (!vgaHWMapMem(scrninfp)) {
925            xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
926                       "vgaHWSaveFonts: vgaHWMapMem() failed\n");
927            return;
928        }
929    }
930
931    /* If in graphics mode, don't save anything */
932    attr10 = hwp->readAttr(hwp, 0x10);
933    if (attr10 & 0x01)
934        return;
935
936    /* save the registers that are needed here */
937    miscOut = hwp->readMiscOut(hwp);
938    gr4 = hwp->readGr(hwp, 0x04);
939    gr5 = hwp->readGr(hwp, 0x05);
940    gr6 = hwp->readGr(hwp, 0x06);
941    seq2 = hwp->readSeq(hwp, 0x02);
942    seq4 = hwp->readSeq(hwp, 0x04);
943
944    /* save hwp->IOBase and temporarily set it for colour mode */
945    savedIOBase = hwp->IOBase;
946    hwp->IOBase = VGA_IOBASE_COLOR;
947
948    /* Force into colour mode */
949    hwp->writeMiscOut(hwp, miscOut | 0x01);
950
951    vgaHWBlankScreen(scrninfp, FALSE);
952
953    /*
954     * get the character sets, and text screen if required
955     */
956    /*
957     * Here we temporarily switch to 16 colour planar mode, to simply
958     * copy the font-info
959     *
960     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
961     */
962#if 0
963    hwp->writeAttr(hwp, 0x10, 0x01);    /* graphics mode */
964#endif
965
966    hwp->writeSeq(hwp, 0x04, 0x06);     /* enable plane graphics */
967    hwp->writeGr(hwp, 0x05, 0x00);      /* write mode 0, read mode 0 */
968    hwp->writeGr(hwp, 0x06, 0x05);      /* set graphics */
969
970#if SAVE_FONT1
971    if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) {
972        hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
973        hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
974        slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
975    }
976#endif                          /* SAVE_FONT1 */
977#if SAVE_FONT2
978    if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) {
979        hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
980        hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
981        slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
982    }
983#endif                          /* SAVE_FONT2 */
984#if SAVE_TEXT
985    if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) {
986        hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
987        hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
988        slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
989        hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
990        hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
991        slowbcopy_frombus(hwp->Base,
992                          (unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
993                          TEXT_AMOUNT);
994    }
995#endif                          /* SAVE_TEXT */
996
997    /* Restore clobbered registers */
998    hwp->writeAttr(hwp, 0x10, attr10);
999    hwp->writeSeq(hwp, 0x02, seq2);
1000    hwp->writeSeq(hwp, 0x04, seq4);
1001    hwp->writeGr(hwp, 0x04, gr4);
1002    hwp->writeGr(hwp, 0x05, gr5);
1003    hwp->writeGr(hwp, 0x06, gr6);
1004    hwp->writeMiscOut(hwp, miscOut);
1005    hwp->IOBase = savedIOBase;
1006
1007    vgaHWBlankScreen(scrninfp, TRUE);
1008
1009    if (doMap)
1010        vgaHWUnmapMem(scrninfp);
1011
1012#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
1013}
1014
1015void
1016vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
1017{
1018    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1019    int i;
1020
1021    save->MiscOutReg = hwp->readMiscOut(hwp);
1022    if (save->MiscOutReg & 0x01)
1023        hwp->IOBase = VGA_IOBASE_COLOR;
1024    else
1025        hwp->IOBase = VGA_IOBASE_MONO;
1026
1027    for (i = 0; i < save->numCRTC; i++) {
1028        save->CRTC[i] = hwp->readCrtc(hwp, i);
1029        DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1030    }
1031
1032    hwp->enablePalette(hwp);
1033    for (i = 0; i < save->numAttribute; i++) {
1034        save->Attribute[i] = hwp->readAttr(hwp, i);
1035        DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1036    }
1037    hwp->disablePalette(hwp);
1038
1039    for (i = 0; i < save->numGraphics; i++) {
1040        save->Graphics[i] = hwp->readGr(hwp, i);
1041        DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1042    }
1043
1044    for (i = 1; i < save->numSequencer; i++) {
1045        save->Sequencer[i] = hwp->readSeq(hwp, i);
1046        DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
1047    }
1048}
1049
1050void
1051vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
1052{
1053    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1054    Bool readError = FALSE;
1055    int i;
1056
1057#ifdef NEED_SAVED_CMAP
1058    /*
1059     * Some ET4000 chips from 1991 have a HW bug that prevents the reading
1060     * of the color lookup table.  Mask rev 9042EAI is known to have this bug.
1061     *
1062     * If the colourmap is not readable, we set the saved map to a default
1063     * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
1064     * Cards" 2nd ed).
1065     */
1066
1067    /* Only save it once */
1068    if (hwp->cmapSaved)
1069        return;
1070
1071#if 0
1072    hwp->enablePalette(hwp);
1073#endif
1074
1075    hwp->writeDacMask(hwp, 0xFF);
1076
1077    /*
1078     * check if we can read the lookup table
1079     */
1080    hwp->writeDacReadAddr(hwp, 0x00);
1081    for (i = 0; i < 6; i++) {
1082        save->DAC[i] = hwp->readDacData(hwp);
1083        switch (i % 3) {
1084        case 0:
1085            DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1086            break;
1087        case 1:
1088            DebugF("0x%02x, ", save->DAC[i]);
1089            break;
1090        case 2:
1091            DebugF("0x%02x\n", save->DAC[i]);
1092        }
1093    }
1094
1095    /*
1096     * Check if we can read the palette -
1097     * use foreground color to prevent flashing.
1098     */
1099    hwp->writeDacWriteAddr(hwp, 0x01);
1100    for (i = 3; i < 6; i++)
1101        hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
1102    hwp->writeDacReadAddr(hwp, 0x01);
1103    for (i = 3; i < 6; i++) {
1104        if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
1105            readError = TRUE;
1106    }
1107    hwp->writeDacWriteAddr(hwp, 0x01);
1108    for (i = 3; i < 6; i++)
1109        hwp->writeDacData(hwp, save->DAC[i]);
1110
1111    if (readError) {
1112        /*
1113         * save the default lookup table
1114         */
1115        memmove(save->DAC, defaultDAC, 768);
1116        xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
1117                   "Cannot read colourmap from VGA.  Will restore with default\n");
1118    }
1119    else {
1120        /* save the colourmap */
1121        hwp->writeDacReadAddr(hwp, 0x02);
1122        for (i = 6; i < 768; i++) {
1123            save->DAC[i] = hwp->readDacData(hwp);
1124            DACDelay(hwp);
1125            switch (i % 3) {
1126            case 0:
1127                DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1128                break;
1129            case 1:
1130                DebugF("0x%02x, ", save->DAC[i]);
1131                break;
1132            case 2:
1133                DebugF("0x%02x\n", save->DAC[i]);
1134            }
1135        }
1136    }
1137
1138    hwp->disablePalette(hwp);
1139    hwp->cmapSaved = TRUE;
1140#endif
1141}
1142
1143/*
1144 * vgaHWSave --
1145 *      save the current VGA state
1146 */
1147
1148void
1149vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1150{
1151    if (save == NULL)
1152        return;
1153
1154    if (flags & VGA_SR_CMAP)
1155        vgaHWSaveColormap(scrninfp, save);
1156
1157    if (flags & VGA_SR_MODE)
1158        vgaHWSaveMode(scrninfp, save);
1159
1160    if (flags & VGA_SR_FONTS)
1161        vgaHWSaveFonts(scrninfp, save);
1162}
1163
1164/*
1165 * vgaHWInit --
1166 *      Handle the initialization, etc. of a screen.
1167 *      Return FALSE on failure.
1168 */
1169
1170Bool
1171vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
1172{
1173    unsigned int i;
1174    vgaHWPtr hwp;
1175    vgaRegPtr regp;
1176    int depth = scrninfp->depth;
1177
1178    /*
1179     * make sure the vgaHWRec is allocated
1180     */
1181    if (!vgaHWGetHWRec(scrninfp))
1182        return FALSE;
1183    hwp = VGAHWPTR(scrninfp);
1184    regp = &hwp->ModeReg;
1185
1186    /*
1187     * compute correct Hsync & Vsync polarity
1188     */
1189    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
1190        && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
1191        regp->MiscOutReg = 0x23;
1192        if (mode->Flags & V_NHSYNC)
1193            regp->MiscOutReg |= 0x40;
1194        if (mode->Flags & V_NVSYNC)
1195            regp->MiscOutReg |= 0x80;
1196    }
1197    else {
1198        int VDisplay = mode->VDisplay;
1199
1200        if (mode->Flags & V_DBLSCAN)
1201            VDisplay *= 2;
1202        if (mode->VScan > 1)
1203            VDisplay *= mode->VScan;
1204        if (VDisplay < 400)
1205            regp->MiscOutReg = 0xA3;    /* +hsync -vsync */
1206        else if (VDisplay < 480)
1207            regp->MiscOutReg = 0x63;    /* -hsync +vsync */
1208        else if (VDisplay < 768)
1209            regp->MiscOutReg = 0xE3;    /* -hsync -vsync */
1210        else
1211            regp->MiscOutReg = 0x23;    /* +hsync +vsync */
1212    }
1213
1214    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1215
1216    /*
1217     * Time Sequencer
1218     */
1219    if (depth == 4)
1220        regp->Sequencer[0] = 0x02;
1221    else
1222        regp->Sequencer[0] = 0x00;
1223    if (mode->Flags & V_CLKDIV2)
1224        regp->Sequencer[1] = 0x09;
1225    else
1226        regp->Sequencer[1] = 0x01;
1227    if (depth == 1)
1228        regp->Sequencer[2] = 1 << BIT_PLANE;
1229    else
1230        regp->Sequencer[2] = 0x0F;
1231    regp->Sequencer[3] = 0x00;  /* Font select */
1232    if (depth < 8)
1233        regp->Sequencer[4] = 0x06;      /* Misc */
1234    else
1235        regp->Sequencer[4] = 0x0E;      /* Misc */
1236
1237    /*
1238     * CRTC Controller
1239     */
1240    regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5;
1241    regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1;
1242    regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1;
1243    regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1244    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1245    if (i < 0x80)
1246        regp->CRTC[3] |= i;
1247    regp->CRTC[4] = (mode->CrtcHSyncStart >> 3);
1248    regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1249        | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1250    regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF;
1251    regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1252        | (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1253        | ((mode->CrtcVSyncStart & 0x100) >> 6)
1254        | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1255        | 0x10 | (((mode->CrtcVTotal - 2) & 0x200) >> 4)
1256        | (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
1257        | ((mode->CrtcVSyncStart & 0x200) >> 2);
1258    regp->CRTC[8] = 0x00;
1259    regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
1260    if (mode->Flags & V_DBLSCAN)
1261        regp->CRTC[9] |= 0x80;
1262    if (mode->VScan >= 32)
1263        regp->CRTC[9] |= 0x1F;
1264    else if (mode->VScan > 1)
1265        regp->CRTC[9] |= mode->VScan - 1;
1266    regp->CRTC[10] = 0x00;
1267    regp->CRTC[11] = 0x00;
1268    regp->CRTC[12] = 0x00;
1269    regp->CRTC[13] = 0x00;
1270    regp->CRTC[14] = 0x00;
1271    regp->CRTC[15] = 0x00;
1272    regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
1273    regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
1274    regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
1275    regp->CRTC[19] = scrninfp->displayWidth >> 4;       /* just a guess */
1276    regp->CRTC[20] = 0x00;
1277    regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
1278    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1279    if (depth < 8)
1280        regp->CRTC[23] = 0xE3;
1281    else
1282        regp->CRTC[23] = 0xC3;
1283    regp->CRTC[24] = 0xFF;
1284
1285    vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1286    vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1287
1288    /*
1289     * Theory resumes here....
1290     */
1291
1292    /*
1293     * Graphics Display Controller
1294     */
1295    regp->Graphics[0] = 0x00;
1296    regp->Graphics[1] = 0x00;
1297    regp->Graphics[2] = 0x00;
1298    regp->Graphics[3] = 0x00;
1299    if (depth == 1) {
1300        regp->Graphics[4] = BIT_PLANE;
1301        regp->Graphics[5] = 0x00;
1302    }
1303    else {
1304        regp->Graphics[4] = 0x00;
1305        if (depth == 4)
1306            regp->Graphics[5] = 0x02;
1307        else
1308            regp->Graphics[5] = 0x40;
1309    }
1310    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
1311    regp->Graphics[7] = 0x0F;
1312    regp->Graphics[8] = 0xFF;
1313
1314    if (depth == 1) {
1315        /* Initialise the Mono map according to which bit-plane gets used */
1316
1317        Bool flipPixels = xf86GetFlipPixels();
1318
1319        for (i = 0; i < 16; i++)
1320            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1321                regp->Attribute[i] = WHITE_VALUE;
1322            else
1323                regp->Attribute[i] = BLACK_VALUE;
1324
1325        regp->Attribute[16] = 0x01;     /* -VGA2- *//* wrong for the ET4000 */
1326        if (!hwp->ShowOverscan)
1327            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
1328    }
1329    else {
1330        regp->Attribute[0] = 0x00;      /* standard colormap translation */
1331        regp->Attribute[1] = 0x01;
1332        regp->Attribute[2] = 0x02;
1333        regp->Attribute[3] = 0x03;
1334        regp->Attribute[4] = 0x04;
1335        regp->Attribute[5] = 0x05;
1336        regp->Attribute[6] = 0x06;
1337        regp->Attribute[7] = 0x07;
1338        regp->Attribute[8] = 0x08;
1339        regp->Attribute[9] = 0x09;
1340        regp->Attribute[10] = 0x0A;
1341        regp->Attribute[11] = 0x0B;
1342        regp->Attribute[12] = 0x0C;
1343        regp->Attribute[13] = 0x0D;
1344        regp->Attribute[14] = 0x0E;
1345        regp->Attribute[15] = 0x0F;
1346        if (depth == 4)
1347            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1348        else
1349            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1350        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1351    }
1352    regp->Attribute[18] = 0x0F;
1353    regp->Attribute[19] = 0x00;
1354    regp->Attribute[20] = 0x00;
1355
1356    return TRUE;
1357}
1358
1359    /*
1360     * OK, so much for theory.  Now, let's deal with the >real< world...
1361     *
1362     * The above CRTC settings are precise in theory, except that many, if not
1363     * most, VGA clones fail to reset the blanking signal when the character or
1364     * line counter reaches [HV]Total.  In this case, the signal is only
1365     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1366     * the case may be) at the start of the >next< scanline or frame, which
1367     * means only part of the screen shows.  This affects how null overscans
1368     * are to be implemented on such adapters.
1369     *
1370     * Henceforth, VGA cores that implement this broken, but unfortunately
1371     * common, behaviour are to be designated as KGA's, in honour of Koen
1372     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1373     * a series of events that led to the discovery of this problem.
1374     *
1375     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1376     * some in both, others in neither.  Don't let anyone tell you there is
1377     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1378     * that Hilbert spaces are not yet implemented in this industry.
1379     *
1380     * The following implements a trick suggested by David Dawes.  This sets
1381     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1382     * 0-point, and decrements it by one otherwise.  In the latter case, this
1383     * will produce a left and/or top overscan which the colourmap code will
1384     * (still) need to ensure is as close to black as possible.  This will make
1385     * the behaviour consistent across all chipsets, while allowing all
1386     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1387     * following in their own copy of this code.
1388     *
1389     * --  TSI @ UQV,  1998.08.21
1390     */
1391
1392CARD32
1393vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1394               unsigned int Flags)
1395{
1396    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1397    CARD32 ExtBits;
1398    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1399
1400    regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
1401        | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1402    regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
1403        | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1404    ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1405
1406    /* First the horizontal case */
1407    if ((Flags & KGA_FIX_OVERSCAN)
1408        && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
1409        int i = (regp->CRTC[3] & 0x1F)
1410            | ((regp->CRTC[5] & 0x80) >> 2)
1411            | ExtBits;
1412
1413        if (Flags & KGA_ENABLE_ON_ZERO) {
1414            if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1415                        & (0x3F | ExtBitMask)))
1416                && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1417                i = 0;
1418        }
1419        else if (Flags & KGA_BE_TOT_DEC)
1420            i--;
1421        regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1422        regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1423        ExtBits = i & ExtBitMask;
1424    }
1425    return ExtBits >> 6;
1426}
1427
1428    /*
1429     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1430     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1431     * very first scanline in a double- or multi-scanned mode.  This last case
1432     * needs further investigation.
1433     */
1434CARD32
1435vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1436               unsigned int Flags)
1437{
1438    CARD32 ExtBits;
1439    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1440    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1441
1442    /* If width is not known nBits should be 0. In this
1443     * case BitMask is set to 0 so we can check for it. */
1444    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1445    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1446
1447    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1448    ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1449
1450    if ((Flags & KGA_FIX_OVERSCAN)
1451        && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1452        /* Null top overscan */
1453    {
1454        int i = regp->CRTC[22] | ExtBits;
1455
1456        if (Flags & KGA_ENABLE_ON_ZERO) {
1457            if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1458                 || ((i > VBlankStart) &&       /* 8-bit case */
1459                     ((i & 0x7F) > (VBlankStart & 0x7F)))) &&   /* 7-bit case */
1460                !(regp->CRTC[9] & 0x9F))        /* 1 scanline/row */
1461                i = 0;
1462            else
1463                i = (i - 1);
1464        }
1465        else if (Flags & KGA_BE_TOT_DEC)
1466            i = (i - 1);
1467
1468        regp->CRTC[22] = i & 0xFF;
1469        ExtBits = i & 0xFF00;
1470    }
1471    return ExtBits >> 8;
1472}
1473
1474/*
1475 * these are some more hardware specific helpers, formerly in vga.c
1476 */
1477static void
1478vgaHWGetHWRecPrivate(void)
1479{
1480    if (vgaHWPrivateIndex < 0)
1481        vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1482    return;
1483}
1484
1485static void
1486vgaHWFreeRegs(vgaRegPtr regp)
1487{
1488    free(regp->CRTC);
1489
1490    regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
1491
1492    regp->numCRTC =
1493        regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
1494}
1495
1496static Bool
1497vgaHWAllocRegs(vgaRegPtr regp)
1498{
1499    unsigned char *buf;
1500
1501    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1502         regp->numAttribute) == 0)
1503        return FALSE;
1504
1505    buf = calloc(regp->numCRTC +
1506                 regp->numSequencer +
1507                 regp->numGraphics + regp->numAttribute, 1);
1508    if (!buf)
1509        return FALSE;
1510
1511    regp->CRTC = buf;
1512    regp->Sequencer = regp->CRTC + regp->numCRTC;
1513    regp->Graphics = regp->Sequencer + regp->numSequencer;
1514    regp->Attribute = regp->Graphics + regp->numGraphics;
1515
1516    return TRUE;
1517}
1518
1519Bool
1520vgaHWAllocDefaultRegs(vgaRegPtr regp)
1521{
1522    regp->numCRTC = VGA_NUM_CRTC;
1523    regp->numSequencer = VGA_NUM_SEQ;
1524    regp->numGraphics = VGA_NUM_GFX;
1525    regp->numAttribute = VGA_NUM_ATTR;
1526
1527    return vgaHWAllocRegs(regp);
1528}
1529
1530Bool
1531vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1532                  int numGraphics, int numAttribute)
1533{
1534#define VGAHWMINNUM(regtype) \
1535	((newMode.num##regtype < regp->num##regtype) ? \
1536	 (newMode.num##regtype) : (regp->num##regtype))
1537#define VGAHWCOPYREGSET(regtype) \
1538	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1539
1540    vgaRegRec newMode, newSaved;
1541    vgaRegPtr regp;
1542
1543    regp = &VGAHWPTR(scrp)->ModeReg;
1544    memcpy(&newMode, regp, sizeof(vgaRegRec));
1545
1546    /* allocate space for new registers */
1547
1548    regp = &newMode;
1549    regp->numCRTC = numCRTC;
1550    regp->numSequencer = numSequencer;
1551    regp->numGraphics = numGraphics;
1552    regp->numAttribute = numAttribute;
1553    if (!vgaHWAllocRegs(regp))
1554        return FALSE;
1555
1556    regp = &VGAHWPTR(scrp)->SavedReg;
1557    memcpy(&newSaved, regp, sizeof(vgaRegRec));
1558
1559    regp = &newSaved;
1560    regp->numCRTC = numCRTC;
1561    regp->numSequencer = numSequencer;
1562    regp->numGraphics = numGraphics;
1563    regp->numAttribute = numAttribute;
1564    if (!vgaHWAllocRegs(regp)) {
1565        vgaHWFreeRegs(&newMode);
1566        return FALSE;
1567    }
1568
1569    /* allocations succeeded, copy register data into new space */
1570
1571    regp = &VGAHWPTR(scrp)->ModeReg;
1572    VGAHWCOPYREGSET(CRTC);
1573    VGAHWCOPYREGSET(Sequencer);
1574    VGAHWCOPYREGSET(Graphics);
1575    VGAHWCOPYREGSET(Attribute);
1576
1577    regp = &VGAHWPTR(scrp)->SavedReg;
1578    VGAHWCOPYREGSET(CRTC);
1579    VGAHWCOPYREGSET(Sequencer);
1580    VGAHWCOPYREGSET(Graphics);
1581    VGAHWCOPYREGSET(Attribute);
1582
1583    /* free old register arrays */
1584
1585    regp = &VGAHWPTR(scrp)->ModeReg;
1586    vgaHWFreeRegs(regp);
1587    memcpy(regp, &newMode, sizeof(vgaRegRec));
1588
1589    regp = &VGAHWPTR(scrp)->SavedReg;
1590    vgaHWFreeRegs(regp);
1591    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1592
1593    return TRUE;
1594
1595#undef VGAHWMINNUM
1596#undef VGAHWCOPYREGSET
1597}
1598
1599Bool
1600vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1601{
1602    vgaHWFreeRegs(dst);
1603
1604    memcpy(dst, src, sizeof(vgaRegRec));
1605
1606    if (!vgaHWAllocRegs(dst))
1607        return FALSE;
1608
1609    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1610    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1611    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1612    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1613
1614    return TRUE;
1615}
1616
1617Bool
1618vgaHWGetHWRec(ScrnInfoPtr scrp)
1619{
1620    vgaRegPtr regp;
1621    vgaHWPtr hwp;
1622    int i;
1623
1624    /*
1625     * Let's make sure that the private exists and allocate one.
1626     */
1627    vgaHWGetHWRecPrivate();
1628    /*
1629     * New privates are always set to NULL, so we can check if the allocation
1630     * has already been done.
1631     */
1632    if (VGAHWPTR(scrp))
1633        return TRUE;
1634    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1635    regp = &VGAHWPTR(scrp)->ModeReg;
1636
1637    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1638        (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1639        free(hwp);
1640        return FALSE;
1641    }
1642
1643    if (scrp->bitsPerPixel == 1) {
1644        rgb blackColour = scrp->display->blackColour,
1645            whiteColour = scrp->display->whiteColour;
1646
1647        if (blackColour.red > 0x3F)
1648            blackColour.red = 0x3F;
1649        if (blackColour.green > 0x3F)
1650            blackColour.green = 0x3F;
1651        if (blackColour.blue > 0x3F)
1652            blackColour.blue = 0x3F;
1653
1654        if (whiteColour.red > 0x3F)
1655            whiteColour.red = 0x3F;
1656        if (whiteColour.green > 0x3F)
1657            whiteColour.green = 0x3F;
1658        if (whiteColour.blue > 0x3F)
1659            whiteColour.blue = 0x3F;
1660
1661        if ((blackColour.red == whiteColour.red) &&
1662            (blackColour.green == whiteColour.green) &&
1663            (blackColour.blue == whiteColour.blue)) {
1664            blackColour.red ^= 0x3F;
1665            blackColour.green ^= 0x3F;
1666            blackColour.blue ^= 0x3F;
1667        }
1668
1669        /*
1670         * initialize default colormap for monochrome
1671         */
1672        for (i = 0; i < 3; i++)
1673            regp->DAC[i] = 0x00;
1674        for (i = 3; i < 768; i++)
1675            regp->DAC[i] = 0x3F;
1676        i = BLACK_VALUE * 3;
1677        regp->DAC[i++] = blackColour.red;
1678        regp->DAC[i++] = blackColour.green;
1679        regp->DAC[i] = blackColour.blue;
1680        i = WHITE_VALUE * 3;
1681        regp->DAC[i++] = whiteColour.red;
1682        regp->DAC[i++] = whiteColour.green;
1683        regp->DAC[i] = whiteColour.blue;
1684        i = OVERSCAN_VALUE * 3;
1685        regp->DAC[i++] = 0x00;
1686        regp->DAC[i++] = 0x00;
1687        regp->DAC[i] = 0x00;
1688    }
1689    else {
1690        /* Set all colours to black */
1691        for (i = 0; i < 768; i++)
1692            regp->DAC[i] = 0x00;
1693        /* ... and the overscan */
1694        if (scrp->depth >= 4)
1695            regp->Attribute[OVERSCAN] = 0xFF;
1696    }
1697    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1698        xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1699        xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1700        regp->DAC[765] = 0x3F;
1701        regp->DAC[766] = 0x00;
1702        regp->DAC[767] = 0x3F;
1703        regp->Attribute[OVERSCAN] = 0xFF;
1704        hwp->ShowOverscan = TRUE;
1705    }
1706    else
1707        hwp->ShowOverscan = FALSE;
1708
1709    hwp->paletteEnabled = FALSE;
1710    hwp->cmapSaved = FALSE;
1711    hwp->MapSize = 0;
1712    hwp->pScrn = scrp;
1713
1714    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1715
1716    return TRUE;
1717}
1718
1719void
1720vgaHWFreeHWRec(ScrnInfoPtr scrp)
1721{
1722    if (vgaHWPrivateIndex >= 0) {
1723        vgaHWPtr hwp = VGAHWPTR(scrp);
1724
1725        if (!hwp)
1726            return;
1727
1728        pci_device_close_io(hwp->dev, hwp->io);
1729
1730        free(hwp->FontInfo1);
1731        free(hwp->FontInfo2);
1732        free(hwp->TextInfo);
1733
1734        vgaHWFreeRegs(&hwp->ModeReg);
1735        vgaHWFreeRegs(&hwp->SavedReg);
1736
1737        free(hwp);
1738        VGAHWPTRLVAL(scrp) = NULL;
1739    }
1740}
1741
1742Bool
1743vgaHWMapMem(ScrnInfoPtr scrp)
1744{
1745    vgaHWPtr hwp = VGAHWPTR(scrp);
1746
1747    if (hwp->Base)
1748        return TRUE;
1749
1750    /* If not set, initialise with the defaults */
1751    if (hwp->MapSize == 0)
1752        hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1753    if (hwp->MapPhys == 0)
1754        hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1755
1756    /*
1757     * Map as VIDMEM_MMIO_32BIT because WC
1758     * is bad when there is page flipping.
1759     * XXX This is not correct but we do it
1760     * for now.
1761     */
1762    DebugF("Mapping VGAMem\n");
1763    pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
1764                          PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
1765    return hwp->Base != NULL;
1766}
1767
1768void
1769vgaHWUnmapMem(ScrnInfoPtr scrp)
1770{
1771    vgaHWPtr hwp = VGAHWPTR(scrp);
1772
1773    if (hwp->Base == NULL)
1774        return;
1775
1776    DebugF("Unmapping VGAMem\n");
1777    pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
1778    hwp->Base = NULL;
1779}
1780
1781int
1782vgaHWGetIndex(void)
1783{
1784    return vgaHWPrivateIndex;
1785}
1786
1787void
1788vgaHWGetIOBase(vgaHWPtr hwp)
1789{
1790    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1791        VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1792    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1793                   "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
1794}
1795
1796void
1797vgaHWLock(vgaHWPtr hwp)
1798{
1799    /* Protect CRTC[0-7] */
1800    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1801}
1802
1803void
1804vgaHWUnlock(vgaHWPtr hwp)
1805{
1806    /* Unprotect CRTC[0-7] */
1807    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1808}
1809
1810void
1811vgaHWEnable(vgaHWPtr hwp)
1812{
1813    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1814}
1815
1816void
1817vgaHWDisable(vgaHWPtr hwp)
1818{
1819    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1820}
1821
1822static void
1823vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
1824                 VisualPtr pVisual)
1825{
1826    vgaHWPtr hwp = VGAHWPTR(pScrn);
1827    int i, index;
1828
1829    for (i = 0; i < numColors; i++) {
1830        index = indices[i];
1831        hwp->writeDacWriteAddr(hwp, index);
1832        DACDelay(hwp);
1833        hwp->writeDacData(hwp, colors[index].red);
1834        DACDelay(hwp);
1835        hwp->writeDacData(hwp, colors[index].green);
1836        DACDelay(hwp);
1837        hwp->writeDacData(hwp, colors[index].blue);
1838        DACDelay(hwp);
1839    }
1840
1841    /* This shouldn't be necessary, but we'll play safe. */
1842    hwp->disablePalette(hwp);
1843}
1844
1845static void
1846vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1847{
1848    vgaHWPtr hwp = VGAHWPTR(pScrn);
1849
1850    if (overscan < 0 || overscan > 255)
1851        return;
1852
1853    hwp->enablePalette(hwp);
1854    hwp->writeAttr(hwp, OVERSCAN, overscan);
1855
1856#ifdef DEBUGOVERSCAN
1857    {
1858        int ov = hwp->readAttr(hwp, OVERSCAN);
1859        int red, green, blue;
1860
1861        hwp->writeDacReadAddr(hwp, ov);
1862        red = hwp->readDacData(hwp);
1863        green = hwp->readDacData(hwp);
1864        blue = hwp->readDacData(hwp);
1865        ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1866               ov, red, green, blue);
1867    }
1868#endif
1869
1870    hwp->disablePalette(hwp);
1871}
1872
1873Bool
1874vgaHWHandleColormaps(ScreenPtr pScreen)
1875{
1876    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1877
1878    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1879        return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1880                                   pScrn->rgbBits, vgaHWLoadPalette,
1881                                   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1882                                   CMAP_RELOAD_ON_MODE_SWITCH);
1883    }
1884    return TRUE;
1885}
1886
1887/* ----------------------- DDC support ------------------------*/
1888/*
1889 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1890 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1891 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1892 * readback, enable access to cr00-cr07.
1893 */
1894
1895/* vertical timings */
1896#define DISPLAY_END 0x04
1897#define BLANK_START DISPLAY_END
1898#define SYNC_START BLANK_START
1899#define SYNC_END 0x09
1900#define BLANK_END SYNC_END
1901#define V_TOTAL BLANK_END
1902/* this function doesn't have to be reentrant for our purposes */
1903struct _vgaDdcSave {
1904    unsigned char cr03;
1905    unsigned char cr06;
1906    unsigned char cr07;
1907    unsigned char cr09;
1908    unsigned char cr10;
1909    unsigned char cr11;
1910    unsigned char cr12;
1911    unsigned char cr15;
1912    unsigned char cr16;
1913    unsigned char msr;
1914};
1915
1916void
1917vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1918{
1919    vgaHWPtr hwp = VGAHWPTR(pScrn);
1920    unsigned char tmp;
1921    struct _vgaDdcSave *save;
1922
1923    switch (speed) {
1924    case DDC_FAST:
1925
1926        if (hwp->ddc != NULL)
1927            break;
1928        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
1929        save = (struct _vgaDdcSave *) hwp->ddc;
1930        /* Lightpen register disable - allow access to cr10 & 11; just in case */
1931        save->cr03 = hwp->readCrtc(hwp, 0x03);
1932        hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
1933        save->cr12 = hwp->readCrtc(hwp, 0x12);
1934        hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
1935        save->cr15 = hwp->readCrtc(hwp, 0x15);
1936        hwp->writeCrtc(hwp, 0x15, BLANK_START);
1937        save->cr10 = hwp->readCrtc(hwp, 0x10);
1938        hwp->writeCrtc(hwp, 0x10, SYNC_START);
1939        save->cr11 = hwp->readCrtc(hwp, 0x11);
1940        /* unprotect group 1 registers; just in case ... */
1941        hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
1942        save->cr16 = hwp->readCrtc(hwp, 0x16);
1943        hwp->writeCrtc(hwp, 0x16, BLANK_END);
1944        save->cr06 = hwp->readCrtc(hwp, 0x06);
1945        hwp->writeCrtc(hwp, 0x06, V_TOTAL);
1946        /* all values have less than 8 bit - mask out 9th and 10th bits */
1947        save->cr09 = hwp->readCrtc(hwp, 0x09);
1948        hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
1949        save->cr07 = hwp->readCrtc(hwp, 0x07);
1950        hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
1951        /* vsync polarity negativ & ensure a 25MHz clock */
1952        save->msr = hwp->readMiscOut(hwp);
1953        hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
1954        break;
1955    case DDC_SLOW:
1956        if (hwp->ddc == NULL)
1957            break;
1958        save = (struct _vgaDdcSave *) hwp->ddc;
1959        hwp->writeMiscOut(hwp, save->msr);
1960        hwp->writeCrtc(hwp, 0x07, save->cr07);
1961        tmp = hwp->readCrtc(hwp, 0x09);
1962        hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
1963        hwp->writeCrtc(hwp, 0x06, save->cr06);
1964        hwp->writeCrtc(hwp, 0x16, save->cr16);
1965        hwp->writeCrtc(hwp, 0x11, save->cr11);
1966        hwp->writeCrtc(hwp, 0x10, save->cr10);
1967        hwp->writeCrtc(hwp, 0x15, save->cr15);
1968        hwp->writeCrtc(hwp, 0x12, save->cr12);
1969        hwp->writeCrtc(hwp, 0x03, save->cr03);
1970        free(save);
1971        hwp->ddc = NULL;
1972        break;
1973    default:
1974        break;
1975    }
1976}
1977
1978DDC1SetSpeedProc
1979vgaHWddc1SetSpeedWeak(void)
1980{
1981    return vgaHWddc1SetSpeed;
1982}
1983
1984SaveScreenProcPtr
1985vgaHWSaveScreenWeak(void)
1986{
1987    return vgaHWSaveScreen;
1988}
1989
1990/*
1991 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1992 */
1993void
1994xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
1995              void (*ProtectRegs) (ScrnInfoPtr, Bool),
1996              void (*BlankScreen) (ScrnInfoPtr, Bool),
1997              unsigned long vertsyncreg, int maskval, int knownclkindex,
1998              int knownclkvalue)
1999{
2000    register int status = vertsyncreg;
2001    unsigned long i, cnt, rcnt, sync;
2002    vgaHWPtr hwp = VGAHWPTR(pScrn);
2003
2004    /* First save registers that get written on */
2005    (*ClockFunc) (pScrn, CLK_REG_SAVE);
2006
2007    if (num > MAXCLOCKS)
2008        num = MAXCLOCKS;
2009
2010    for (i = 0; i < num; i++) {
2011        if (ProtectRegs)
2012            (*ProtectRegs) (pScrn, TRUE);
2013        if (!(*ClockFunc) (pScrn, i)) {
2014            pScrn->clock[i] = -1;
2015            continue;
2016        }
2017        if (ProtectRegs)
2018            (*ProtectRegs) (pScrn, FALSE);
2019        if (BlankScreen)
2020            (*BlankScreen) (pScrn, FALSE);
2021
2022        usleep(50000);          /* let VCO stabilise */
2023
2024        cnt = 0;
2025        sync = 200000;
2026
2027        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2028            if (sync-- == 0)
2029                goto finish;
2030        /* Something appears to be happening, so reset sync count */
2031        sync = 200000;
2032        while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
2033            if (sync-- == 0)
2034                goto finish;
2035        /* Something appears to be happening, so reset sync count */
2036        sync = 200000;
2037        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2038            if (sync-- == 0)
2039                goto finish;
2040
2041        for (rcnt = 0; rcnt < 5; rcnt++) {
2042            while (!(pci_io_read8(hwp->io, status) & maskval))
2043                cnt++;
2044            while ((pci_io_read8(hwp->io, status) & maskval))
2045                cnt++;
2046        }
2047
2048 finish:
2049        pScrn->clock[i] = cnt ? cnt : -1;
2050        if (BlankScreen)
2051            (*BlankScreen) (pScrn, TRUE);
2052    }
2053
2054    for (i = 0; i < num; i++) {
2055        if (i != knownclkindex) {
2056            if (pScrn->clock[i] == -1) {
2057                pScrn->clock[i] = 0;
2058            }
2059            else {
2060                pScrn->clock[i] = (int) (0.5 +
2061                                         (((float) knownclkvalue) *
2062                                          pScrn->clock[knownclkindex]) /
2063                                         (pScrn->clock[i]));
2064                /* Round to nearest 10KHz */
2065                pScrn->clock[i] += 5;
2066                pScrn->clock[i] /= 10;
2067                pScrn->clock[i] *= 10;
2068            }
2069        }
2070    }
2071
2072    pScrn->clock[knownclkindex] = knownclkvalue;
2073    pScrn->numClocks = num;
2074
2075    /* Restore registers that were written on */
2076    (*ClockFunc) (pScrn, CLK_REG_RESTORE);
2077}
2078