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