xserver-multidpi/hw/xfree86/vgahw/vgaHW.c
Keith Packard 9838b7032e Introduce a consistent coding style
This is strictly the application of the script 'x-indent-all.sh'
from util/modular. Compared to the patch that Daniel posted in
January, I've added a few indent flags:

	-bap
	-psl
	-T PrivatePtr
	-T pmWait
	-T _XFUNCPROTOBEGIN
	-T _XFUNCPROTOEND
	-T _X_EXPORT

The typedefs were needed to make the output of sdksyms.sh match the
previous output, otherwise, the code is formatted badly enough that
sdksyms.sh generates incorrect output.

The generated code was compared with the previous version and found to
be essentially identical -- "assert" line numbers and BUILD_TIME were
the only differences found.

The comparison was done with this script:

dir1=$1
dir2=$2

for dir in $dir1 $dir2; do
	(cd $dir && find . -name '*.o' | while read file; do
		dir=`dirname $file`
		base=`basename $file .o`
		dump=$dir/$base.dump
		objdump -d $file > $dump
	done)
done

find $dir1 -name '*.dump' | while read dump; do
	otherdump=`echo $dump | sed "s;$dir1;$dir2;"`
	diff -u $dump $otherdump
done

Signed-off-by: Keith Packard <keithp@keithp.com>
Acked-by: Daniel Stone <daniel@fooishbar.org>
Acked-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2012-03-21 13:54:42 -07:00

2078 lines
56 KiB
C

/*
*
* Copyright 1991-1999 by The XFree86 Project, Inc.
*
* Loosely based on code bearing the following copyright:
*
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
*
*/
#define _NEED_SYSI86
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/X.h>
#include "misc.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "vgaHW.h"
#include "compiler.h"
#include "xf86cmap.h"
#include "Pci.h"
#ifndef SAVE_FONT1
#define SAVE_FONT1 1
#endif
/*
* These used to be OS-specific, which made this module have an undesirable
* OS dependency. Define them by default for all platforms.
*/
#ifndef NEED_SAVED_CMAP
#define NEED_SAVED_CMAP
#endif
#ifndef SAVE_TEXT
#define SAVE_TEXT 1
#endif
#ifndef SAVE_FONT2
#define SAVE_FONT2 1
#endif
/* bytes per plane to save for text */
#define TEXT_AMOUNT 16384
/* bytes per plane to save for font data */
#define FONT_AMOUNT (8*8192)
#if 0
/* Override all of these for now */
#undef SAVE_FONT1
#define SAVE_FONT1 1
#undef SAVE_FONT2
#define SAVE_FONT2 1
#undef SAVE_TEST
#define SAVE_TEST 1
#undef FONT_AMOUNT
#define FONT_AMOUNT 65536
#undef TEXT_AMOUNT
#define TEXT_AMOUNT 65536
#endif
/* DAC indices for white and black */
#define WHITE_VALUE 0x3F
#define BLACK_VALUE 0x00
#define OVERSCAN_VALUE 0x01
/* Use a private definition of this here */
#undef VGAHWPTR
#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
static int vgaHWPrivateIndex = -1;
#define DAC_TEST_MASK 0x3F
#ifdef NEED_SAVED_CMAP
/* This default colourmap is used only when it can't be read from the VGA */
static CARD8 defaultDAC[768] = {
0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11,
14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24,
28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40,
45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63,
0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63,
63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16,
63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0,
63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0,
0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47,
0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63,
31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63,
63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39,
63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31,
63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31,
31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55,
31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63,
45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63,
63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49,
63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45,
63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45,
45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58,
45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63,
0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28,
28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7,
28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0,
28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0,
0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21,
0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28,
14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28,
28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17,
28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14,
28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14,
14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24,
14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28,
20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28,
28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22,
28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20,
28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20,
20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26,
20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28,
0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16,
16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4,
16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0,
16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0,
0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12,
0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16,
8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16,
16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10,
16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8,
16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8,
8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14,
8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16,
11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16,
16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12,
16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11,
16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11,
11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15,
11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#endif /* NEED_SAVED_CMAP */
/*
* Standard VGA versions of the register access functions.
*/
static void
stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
}
static CARD8
stdReadCrtc(vgaHWPtr hwp, CARD8 index)
{
pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
return pci_io_read8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET);
}
static void
stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
pci_io_write8(hwp->io, VGA_GRAPH_DATA, value);
}
static CARD8
stdReadGr(vgaHWPtr hwp, CARD8 index)
{
pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
return pci_io_read8(hwp->io, VGA_GRAPH_DATA);
}
static void
stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
pci_io_write8(hwp->io, VGA_SEQ_DATA, value);
}
static CARD8
stdReadSeq(vgaHWPtr hwp, CARD8 index)
{
pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
return pci_io_read8(hwp->io, VGA_SEQ_DATA);
}
static CARD8
stdReadST00(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_IN_STAT_0);
}
static CARD8
stdReadST01(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
}
static CARD8
stdReadFCR(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_FEATURE_R);
}
static void
stdWriteFCR(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
}
static void
stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
if (hwp->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
(void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
pci_io_write8(hwp->io, VGA_ATTR_DATA_W, value);
}
static CARD8
stdReadAttr(vgaHWPtr hwp, CARD8 index)
{
if (hwp->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
(void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
return pci_io_read8(hwp->io, VGA_ATTR_DATA_R);
}
static void
stdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
}
static CARD8
stdReadMiscOut(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
}
static void
stdEnablePalette(vgaHWPtr hwp)
{
(void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x00);
hwp->paletteEnabled = TRUE;
}
static void
stdDisablePalette(vgaHWPtr hwp)
{
(void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x20);
hwp->paletteEnabled = FALSE;
}
static void
stdWriteDacMask(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_DAC_MASK, value);
}
static CARD8
stdReadDacMask(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_DAC_MASK);
}
static void
stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
}
static void
stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
}
static void
stdWriteDacData(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_DAC_DATA, value);
}
static CARD8
stdReadDacData(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_DAC_DATA);
}
static CARD8
stdReadEnable(vgaHWPtr hwp)
{
return pci_io_read8(hwp->io, VGA_ENABLE);
}
static void
stdWriteEnable(vgaHWPtr hwp, CARD8 value)
{
pci_io_write8(hwp->io, VGA_ENABLE, value);
}
void
vgaHWSetStdFuncs(vgaHWPtr hwp)
{
hwp->writeCrtc = stdWriteCrtc;
hwp->readCrtc = stdReadCrtc;
hwp->writeGr = stdWriteGr;
hwp->readGr = stdReadGr;
hwp->readST00 = stdReadST00;
hwp->readST01 = stdReadST01;
hwp->readFCR = stdReadFCR;
hwp->writeFCR = stdWriteFCR;
hwp->writeAttr = stdWriteAttr;
hwp->readAttr = stdReadAttr;
hwp->writeSeq = stdWriteSeq;
hwp->readSeq = stdReadSeq;
hwp->writeMiscOut = stdWriteMiscOut;
hwp->readMiscOut = stdReadMiscOut;
hwp->enablePalette = stdEnablePalette;
hwp->disablePalette = stdDisablePalette;
hwp->writeDacMask = stdWriteDacMask;
hwp->readDacMask = stdReadDacMask;
hwp->writeDacWriteAddr = stdWriteDacWriteAddr;
hwp->writeDacReadAddr = stdWriteDacReadAddr;
hwp->writeDacData = stdWriteDacData;
hwp->readDacData = stdReadDacData;
hwp->readEnable = stdReadEnable;
hwp->writeEnable = stdWriteEnable;
hwp->io = pci_legacy_open_io(hwp->dev, 0, 64 * 1024);
}
/*
* MMIO versions of the register access functions. These require
* hwp->MemBase to be set in such a way that when the standard VGA port
* adderss is added the correct memory address results.
*/
#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
static void
mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
}
static CARD8
mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
{
moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
}
static void
mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
moutb(VGA_GRAPH_INDEX, index);
moutb(VGA_GRAPH_DATA, value);
}
static CARD8
mmioReadGr(vgaHWPtr hwp, CARD8 index)
{
moutb(VGA_GRAPH_INDEX, index);
return minb(VGA_GRAPH_DATA);
}
static void
mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
moutb(VGA_SEQ_INDEX, index);
moutb(VGA_SEQ_DATA, value);
}
static CARD8
mmioReadSeq(vgaHWPtr hwp, CARD8 index)
{
moutb(VGA_SEQ_INDEX, index);
return minb(VGA_SEQ_DATA);
}
static CARD8
mmioReadST00(vgaHWPtr hwp)
{
return minb(VGA_IN_STAT_0);
}
static CARD8
mmioReadST01(vgaHWPtr hwp)
{
return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
}
static CARD8
mmioReadFCR(vgaHWPtr hwp)
{
return minb(VGA_FEATURE_R);
}
static void
mmioWriteFCR(vgaHWPtr hwp, CARD8 value)
{
moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
}
static void
mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
if (hwp->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
(void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
moutb(VGA_ATTR_INDEX, index);
moutb(VGA_ATTR_DATA_W, value);
}
static CARD8
mmioReadAttr(vgaHWPtr hwp, CARD8 index)
{
if (hwp->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
(void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
moutb(VGA_ATTR_INDEX, index);
return minb(VGA_ATTR_DATA_R);
}
static void
mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_MISC_OUT_W, value);
}
static CARD8
mmioReadMiscOut(vgaHWPtr hwp)
{
return minb(VGA_MISC_OUT_R);
}
static void
mmioEnablePalette(vgaHWPtr hwp)
{
(void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
moutb(VGA_ATTR_INDEX, 0x00);
hwp->paletteEnabled = TRUE;
}
static void
mmioDisablePalette(vgaHWPtr hwp)
{
(void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
moutb(VGA_ATTR_INDEX, 0x20);
hwp->paletteEnabled = FALSE;
}
static void
mmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_DAC_MASK, value);
}
static CARD8
mmioReadDacMask(vgaHWPtr hwp)
{
return minb(VGA_DAC_MASK);
}
static void
mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_DAC_READ_ADDR, value);
}
static void
mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_DAC_WRITE_ADDR, value);
}
static void
mmioWriteDacData(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_DAC_DATA, value);
}
static CARD8
mmioReadDacData(vgaHWPtr hwp)
{
return minb(VGA_DAC_DATA);
}
static CARD8
mmioReadEnable(vgaHWPtr hwp)
{
return minb(VGA_ENABLE);
}
static void
mmioWriteEnable(vgaHWPtr hwp, CARD8 value)
{
moutb(VGA_ENABLE, value);
}
void
vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
{
hwp->writeCrtc = mmioWriteCrtc;
hwp->readCrtc = mmioReadCrtc;
hwp->writeGr = mmioWriteGr;
hwp->readGr = mmioReadGr;
hwp->readST00 = mmioReadST00;
hwp->readST01 = mmioReadST01;
hwp->readFCR = mmioReadFCR;
hwp->writeFCR = mmioWriteFCR;
hwp->writeAttr = mmioWriteAttr;
hwp->readAttr = mmioReadAttr;
hwp->writeSeq = mmioWriteSeq;
hwp->readSeq = mmioReadSeq;
hwp->writeMiscOut = mmioWriteMiscOut;
hwp->readMiscOut = mmioReadMiscOut;
hwp->enablePalette = mmioEnablePalette;
hwp->disablePalette = mmioDisablePalette;
hwp->writeDacMask = mmioWriteDacMask;
hwp->readDacMask = mmioReadDacMask;
hwp->writeDacWriteAddr = mmioWriteDacWriteAddr;
hwp->writeDacReadAddr = mmioWriteDacReadAddr;
hwp->writeDacData = mmioWriteDacData;
hwp->readDacData = mmioReadDacData;
hwp->MMIOBase = base;
hwp->MMIOOffset = offset;
hwp->readEnable = mmioReadEnable;
hwp->writeEnable = mmioWriteEnable;
}
/*
* vgaHWProtect --
* Protect VGA registers and memory from corruption during loads.
*/
void
vgaHWProtect(ScrnInfoPtr pScrn, Bool on)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
unsigned char tmp;
if (pScrn->vtSema) {
if (on) {
/*
* Turn off screen and disable sequencer.
*/
tmp = hwp->readSeq(hwp, 0x01);
vgaHWSeqReset(hwp, TRUE); /* start synchronous reset */
hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */
hwp->enablePalette(hwp);
}
else {
/*
* Reenable sequencer, then turn on screen.
*/
tmp = hwp->readSeq(hwp, 0x01);
hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */
vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */
hwp->disablePalette(hwp);
}
}
}
vgaHWProtectProc *
vgaHWProtectWeak(void)
{
return vgaHWProtect;
}
/*
* vgaHWBlankScreen -- blank the screen.
*/
void
vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
unsigned char scrn;
scrn = hwp->readSeq(hwp, 0x01);
if (on) {
scrn &= ~0x20; /* enable screen */
}
else {
scrn |= 0x20; /* blank screen */
}
vgaHWSeqReset(hwp, TRUE);
hwp->writeSeq(hwp, 0x01, scrn); /* change mode */
vgaHWSeqReset(hwp, FALSE);
}
vgaHWBlankScreenProc *
vgaHWBlankScreenWeak(void)
{
return vgaHWBlankScreen;
}
/*
* vgaHWSaveScreen -- blank the screen.
*/
Bool
vgaHWSaveScreen(ScreenPtr pScreen, int mode)
{
ScrnInfoPtr pScrn = NULL;
Bool on;
if (pScreen != NULL)
pScrn = xf86Screens[pScreen->myNum];
on = xf86IsUnblank(mode);
#if 0
if (on)
SetTimeSinceLastInputEvent();
#endif
if ((pScrn != NULL) && pScrn->vtSema) {
vgaHWBlankScreen(pScrn, on);
}
return TRUE;
}
/*
* vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
*
* This generic VGA function can only set the Off and On modes. If the
* Standby and Suspend modes are to be supported, a chip specific replacement
* for this function must be written.
*/
void
vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
{
unsigned char seq1 = 0, crtc17 = 0;
vgaHWPtr hwp = VGAHWPTR(pScrn);
if (!pScrn->vtSema)
return;
switch (PowerManagementMode) {
case DPMSModeOn:
/* Screen: On; HSync: On, VSync: On */
seq1 = 0x00;
crtc17 = 0x80;
break;
case DPMSModeStandby:
/* Screen: Off; HSync: Off, VSync: On -- Not Supported */
seq1 = 0x20;
crtc17 = 0x80;
break;
case DPMSModeSuspend:
/* Screen: Off; HSync: On, VSync: Off -- Not Supported */
seq1 = 0x20;
crtc17 = 0x80;
break;
case DPMSModeOff:
/* Screen: Off; HSync: Off, VSync: Off */
seq1 = 0x20;
crtc17 = 0x00;
break;
}
hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
hwp->writeSeq(hwp, 0x01, seq1);
crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
usleep(10000);
hwp->writeCrtc(hwp, 0x17, crtc17);
hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
}
/*
* vgaHWSeqReset
* perform a sequencer reset.
*/
void
vgaHWSeqReset(vgaHWPtr hwp, Bool start)
{
if (start)
hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
else
hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
}
void
vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
{
#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int savedIOBase;
unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
Bool doMap = FALSE;
/* If nothing to do, return now */
if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
return;
if (hwp->Base == NULL) {
doMap = TRUE;
if (!vgaHWMapMem(scrninfp)) {
xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
"vgaHWRestoreFonts: vgaHWMapMem() failed\n");
return;
}
}
/* save the registers that are needed here */
miscOut = hwp->readMiscOut(hwp);
attr10 = hwp->readAttr(hwp, 0x10);
gr1 = hwp->readGr(hwp, 0x01);
gr3 = hwp->readGr(hwp, 0x03);
gr4 = hwp->readGr(hwp, 0x04);
gr5 = hwp->readGr(hwp, 0x05);
gr6 = hwp->readGr(hwp, 0x06);
gr8 = hwp->readGr(hwp, 0x08);
seq2 = hwp->readSeq(hwp, 0x02);
seq4 = hwp->readSeq(hwp, 0x04);
/* save hwp->IOBase and temporarily set it for colour mode */
savedIOBase = hwp->IOBase;
hwp->IOBase = VGA_IOBASE_COLOR;
/* Force into colour mode */
hwp->writeMiscOut(hwp, miscOut | 0x01);
vgaHWBlankScreen(scrninfp, FALSE);
/*
* here we temporarily switch to 16 colour planar mode, to simply
* copy the font-info and saved text.
*
* BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
*/
#if 0
hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */
#endif
hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */
hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */
if (scrninfp->depth == 4) {
/* GJA */
hwp->writeGr(hwp, 0x03, 0x00); /* don't rotate, write unmodified */
hwp->writeGr(hwp, 0x08, 0xFF); /* write all bits in a byte */
hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */
}
#if SAVE_FONT1
if (hwp->FontInfo1) {
hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
}
#endif
#if SAVE_FONT2
if (hwp->FontInfo2) {
hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
}
#endif
#if SAVE_TEXT
if (hwp->TextInfo) {
hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */
slowbcopy_tobus((unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
hwp->Base, TEXT_AMOUNT);
}
#endif
vgaHWBlankScreen(scrninfp, TRUE);
/* restore the registers that were changed */
hwp->writeMiscOut(hwp, miscOut);
hwp->writeAttr(hwp, 0x10, attr10);
hwp->writeGr(hwp, 0x01, gr1);
hwp->writeGr(hwp, 0x03, gr3);
hwp->writeGr(hwp, 0x04, gr4);
hwp->writeGr(hwp, 0x05, gr5);
hwp->writeGr(hwp, 0x06, gr6);
hwp->writeGr(hwp, 0x08, gr8);
hwp->writeSeq(hwp, 0x02, seq2);
hwp->writeSeq(hwp, 0x04, seq4);
hwp->IOBase = savedIOBase;
if (doMap)
vgaHWUnmapMem(scrninfp);
#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
}
void
vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
{
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int i;
if (restore->MiscOutReg & 0x01)
hwp->IOBase = VGA_IOBASE_COLOR;
else
hwp->IOBase = VGA_IOBASE_MONO;
hwp->writeMiscOut(hwp, restore->MiscOutReg);
for (i = 1; i < restore->numSequencer; i++)
hwp->writeSeq(hwp, i, restore->Sequencer[i]);
/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
for (i = 0; i < restore->numCRTC; i++)
hwp->writeCrtc(hwp, i, restore->CRTC[i]);
for (i = 0; i < restore->numGraphics; i++)
hwp->writeGr(hwp, i, restore->Graphics[i]);
hwp->enablePalette(hwp);
for (i = 0; i < restore->numAttribute; i++)
hwp->writeAttr(hwp, i, restore->Attribute[i]);
hwp->disablePalette(hwp);
}
void
vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
{
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int i;
#if 0
hwp->enablePalette(hwp);
#endif
hwp->writeDacMask(hwp, 0xFF);
hwp->writeDacWriteAddr(hwp, 0x00);
for (i = 0; i < 768; i++) {
hwp->writeDacData(hwp, restore->DAC[i]);
DACDelay(hwp);
}
hwp->disablePalette(hwp);
}
/*
* vgaHWRestore --
* restore the VGA state
*/
void
vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
{
if (flags & VGA_SR_MODE)
vgaHWRestoreMode(scrninfp, restore);
if (flags & VGA_SR_FONTS)
vgaHWRestoreFonts(scrninfp, restore);
if (flags & VGA_SR_CMAP)
vgaHWRestoreColormap(scrninfp, restore);
}
void
vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
{
#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int savedIOBase;
unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
Bool doMap = FALSE;
if (hwp->Base == NULL) {
doMap = TRUE;
if (!vgaHWMapMem(scrninfp)) {
xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
"vgaHWSaveFonts: vgaHWMapMem() failed\n");
return;
}
}
/* If in graphics mode, don't save anything */
attr10 = hwp->readAttr(hwp, 0x10);
if (attr10 & 0x01)
return;
/* save the registers that are needed here */
miscOut = hwp->readMiscOut(hwp);
gr4 = hwp->readGr(hwp, 0x04);
gr5 = hwp->readGr(hwp, 0x05);
gr6 = hwp->readGr(hwp, 0x06);
seq2 = hwp->readSeq(hwp, 0x02);
seq4 = hwp->readSeq(hwp, 0x04);
/* save hwp->IOBase and temporarily set it for colour mode */
savedIOBase = hwp->IOBase;
hwp->IOBase = VGA_IOBASE_COLOR;
/* Force into colour mode */
hwp->writeMiscOut(hwp, miscOut | 0x01);
vgaHWBlankScreen(scrninfp, FALSE);
/*
* get the character sets, and text screen if required
*/
/*
* Here we temporarily switch to 16 colour planar mode, to simply
* copy the font-info
*
* BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
*/
#if 0
hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */
#endif
hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */
hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */
#if SAVE_FONT1
if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
}
#endif /* SAVE_FONT1 */
#if SAVE_FONT2
if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
}
#endif /* SAVE_FONT2 */
#if SAVE_TEXT
if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */
slowbcopy_frombus(hwp->Base,
(unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
TEXT_AMOUNT);
}
#endif /* SAVE_TEXT */
/* Restore clobbered registers */
hwp->writeAttr(hwp, 0x10, attr10);
hwp->writeSeq(hwp, 0x02, seq2);
hwp->writeSeq(hwp, 0x04, seq4);
hwp->writeGr(hwp, 0x04, gr4);
hwp->writeGr(hwp, 0x05, gr5);
hwp->writeGr(hwp, 0x06, gr6);
hwp->writeMiscOut(hwp, miscOut);
hwp->IOBase = savedIOBase;
vgaHWBlankScreen(scrninfp, TRUE);
if (doMap)
vgaHWUnmapMem(scrninfp);
#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
}
void
vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
{
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int i;
save->MiscOutReg = hwp->readMiscOut(hwp);
if (save->MiscOutReg & 0x01)
hwp->IOBase = VGA_IOBASE_COLOR;
else
hwp->IOBase = VGA_IOBASE_MONO;
for (i = 0; i < save->numCRTC; i++) {
save->CRTC[i] = hwp->readCrtc(hwp, i);
DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
}
hwp->enablePalette(hwp);
for (i = 0; i < save->numAttribute; i++) {
save->Attribute[i] = hwp->readAttr(hwp, i);
DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
}
hwp->disablePalette(hwp);
for (i = 0; i < save->numGraphics; i++) {
save->Graphics[i] = hwp->readGr(hwp, i);
DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
}
for (i = 1; i < save->numSequencer; i++) {
save->Sequencer[i] = hwp->readSeq(hwp, i);
DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
}
}
void
vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
{
vgaHWPtr hwp = VGAHWPTR(scrninfp);
Bool readError = FALSE;
int i;
#ifdef NEED_SAVED_CMAP
/*
* Some ET4000 chips from 1991 have a HW bug that prevents the reading
* of the color lookup table. Mask rev 9042EAI is known to have this bug.
*
* If the colourmap is not readable, we set the saved map to a default
* map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
* Cards" 2nd ed).
*/
/* Only save it once */
if (hwp->cmapSaved)
return;
#if 0
hwp->enablePalette(hwp);
#endif
hwp->writeDacMask(hwp, 0xFF);
/*
* check if we can read the lookup table
*/
hwp->writeDacReadAddr(hwp, 0x00);
for (i = 0; i < 6; i++) {
save->DAC[i] = hwp->readDacData(hwp);
switch (i % 3) {
case 0:
DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
break;
case 1:
DebugF("0x%02x, ", save->DAC[i]);
break;
case 2:
DebugF("0x%02x\n", save->DAC[i]);
}
}
/*
* Check if we can read the palette -
* use foreground color to prevent flashing.
*/
hwp->writeDacWriteAddr(hwp, 0x01);
for (i = 3; i < 6; i++)
hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
hwp->writeDacReadAddr(hwp, 0x01);
for (i = 3; i < 6; i++) {
if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
readError = TRUE;
}
hwp->writeDacWriteAddr(hwp, 0x01);
for (i = 3; i < 6; i++)
hwp->writeDacData(hwp, save->DAC[i]);
if (readError) {
/*
* save the default lookup table
*/
memmove(save->DAC, defaultDAC, 768);
xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
"Cannot read colourmap from VGA. Will restore with default\n");
}
else {
/* save the colourmap */
hwp->writeDacReadAddr(hwp, 0x02);
for (i = 6; i < 768; i++) {
save->DAC[i] = hwp->readDacData(hwp);
DACDelay(hwp);
switch (i % 3) {
case 0:
DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
break;
case 1:
DebugF("0x%02x, ", save->DAC[i]);
break;
case 2:
DebugF("0x%02x\n", save->DAC[i]);
}
}
}
hwp->disablePalette(hwp);
hwp->cmapSaved = TRUE;
#endif
}
/*
* vgaHWSave --
* save the current VGA state
*/
void
vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
{
if (save == NULL)
return;
if (flags & VGA_SR_CMAP)
vgaHWSaveColormap(scrninfp, save);
if (flags & VGA_SR_MODE)
vgaHWSaveMode(scrninfp, save);
if (flags & VGA_SR_FONTS)
vgaHWSaveFonts(scrninfp, save);
}
/*
* vgaHWInit --
* Handle the initialization, etc. of a screen.
* Return FALSE on failure.
*/
Bool
vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
{
unsigned int i;
vgaHWPtr hwp;
vgaRegPtr regp;
int depth = scrninfp->depth;
/*
* make sure the vgaHWRec is allocated
*/
if (!vgaHWGetHWRec(scrninfp))
return FALSE;
hwp = VGAHWPTR(scrninfp);
regp = &hwp->ModeReg;
/*
* compute correct Hsync & Vsync polarity
*/
if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
&& (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
regp->MiscOutReg = 0x23;
if (mode->Flags & V_NHSYNC)
regp->MiscOutReg |= 0x40;
if (mode->Flags & V_NVSYNC)
regp->MiscOutReg |= 0x80;
}
else {
int VDisplay = mode->VDisplay;
if (mode->Flags & V_DBLSCAN)
VDisplay *= 2;
if (mode->VScan > 1)
VDisplay *= mode->VScan;
if (VDisplay < 400)
regp->MiscOutReg = 0xA3; /* +hsync -vsync */
else if (VDisplay < 480)
regp->MiscOutReg = 0x63; /* -hsync +vsync */
else if (VDisplay < 768)
regp->MiscOutReg = 0xE3; /* -hsync -vsync */
else
regp->MiscOutReg = 0x23; /* +hsync +vsync */
}
regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
/*
* Time Sequencer
*/
if (depth == 4)
regp->Sequencer[0] = 0x02;
else
regp->Sequencer[0] = 0x00;
if (mode->Flags & V_CLKDIV2)
regp->Sequencer[1] = 0x09;
else
regp->Sequencer[1] = 0x01;
if (depth == 1)
regp->Sequencer[2] = 1 << BIT_PLANE;
else
regp->Sequencer[2] = 0x0F;
regp->Sequencer[3] = 0x00; /* Font select */
if (depth < 8)
regp->Sequencer[4] = 0x06; /* Misc */
else
regp->Sequencer[4] = 0x0E; /* Misc */
/*
* CRTC Controller
*/
regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5;
regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1;
regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1;
regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
if (i < 0x80)
regp->CRTC[3] |= i;
regp->CRTC[4] = (mode->CrtcHSyncStart >> 3);
regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF;
regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
| (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
| ((mode->CrtcVSyncStart & 0x100) >> 6)
| (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
| 0x10 | (((mode->CrtcVTotal - 2) & 0x200) >> 4)
| (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
| ((mode->CrtcVSyncStart & 0x200) >> 2);
regp->CRTC[8] = 0x00;
regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
if (mode->Flags & V_DBLSCAN)
regp->CRTC[9] |= 0x80;
if (mode->VScan >= 32)
regp->CRTC[9] |= 0x1F;
else if (mode->VScan > 1)
regp->CRTC[9] |= mode->VScan - 1;
regp->CRTC[10] = 0x00;
regp->CRTC[11] = 0x00;
regp->CRTC[12] = 0x00;
regp->CRTC[13] = 0x00;
regp->CRTC[14] = 0x00;
regp->CRTC[15] = 0x00;
regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
regp->CRTC[19] = scrninfp->displayWidth >> 4; /* just a guess */
regp->CRTC[20] = 0x00;
regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
if (depth < 8)
regp->CRTC[23] = 0xE3;
else
regp->CRTC[23] = 0xC3;
regp->CRTC[24] = 0xFF;
vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
/*
* Theory resumes here....
*/
/*
* Graphics Display Controller
*/
regp->Graphics[0] = 0x00;
regp->Graphics[1] = 0x00;
regp->Graphics[2] = 0x00;
regp->Graphics[3] = 0x00;
if (depth == 1) {
regp->Graphics[4] = BIT_PLANE;
regp->Graphics[5] = 0x00;
}
else {
regp->Graphics[4] = 0x00;
if (depth == 4)
regp->Graphics[5] = 0x02;
else
regp->Graphics[5] = 0x40;
}
regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
regp->Graphics[7] = 0x0F;
regp->Graphics[8] = 0xFF;
if (depth == 1) {
/* Initialise the Mono map according to which bit-plane gets used */
Bool flipPixels = xf86GetFlipPixels();
for (i = 0; i < 16; i++)
if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
regp->Attribute[i] = WHITE_VALUE;
else
regp->Attribute[i] = BLACK_VALUE;
regp->Attribute[16] = 0x01; /* -VGA2- *//* wrong for the ET4000 */
if (!hwp->ShowOverscan)
regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
}
else {
regp->Attribute[0] = 0x00; /* standard colormap translation */
regp->Attribute[1] = 0x01;
regp->Attribute[2] = 0x02;
regp->Attribute[3] = 0x03;
regp->Attribute[4] = 0x04;
regp->Attribute[5] = 0x05;
regp->Attribute[6] = 0x06;
regp->Attribute[7] = 0x07;
regp->Attribute[8] = 0x08;
regp->Attribute[9] = 0x09;
regp->Attribute[10] = 0x0A;
regp->Attribute[11] = 0x0B;
regp->Attribute[12] = 0x0C;
regp->Attribute[13] = 0x0D;
regp->Attribute[14] = 0x0E;
regp->Attribute[15] = 0x0F;
if (depth == 4)
regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
else
regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
/* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
}
regp->Attribute[18] = 0x0F;
regp->Attribute[19] = 0x00;
regp->Attribute[20] = 0x00;
return TRUE;
}
/*
* OK, so much for theory. Now, let's deal with the >real< world...
*
* The above CRTC settings are precise in theory, except that many, if not
* most, VGA clones fail to reset the blanking signal when the character or
* line counter reaches [HV]Total. In this case, the signal is only
* unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
* the case may be) at the start of the >next< scanline or frame, which
* means only part of the screen shows. This affects how null overscans
* are to be implemented on such adapters.
*
* Henceforth, VGA cores that implement this broken, but unfortunately
* common, behaviour are to be designated as KGA's, in honour of Koen
* Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
* a series of events that led to the discovery of this problem.
*
* Some VGA's are KGA's only in the horizontal, or only in the vertical,
* some in both, others in neither. Don't let anyone tell you there is
* such a thing as a VGA "standard"... And, thank the Creator for the fact
* that Hilbert spaces are not yet implemented in this industry.
*
* The following implements a trick suggested by David Dawes. This sets
* [HV]BlankEnd to zero if the blanking interval does not already contain a
* 0-point, and decrements it by one otherwise. In the latter case, this
* will produce a left and/or top overscan which the colourmap code will
* (still) need to ensure is as close to black as possible. This will make
* the behaviour consistent across all chipsets, while allowing all
* chipsets to display the entire screen. Non-KGA drivers can ignore the
* following in their own copy of this code.
*
* -- TSI @ UQV, 1998.08.21
*/
CARD32
vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
unsigned int Flags)
{
int nExtBits = (nBits < 6) ? 0 : nBits - 6;
CARD32 ExtBits;
CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
| (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
| ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
/* First the horizontal case */
if ((Flags & KGA_FIX_OVERSCAN)
&& ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
int i = (regp->CRTC[3] & 0x1F)
| ((regp->CRTC[5] & 0x80) >> 2)
| ExtBits;
if (Flags & KGA_ENABLE_ON_ZERO) {
if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
& (0x3F | ExtBitMask)))
&& (mode->CrtcHBlankEnd == mode->CrtcHTotal))
i = 0;
}
else if (Flags & KGA_BE_TOT_DEC)
i--;
regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
ExtBits = i & ExtBitMask;
}
return ExtBits >> 6;
}
/*
* The vertical case is a little trickier. Some VGA's ignore bit 0x80 of
* CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the
* very first scanline in a double- or multi-scanned mode. This last case
* needs further investigation.
*/
CARD32
vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
unsigned int Flags)
{
CARD32 ExtBits;
CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
/* If width is not known nBits should be 0. In this
* case BitMask is set to 0 so we can check for it. */
CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
if ((Flags & KGA_FIX_OVERSCAN)
&& (mode->CrtcVBlankEnd == mode->CrtcVTotal))
/* Null top overscan */
{
int i = regp->CRTC[22] | ExtBits;
if (Flags & KGA_ENABLE_ON_ZERO) {
if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
|| ((i > VBlankStart) && /* 8-bit case */
((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */
!(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */
i = 0;
else
i = (i - 1);
}
else if (Flags & KGA_BE_TOT_DEC)
i = (i - 1);
regp->CRTC[22] = i & 0xFF;
ExtBits = i & 0xFF00;
}
return ExtBits >> 8;
}
/*
* these are some more hardware specific helpers, formerly in vga.c
*/
static void
vgaHWGetHWRecPrivate(void)
{
if (vgaHWPrivateIndex < 0)
vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
return;
}
static void
vgaHWFreeRegs(vgaRegPtr regp)
{
free(regp->CRTC);
regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
regp->numCRTC =
regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
}
static Bool
vgaHWAllocRegs(vgaRegPtr regp)
{
unsigned char *buf;
if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
regp->numAttribute) == 0)
return FALSE;
buf = calloc(regp->numCRTC +
regp->numSequencer +
regp->numGraphics + regp->numAttribute, 1);
if (!buf)
return FALSE;
regp->CRTC = buf;
regp->Sequencer = regp->CRTC + regp->numCRTC;
regp->Graphics = regp->Sequencer + regp->numSequencer;
regp->Attribute = regp->Graphics + regp->numGraphics;
return TRUE;
}
Bool
vgaHWAllocDefaultRegs(vgaRegPtr regp)
{
regp->numCRTC = VGA_NUM_CRTC;
regp->numSequencer = VGA_NUM_SEQ;
regp->numGraphics = VGA_NUM_GFX;
regp->numAttribute = VGA_NUM_ATTR;
return vgaHWAllocRegs(regp);
}
Bool
vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
int numGraphics, int numAttribute)
{
#define VGAHWMINNUM(regtype) \
((newMode.num##regtype < regp->num##regtype) ? \
(newMode.num##regtype) : (regp->num##regtype))
#define VGAHWCOPYREGSET(regtype) \
memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
vgaRegRec newMode, newSaved;
vgaRegPtr regp;
regp = &VGAHWPTR(scrp)->ModeReg;
memcpy(&newMode, regp, sizeof(vgaRegRec));
/* allocate space for new registers */
regp = &newMode;
regp->numCRTC = numCRTC;
regp->numSequencer = numSequencer;
regp->numGraphics = numGraphics;
regp->numAttribute = numAttribute;
if (!vgaHWAllocRegs(regp))
return FALSE;
regp = &VGAHWPTR(scrp)->SavedReg;
memcpy(&newSaved, regp, sizeof(vgaRegRec));
regp = &newSaved;
regp->numCRTC = numCRTC;
regp->numSequencer = numSequencer;
regp->numGraphics = numGraphics;
regp->numAttribute = numAttribute;
if (!vgaHWAllocRegs(regp)) {
vgaHWFreeRegs(&newMode);
return FALSE;
}
/* allocations succeeded, copy register data into new space */
regp = &VGAHWPTR(scrp)->ModeReg;
VGAHWCOPYREGSET(CRTC);
VGAHWCOPYREGSET(Sequencer);
VGAHWCOPYREGSET(Graphics);
VGAHWCOPYREGSET(Attribute);
regp = &VGAHWPTR(scrp)->SavedReg;
VGAHWCOPYREGSET(CRTC);
VGAHWCOPYREGSET(Sequencer);
VGAHWCOPYREGSET(Graphics);
VGAHWCOPYREGSET(Attribute);
/* free old register arrays */
regp = &VGAHWPTR(scrp)->ModeReg;
vgaHWFreeRegs(regp);
memcpy(regp, &newMode, sizeof(vgaRegRec));
regp = &VGAHWPTR(scrp)->SavedReg;
vgaHWFreeRegs(regp);
memcpy(regp, &newSaved, sizeof(vgaRegRec));
return TRUE;
#undef VGAHWMINNUM
#undef VGAHWCOPYREGSET
}
Bool
vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
{
vgaHWFreeRegs(dst);
memcpy(dst, src, sizeof(vgaRegRec));
if (!vgaHWAllocRegs(dst))
return FALSE;
memcpy(dst->CRTC, src->CRTC, src->numCRTC);
memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
memcpy(dst->Graphics, src->Graphics, src->numGraphics);
memcpy(dst->Attribute, src->Attribute, src->numAttribute);
return TRUE;
}
Bool
vgaHWGetHWRec(ScrnInfoPtr scrp)
{
vgaRegPtr regp;
vgaHWPtr hwp;
int i;
/*
* Let's make sure that the private exists and allocate one.
*/
vgaHWGetHWRecPrivate();
/*
* New privates are always set to NULL, so we can check if the allocation
* has already been done.
*/
if (VGAHWPTR(scrp))
return TRUE;
hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
regp = &VGAHWPTR(scrp)->ModeReg;
if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
(!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
free(hwp);
return FALSE;
}
if (scrp->bitsPerPixel == 1) {
rgb blackColour = scrp->display->blackColour,
whiteColour = scrp->display->whiteColour;
if (blackColour.red > 0x3F)
blackColour.red = 0x3F;
if (blackColour.green > 0x3F)
blackColour.green = 0x3F;
if (blackColour.blue > 0x3F)
blackColour.blue = 0x3F;
if (whiteColour.red > 0x3F)
whiteColour.red = 0x3F;
if (whiteColour.green > 0x3F)
whiteColour.green = 0x3F;
if (whiteColour.blue > 0x3F)
whiteColour.blue = 0x3F;
if ((blackColour.red == whiteColour.red) &&
(blackColour.green == whiteColour.green) &&
(blackColour.blue == whiteColour.blue)) {
blackColour.red ^= 0x3F;
blackColour.green ^= 0x3F;
blackColour.blue ^= 0x3F;
}
/*
* initialize default colormap for monochrome
*/
for (i = 0; i < 3; i++)
regp->DAC[i] = 0x00;
for (i = 3; i < 768; i++)
regp->DAC[i] = 0x3F;
i = BLACK_VALUE * 3;
regp->DAC[i++] = blackColour.red;
regp->DAC[i++] = blackColour.green;
regp->DAC[i] = blackColour.blue;
i = WHITE_VALUE * 3;
regp->DAC[i++] = whiteColour.red;
regp->DAC[i++] = whiteColour.green;
regp->DAC[i] = whiteColour.blue;
i = OVERSCAN_VALUE * 3;
regp->DAC[i++] = 0x00;
regp->DAC[i++] = 0x00;
regp->DAC[i] = 0x00;
}
else {
/* Set all colours to black */
for (i = 0; i < 768; i++)
regp->DAC[i] = 0x00;
/* ... and the overscan */
if (scrp->depth >= 4)
regp->Attribute[OVERSCAN] = 0xFF;
}
if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
regp->DAC[765] = 0x3F;
regp->DAC[766] = 0x00;
regp->DAC[767] = 0x3F;
regp->Attribute[OVERSCAN] = 0xFF;
hwp->ShowOverscan = TRUE;
}
else
hwp->ShowOverscan = FALSE;
hwp->paletteEnabled = FALSE;
hwp->cmapSaved = FALSE;
hwp->MapSize = 0;
hwp->pScrn = scrp;
hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
return TRUE;
}
void
vgaHWFreeHWRec(ScrnInfoPtr scrp)
{
if (vgaHWPrivateIndex >= 0) {
vgaHWPtr hwp = VGAHWPTR(scrp);
if (!hwp)
return;
pci_device_close_io(hwp->dev, hwp->io);
free(hwp->FontInfo1);
free(hwp->FontInfo2);
free(hwp->TextInfo);
vgaHWFreeRegs(&hwp->ModeReg);
vgaHWFreeRegs(&hwp->SavedReg);
free(hwp);
VGAHWPTRLVAL(scrp) = NULL;
}
}
Bool
vgaHWMapMem(ScrnInfoPtr scrp)
{
vgaHWPtr hwp = VGAHWPTR(scrp);
if (hwp->Base)
return TRUE;
/* If not set, initialise with the defaults */
if (hwp->MapSize == 0)
hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
if (hwp->MapPhys == 0)
hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
/*
* Map as VIDMEM_MMIO_32BIT because WC
* is bad when there is page flipping.
* XXX This is not correct but we do it
* for now.
*/
DebugF("Mapping VGAMem\n");
pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
return hwp->Base != NULL;
}
void
vgaHWUnmapMem(ScrnInfoPtr scrp)
{
vgaHWPtr hwp = VGAHWPTR(scrp);
if (hwp->Base == NULL)
return;
DebugF("Unmapping VGAMem\n");
pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
hwp->Base = NULL;
}
int
vgaHWGetIndex(void)
{
return vgaHWPrivateIndex;
}
void
vgaHWGetIOBase(vgaHWPtr hwp)
{
hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
"vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
}
void
vgaHWLock(vgaHWPtr hwp)
{
/* Protect CRTC[0-7] */
hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
}
void
vgaHWUnlock(vgaHWPtr hwp)
{
/* Unprotect CRTC[0-7] */
hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
}
void
vgaHWEnable(vgaHWPtr hwp)
{
hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
}
void
vgaHWDisable(vgaHWPtr hwp)
{
hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
}
static void
vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
VisualPtr pVisual)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
int i, index;
for (i = 0; i < numColors; i++) {
index = indices[i];
hwp->writeDacWriteAddr(hwp, index);
DACDelay(hwp);
hwp->writeDacData(hwp, colors[index].red);
DACDelay(hwp);
hwp->writeDacData(hwp, colors[index].green);
DACDelay(hwp);
hwp->writeDacData(hwp, colors[index].blue);
DACDelay(hwp);
}
/* This shouldn't be necessary, but we'll play safe. */
hwp->disablePalette(hwp);
}
static void
vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
if (overscan < 0 || overscan > 255)
return;
hwp->enablePalette(hwp);
hwp->writeAttr(hwp, OVERSCAN, overscan);
#ifdef DEBUGOVERSCAN
{
int ov = hwp->readAttr(hwp, OVERSCAN);
int red, green, blue;
hwp->writeDacReadAddr(hwp, ov);
red = hwp->readDacData(hwp);
green = hwp->readDacData(hwp);
blue = hwp->readDacData(hwp);
ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
ov, red, green, blue);
}
#endif
hwp->disablePalette(hwp);
}
Bool
vgaHWHandleColormaps(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
if (pScrn->depth > 1 && pScrn->depth <= 8) {
return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
pScrn->rgbBits, vgaHWLoadPalette,
pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
CMAP_RELOAD_ON_MODE_SWITCH);
}
return TRUE;
}
/* ----------------------- DDC support ------------------------*/
/*
* Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
* to read out EDID at a faster rate. Allowed maximum is 25kHz with
* 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
* readback, enable access to cr00-cr07.
*/
/* vertical timings */
#define DISPLAY_END 0x04
#define BLANK_START DISPLAY_END
#define SYNC_START BLANK_START
#define SYNC_END 0x09
#define BLANK_END SYNC_END
#define V_TOTAL BLANK_END
/* this function doesn't have to be reentrant for our purposes */
struct _vgaDdcSave {
unsigned char cr03;
unsigned char cr06;
unsigned char cr07;
unsigned char cr09;
unsigned char cr10;
unsigned char cr11;
unsigned char cr12;
unsigned char cr15;
unsigned char cr16;
unsigned char msr;
};
void
vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
unsigned char tmp;
struct _vgaDdcSave *save;
switch (speed) {
case DDC_FAST:
if (hwp->ddc != NULL)
break;
hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
save = (struct _vgaDdcSave *) hwp->ddc;
/* Lightpen register disable - allow access to cr10 & 11; just in case */
save->cr03 = hwp->readCrtc(hwp, 0x03);
hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
save->cr12 = hwp->readCrtc(hwp, 0x12);
hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
save->cr15 = hwp->readCrtc(hwp, 0x15);
hwp->writeCrtc(hwp, 0x15, BLANK_START);
save->cr10 = hwp->readCrtc(hwp, 0x10);
hwp->writeCrtc(hwp, 0x10, SYNC_START);
save->cr11 = hwp->readCrtc(hwp, 0x11);
/* unprotect group 1 registers; just in case ... */
hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
save->cr16 = hwp->readCrtc(hwp, 0x16);
hwp->writeCrtc(hwp, 0x16, BLANK_END);
save->cr06 = hwp->readCrtc(hwp, 0x06);
hwp->writeCrtc(hwp, 0x06, V_TOTAL);
/* all values have less than 8 bit - mask out 9th and 10th bits */
save->cr09 = hwp->readCrtc(hwp, 0x09);
hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
save->cr07 = hwp->readCrtc(hwp, 0x07);
hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
/* vsync polarity negativ & ensure a 25MHz clock */
save->msr = hwp->readMiscOut(hwp);
hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
break;
case DDC_SLOW:
if (hwp->ddc == NULL)
break;
save = (struct _vgaDdcSave *) hwp->ddc;
hwp->writeMiscOut(hwp, save->msr);
hwp->writeCrtc(hwp, 0x07, save->cr07);
tmp = hwp->readCrtc(hwp, 0x09);
hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
hwp->writeCrtc(hwp, 0x06, save->cr06);
hwp->writeCrtc(hwp, 0x16, save->cr16);
hwp->writeCrtc(hwp, 0x11, save->cr11);
hwp->writeCrtc(hwp, 0x10, save->cr10);
hwp->writeCrtc(hwp, 0x15, save->cr15);
hwp->writeCrtc(hwp, 0x12, save->cr12);
hwp->writeCrtc(hwp, 0x03, save->cr03);
free(save);
hwp->ddc = NULL;
break;
default:
break;
}
}
DDC1SetSpeedProc
vgaHWddc1SetSpeedWeak(void)
{
return vgaHWddc1SetSpeed;
}
SaveScreenProcPtr
vgaHWSaveScreenWeak(void)
{
return vgaHWSaveScreen;
}
/*
* xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
*/
void
xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
void (*ProtectRegs) (ScrnInfoPtr, Bool),
void (*BlankScreen) (ScrnInfoPtr, Bool),
unsigned long vertsyncreg, int maskval, int knownclkindex,
int knownclkvalue)
{
register int status = vertsyncreg;
unsigned long i, cnt, rcnt, sync;
vgaHWPtr hwp = VGAHWPTR(pScrn);
/* First save registers that get written on */
(*ClockFunc) (pScrn, CLK_REG_SAVE);
if (num > MAXCLOCKS)
num = MAXCLOCKS;
for (i = 0; i < num; i++) {
if (ProtectRegs)
(*ProtectRegs) (pScrn, TRUE);
if (!(*ClockFunc) (pScrn, i)) {
pScrn->clock[i] = -1;
continue;
}
if (ProtectRegs)
(*ProtectRegs) (pScrn, FALSE);
if (BlankScreen)
(*BlankScreen) (pScrn, FALSE);
usleep(50000); /* let VCO stabilise */
cnt = 0;
sync = 200000;
while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
if (sync-- == 0)
goto finish;
/* Something appears to be happening, so reset sync count */
sync = 200000;
while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
if (sync-- == 0)
goto finish;
/* Something appears to be happening, so reset sync count */
sync = 200000;
while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
if (sync-- == 0)
goto finish;
for (rcnt = 0; rcnt < 5; rcnt++) {
while (!(pci_io_read8(hwp->io, status) & maskval))
cnt++;
while ((pci_io_read8(hwp->io, status) & maskval))
cnt++;
}
finish:
pScrn->clock[i] = cnt ? cnt : -1;
if (BlankScreen)
(*BlankScreen) (pScrn, TRUE);
}
for (i = 0; i < num; i++) {
if (i != knownclkindex) {
if (pScrn->clock[i] == -1) {
pScrn->clock[i] = 0;
}
else {
pScrn->clock[i] = (int) (0.5 +
(((float) knownclkvalue) *
pScrn->clock[knownclkindex]) /
(pScrn->clock[i]));
/* Round to nearest 10KHz */
pScrn->clock[i] += 5;
pScrn->clock[i] /= 10;
pScrn->clock[i] *= 10;
}
}
}
pScrn->clock[knownclkindex] = knownclkvalue;
pScrn->numClocks = num;
/* Restore registers that were written on */
(*ClockFunc) (pScrn, CLK_REG_RESTORE);
}