xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

vgaHW.c (57427B)


      1 
      2 /*
      3  *
      4  * Copyright 1991-1999 by The XFree86 Project, Inc.
      5  *
      6  * Loosely based on code bearing the following copyright:
      7  *
      8  *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
      9  *
     10  */
     11 
     12 #define _NEED_SYSI86
     13 
     14 #ifdef HAVE_XORG_CONFIG_H
     15 #include <xorg-config.h>
     16 #endif
     17 
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #include <unistd.h>
     21 
     22 #include <X11/X.h>
     23 #include "misc.h"
     24 
     25 #include "xf86.h"
     26 #include "xf86_OSproc.h"
     27 #include "vgaHW.h"
     28 
     29 #include "compiler.h"
     30 
     31 #include "xf86cmap.h"
     32 
     33 #include "Pci.h"
     34 
     35 #ifndef SAVE_FONT1
     36 #define SAVE_FONT1 1
     37 #endif
     38 
     39 /*
     40  * These used to be OS-specific, which made this module have an undesirable
     41  * OS dependency.  Define them by default for all platforms.
     42  */
     43 #ifndef NEED_SAVED_CMAP
     44 #define NEED_SAVED_CMAP
     45 #endif
     46 #ifndef SAVE_TEXT
     47 #define SAVE_TEXT 1
     48 #endif
     49 #ifndef SAVE_FONT2
     50 #define SAVE_FONT2 1
     51 #endif
     52 
     53 /* bytes per plane to save for text */
     54 #define TEXT_AMOUNT 16384
     55 
     56 /* bytes per plane to save for font data */
     57 #define FONT_AMOUNT (8*8192)
     58 
     59 #if 0
     60 /* Override all of these for now */
     61 #undef SAVE_FONT1
     62 #define SAVE_FONT1 1
     63 #undef SAVE_FONT2
     64 #define SAVE_FONT2 1
     65 #undef SAVE_TEST
     66 #define SAVE_TEST 1
     67 #undef FONT_AMOUNT
     68 #define FONT_AMOUNT 65536
     69 #undef TEXT_AMOUNT
     70 #define TEXT_AMOUNT 65536
     71 #endif
     72 
     73 /* DAC indices for white and black */
     74 #define WHITE_VALUE 0x3F
     75 #define BLACK_VALUE 0x00
     76 #define OVERSCAN_VALUE 0x01
     77 
     78 /* Use a private definition of this here */
     79 #undef VGAHWPTR
     80 #define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
     81 #define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
     82 
     83 static int vgaHWPrivateIndex = -1;
     84 
     85 #define DAC_TEST_MASK 0x3F
     86 
     87 #ifdef NEED_SAVED_CMAP
     88 /* This default colourmap is used only when it can't be read from the VGA */
     89 
     90 static CARD8 defaultDAC[768] = {
     91     0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
     92     42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
     93     21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
     94     63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
     95     0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11,
     96     14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24,
     97     28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40,
     98     45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63,
     99     0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63,
    100     63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16,
    101     63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0,
    102     63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0,
    103     0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47,
    104     0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63,
    105     31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63,
    106     63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39,
    107     63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31,
    108     63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31,
    109     31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55,
    110     31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63,
    111     45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63,
    112     63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49,
    113     63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45,
    114     63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45,
    115     45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58,
    116     45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63,
    117     0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28,
    118     28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7,
    119     28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0,
    120     28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0,
    121     0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21,
    122     0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28,
    123     14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28,
    124     28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17,
    125     28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14,
    126     28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14,
    127     14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24,
    128     14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28,
    129     20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28,
    130     28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22,
    131     28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20,
    132     28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20,
    133     20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26,
    134     20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28,
    135     0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16,
    136     16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4,
    137     16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0,
    138     16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0,
    139     0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12,
    140     0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16,
    141     8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16,
    142     16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10,
    143     16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8,
    144     16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8,
    145     8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14,
    146     8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16,
    147     11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16,
    148     16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12,
    149     16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11,
    150     16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11,
    151     11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15,
    152     11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16,
    153     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    154     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    155 };
    156 #endif                          /* NEED_SAVED_CMAP */
    157 
    158 /*
    159  * Standard VGA versions of the register access functions.
    160  */
    161 static void
    162 stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
    163 {
    164     pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
    165     pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
    166 }
    167 
    168 static CARD8
    169 stdReadCrtc(vgaHWPtr hwp, CARD8 index)
    170 {
    171     pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
    172     return pci_io_read8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET);
    173 }
    174 
    175 static void
    176 stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
    177 {
    178     pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
    179     pci_io_write8(hwp->io, VGA_GRAPH_DATA, value);
    180 }
    181 
    182 static CARD8
    183 stdReadGr(vgaHWPtr hwp, CARD8 index)
    184 {
    185     pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
    186     return pci_io_read8(hwp->io, VGA_GRAPH_DATA);
    187 }
    188 
    189 static void
    190 stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
    191 {
    192     pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
    193     pci_io_write8(hwp->io, VGA_SEQ_DATA, value);
    194 }
    195 
    196 static CARD8
    197 stdReadSeq(vgaHWPtr hwp, CARD8 index)
    198 {
    199     pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
    200     return pci_io_read8(hwp->io, VGA_SEQ_DATA);
    201 }
    202 
    203 static CARD8
    204 stdReadST00(vgaHWPtr hwp)
    205 {
    206     return pci_io_read8(hwp->io, VGA_IN_STAT_0);
    207 }
    208 
    209 static CARD8
    210 stdReadST01(vgaHWPtr hwp)
    211 {
    212     return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    213 }
    214 
    215 static CARD8
    216 stdReadFCR(vgaHWPtr hwp)
    217 {
    218     return pci_io_read8(hwp->io, VGA_FEATURE_R);
    219 }
    220 
    221 static void
    222 stdWriteFCR(vgaHWPtr hwp, CARD8 value)
    223 {
    224     pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
    225 }
    226 
    227 static void
    228 stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
    229 {
    230     if (hwp->paletteEnabled)
    231         index &= ~0x20;
    232     else
    233         index |= 0x20;
    234 
    235     (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    236     pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
    237     pci_io_write8(hwp->io, VGA_ATTR_DATA_W, value);
    238 }
    239 
    240 static CARD8
    241 stdReadAttr(vgaHWPtr hwp, CARD8 index)
    242 {
    243     if (hwp->paletteEnabled)
    244         index &= ~0x20;
    245     else
    246         index |= 0x20;
    247 
    248     (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    249     pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
    250     return pci_io_read8(hwp->io, VGA_ATTR_DATA_R);
    251 }
    252 
    253 static void
    254 stdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
    255 {
    256     pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
    257 }
    258 
    259 static CARD8
    260 stdReadMiscOut(vgaHWPtr hwp)
    261 {
    262     return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
    263 }
    264 
    265 static void
    266 stdEnablePalette(vgaHWPtr hwp)
    267 {
    268     (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    269     pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x00);
    270     hwp->paletteEnabled = TRUE;
    271 }
    272 
    273 static void
    274 stdDisablePalette(vgaHWPtr hwp)
    275 {
    276     (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    277     pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x20);
    278     hwp->paletteEnabled = FALSE;
    279 }
    280 
    281 static void
    282 stdWriteDacMask(vgaHWPtr hwp, CARD8 value)
    283 {
    284     pci_io_write8(hwp->io, VGA_DAC_MASK, value);
    285 }
    286 
    287 static CARD8
    288 stdReadDacMask(vgaHWPtr hwp)
    289 {
    290     return pci_io_read8(hwp->io, VGA_DAC_MASK);
    291 }
    292 
    293 static void
    294 stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
    295 {
    296     pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
    297 }
    298 
    299 static void
    300 stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
    301 {
    302     pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
    303 }
    304 
    305 static void
    306 stdWriteDacData(vgaHWPtr hwp, CARD8 value)
    307 {
    308     pci_io_write8(hwp->io, VGA_DAC_DATA, value);
    309 }
    310 
    311 static CARD8
    312 stdReadDacData(vgaHWPtr hwp)
    313 {
    314     return pci_io_read8(hwp->io, VGA_DAC_DATA);
    315 }
    316 
    317 static CARD8
    318 stdReadEnable(vgaHWPtr hwp)
    319 {
    320     return pci_io_read8(hwp->io, VGA_ENABLE);
    321 }
    322 
    323 static void
    324 stdWriteEnable(vgaHWPtr hwp, CARD8 value)
    325 {
    326     pci_io_write8(hwp->io, VGA_ENABLE, value);
    327 }
    328 
    329 void
    330 vgaHWSetStdFuncs(vgaHWPtr hwp)
    331 {
    332     hwp->writeCrtc = stdWriteCrtc;
    333     hwp->readCrtc = stdReadCrtc;
    334     hwp->writeGr = stdWriteGr;
    335     hwp->readGr = stdReadGr;
    336     hwp->readST00 = stdReadST00;
    337     hwp->readST01 = stdReadST01;
    338     hwp->readFCR = stdReadFCR;
    339     hwp->writeFCR = stdWriteFCR;
    340     hwp->writeAttr = stdWriteAttr;
    341     hwp->readAttr = stdReadAttr;
    342     hwp->writeSeq = stdWriteSeq;
    343     hwp->readSeq = stdReadSeq;
    344     hwp->writeMiscOut = stdWriteMiscOut;
    345     hwp->readMiscOut = stdReadMiscOut;
    346     hwp->enablePalette = stdEnablePalette;
    347     hwp->disablePalette = stdDisablePalette;
    348     hwp->writeDacMask = stdWriteDacMask;
    349     hwp->readDacMask = stdReadDacMask;
    350     hwp->writeDacWriteAddr = stdWriteDacWriteAddr;
    351     hwp->writeDacReadAddr = stdWriteDacReadAddr;
    352     hwp->writeDacData = stdWriteDacData;
    353     hwp->readDacData = stdReadDacData;
    354     hwp->readEnable = stdReadEnable;
    355     hwp->writeEnable = stdWriteEnable;
    356 
    357     hwp->io = pci_legacy_open_io(hwp->dev, 0, 64 * 1024);
    358 }
    359 
    360 /*
    361  * MMIO versions of the register access functions.  These require
    362  * hwp->MemBase to be set in such a way that when the standard VGA port
    363  * adderss is added the correct memory address results.
    364  */
    365 
    366 #define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
    367 #define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
    368 
    369 static void
    370 mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
    371 {
    372     moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
    373     moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
    374 }
    375 
    376 static CARD8
    377 mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
    378 {
    379     moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
    380     return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
    381 }
    382 
    383 static void
    384 mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
    385 {
    386     moutb(VGA_GRAPH_INDEX, index);
    387     moutb(VGA_GRAPH_DATA, value);
    388 }
    389 
    390 static CARD8
    391 mmioReadGr(vgaHWPtr hwp, CARD8 index)
    392 {
    393     moutb(VGA_GRAPH_INDEX, index);
    394     return minb(VGA_GRAPH_DATA);
    395 }
    396 
    397 static void
    398 mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
    399 {
    400     moutb(VGA_SEQ_INDEX, index);
    401     moutb(VGA_SEQ_DATA, value);
    402 }
    403 
    404 static CARD8
    405 mmioReadSeq(vgaHWPtr hwp, CARD8 index)
    406 {
    407     moutb(VGA_SEQ_INDEX, index);
    408     return minb(VGA_SEQ_DATA);
    409 }
    410 
    411 static CARD8
    412 mmioReadST00(vgaHWPtr hwp)
    413 {
    414     return minb(VGA_IN_STAT_0);
    415 }
    416 
    417 static CARD8
    418 mmioReadST01(vgaHWPtr hwp)
    419 {
    420     return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    421 }
    422 
    423 static CARD8
    424 mmioReadFCR(vgaHWPtr hwp)
    425 {
    426     return minb(VGA_FEATURE_R);
    427 }
    428 
    429 static void
    430 mmioWriteFCR(vgaHWPtr hwp, CARD8 value)
    431 {
    432     moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
    433 }
    434 
    435 static void
    436 mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
    437 {
    438     if (hwp->paletteEnabled)
    439         index &= ~0x20;
    440     else
    441         index |= 0x20;
    442 
    443     (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    444     moutb(VGA_ATTR_INDEX, index);
    445     moutb(VGA_ATTR_DATA_W, value);
    446 }
    447 
    448 static CARD8
    449 mmioReadAttr(vgaHWPtr hwp, CARD8 index)
    450 {
    451     if (hwp->paletteEnabled)
    452         index &= ~0x20;
    453     else
    454         index |= 0x20;
    455 
    456     (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    457     moutb(VGA_ATTR_INDEX, index);
    458     return minb(VGA_ATTR_DATA_R);
    459 }
    460 
    461 static void
    462 mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
    463 {
    464     moutb(VGA_MISC_OUT_W, value);
    465 }
    466 
    467 static CARD8
    468 mmioReadMiscOut(vgaHWPtr hwp)
    469 {
    470     return minb(VGA_MISC_OUT_R);
    471 }
    472 
    473 static void
    474 mmioEnablePalette(vgaHWPtr hwp)
    475 {
    476     (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    477     moutb(VGA_ATTR_INDEX, 0x00);
    478     hwp->paletteEnabled = TRUE;
    479 }
    480 
    481 static void
    482 mmioDisablePalette(vgaHWPtr hwp)
    483 {
    484     (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
    485     moutb(VGA_ATTR_INDEX, 0x20);
    486     hwp->paletteEnabled = FALSE;
    487 }
    488 
    489 static void
    490 mmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
    491 {
    492     moutb(VGA_DAC_MASK, value);
    493 }
    494 
    495 static CARD8
    496 mmioReadDacMask(vgaHWPtr hwp)
    497 {
    498     return minb(VGA_DAC_MASK);
    499 }
    500 
    501 static void
    502 mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
    503 {
    504     moutb(VGA_DAC_READ_ADDR, value);
    505 }
    506 
    507 static void
    508 mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
    509 {
    510     moutb(VGA_DAC_WRITE_ADDR, value);
    511 }
    512 
    513 static void
    514 mmioWriteDacData(vgaHWPtr hwp, CARD8 value)
    515 {
    516     moutb(VGA_DAC_DATA, value);
    517 }
    518 
    519 static CARD8
    520 mmioReadDacData(vgaHWPtr hwp)
    521 {
    522     return minb(VGA_DAC_DATA);
    523 }
    524 
    525 static CARD8
    526 mmioReadEnable(vgaHWPtr hwp)
    527 {
    528     return minb(VGA_ENABLE);
    529 }
    530 
    531 static void
    532 mmioWriteEnable(vgaHWPtr hwp, CARD8 value)
    533 {
    534     moutb(VGA_ENABLE, value);
    535 }
    536 
    537 void
    538 vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
    539 {
    540     hwp->writeCrtc = mmioWriteCrtc;
    541     hwp->readCrtc = mmioReadCrtc;
    542     hwp->writeGr = mmioWriteGr;
    543     hwp->readGr = mmioReadGr;
    544     hwp->readST00 = mmioReadST00;
    545     hwp->readST01 = mmioReadST01;
    546     hwp->readFCR = mmioReadFCR;
    547     hwp->writeFCR = mmioWriteFCR;
    548     hwp->writeAttr = mmioWriteAttr;
    549     hwp->readAttr = mmioReadAttr;
    550     hwp->writeSeq = mmioWriteSeq;
    551     hwp->readSeq = mmioReadSeq;
    552     hwp->writeMiscOut = mmioWriteMiscOut;
    553     hwp->readMiscOut = mmioReadMiscOut;
    554     hwp->enablePalette = mmioEnablePalette;
    555     hwp->disablePalette = mmioDisablePalette;
    556     hwp->writeDacMask = mmioWriteDacMask;
    557     hwp->readDacMask = mmioReadDacMask;
    558     hwp->writeDacWriteAddr = mmioWriteDacWriteAddr;
    559     hwp->writeDacReadAddr = mmioWriteDacReadAddr;
    560     hwp->writeDacData = mmioWriteDacData;
    561     hwp->readDacData = mmioReadDacData;
    562     hwp->MMIOBase = base;
    563     hwp->MMIOOffset = offset;
    564     hwp->readEnable = mmioReadEnable;
    565     hwp->writeEnable = mmioWriteEnable;
    566 }
    567 
    568 /*
    569  * vgaHWProtect --
    570  *	Protect VGA registers and memory from corruption during loads.
    571  */
    572 
    573 void
    574 vgaHWProtect(ScrnInfoPtr pScrn, Bool on)
    575 {
    576     vgaHWPtr hwp = VGAHWPTR(pScrn);
    577 
    578     unsigned char tmp;
    579 
    580     if (pScrn->vtSema) {
    581         if (on) {
    582             /*
    583              * Turn off screen and disable sequencer.
    584              */
    585             tmp = hwp->readSeq(hwp, 0x01);
    586 
    587             vgaHWSeqReset(hwp, TRUE);   /* start synchronous reset */
    588             hwp->writeSeq(hwp, 0x01, tmp | 0x20);       /* disable the display */
    589 
    590             hwp->enablePalette(hwp);
    591         }
    592         else {
    593             /*
    594              * Re-enable sequencer, then turn on screen.
    595              */
    596 
    597             tmp = hwp->readSeq(hwp, 0x01);
    598 
    599             hwp->writeSeq(hwp, 0x01, tmp & ~0x20);      /* re-enable display */
    600             vgaHWSeqReset(hwp, FALSE);  /* clear synchronousreset */
    601 
    602             hwp->disablePalette(hwp);
    603         }
    604     }
    605 }
    606 
    607 vgaHWProtectProc *
    608 vgaHWProtectWeak(void)
    609 {
    610     return vgaHWProtect;
    611 }
    612 
    613 /*
    614  * vgaHWBlankScreen -- blank the screen.
    615  */
    616 
    617 void
    618 vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
    619 {
    620     vgaHWPtr hwp = VGAHWPTR(pScrn);
    621     unsigned char scrn;
    622 
    623     scrn = hwp->readSeq(hwp, 0x01);
    624 
    625     if (on) {
    626         scrn &= ~0x20;          /* enable screen */
    627     }
    628     else {
    629         scrn |= 0x20;           /* blank screen */
    630     }
    631 
    632     vgaHWSeqReset(hwp, TRUE);
    633     hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
    634     vgaHWSeqReset(hwp, FALSE);
    635 }
    636 
    637 vgaHWBlankScreenProc *
    638 vgaHWBlankScreenWeak(void)
    639 {
    640     return vgaHWBlankScreen;
    641 }
    642 
    643 /*
    644  * vgaHWSaveScreen -- blank the screen.
    645  */
    646 
    647 Bool
    648 vgaHWSaveScreen(ScreenPtr pScreen, int mode)
    649 {
    650     ScrnInfoPtr pScrn = NULL;
    651     Bool on;
    652 
    653     if (pScreen != NULL)
    654         pScrn = xf86ScreenToScrn(pScreen);
    655 
    656     on = xf86IsUnblank(mode);
    657 
    658 #if 0
    659     if (on)
    660         SetTimeSinceLastInputEvent();
    661 #endif
    662 
    663     if ((pScrn != NULL) && pScrn->vtSema) {
    664         vgaHWBlankScreen(pScrn, on);
    665     }
    666     return TRUE;
    667 }
    668 
    669 /*
    670  * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
    671  *
    672  * This generic VGA function can only set the Off and On modes.  If the
    673  * Standby and Suspend modes are to be supported, a chip specific replacement
    674  * for this function must be written.
    675  */
    676 
    677 void
    678 vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
    679 {
    680     unsigned char seq1 = 0, crtc17 = 0;
    681     vgaHWPtr hwp = VGAHWPTR(pScrn);
    682 
    683     if (!pScrn->vtSema)
    684         return;
    685 
    686     switch (PowerManagementMode) {
    687     case DPMSModeOn:
    688         /* Screen: On; HSync: On, VSync: On */
    689         seq1 = 0x00;
    690         crtc17 = 0x80;
    691         break;
    692     case DPMSModeStandby:
    693         /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
    694         seq1 = 0x20;
    695         crtc17 = 0x80;
    696         break;
    697     case DPMSModeSuspend:
    698         /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
    699         seq1 = 0x20;
    700         crtc17 = 0x80;
    701         break;
    702     case DPMSModeOff:
    703         /* Screen: Off; HSync: Off, VSync: Off */
    704         seq1 = 0x20;
    705         crtc17 = 0x00;
    706         break;
    707     }
    708     hwp->writeSeq(hwp, 0x00, 0x01);     /* Synchronous Reset */
    709     seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
    710     hwp->writeSeq(hwp, 0x01, seq1);
    711     crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
    712     usleep(10000);
    713     hwp->writeCrtc(hwp, 0x17, crtc17);
    714     hwp->writeSeq(hwp, 0x00, 0x03);     /* End Reset */
    715 }
    716 
    717 /*
    718  * vgaHWSeqReset
    719  *      perform a sequencer reset.
    720  */
    721 
    722 void
    723 vgaHWSeqReset(vgaHWPtr hwp, Bool start)
    724 {
    725     if (start)
    726         hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
    727     else
    728         hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
    729 }
    730 
    731 void
    732 vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
    733 {
    734 #if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
    735     vgaHWPtr hwp = VGAHWPTR(scrninfp);
    736     int savedIOBase;
    737     unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
    738     Bool doMap = FALSE;
    739 
    740     /* If nothing to do, return now */
    741     if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
    742         return;
    743 
    744     if (hwp->Base == NULL) {
    745         doMap = TRUE;
    746         if (!vgaHWMapMem(scrninfp)) {
    747             xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
    748                        "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
    749             return;
    750         }
    751     }
    752 
    753     /* save the registers that are needed here */
    754     miscOut = hwp->readMiscOut(hwp);
    755     attr10 = hwp->readAttr(hwp, 0x10);
    756     gr1 = hwp->readGr(hwp, 0x01);
    757     gr3 = hwp->readGr(hwp, 0x03);
    758     gr4 = hwp->readGr(hwp, 0x04);
    759     gr5 = hwp->readGr(hwp, 0x05);
    760     gr6 = hwp->readGr(hwp, 0x06);
    761     gr8 = hwp->readGr(hwp, 0x08);
    762     seq2 = hwp->readSeq(hwp, 0x02);
    763     seq4 = hwp->readSeq(hwp, 0x04);
    764 
    765     /* save hwp->IOBase and temporarily set it for colour mode */
    766     savedIOBase = hwp->IOBase;
    767     hwp->IOBase = VGA_IOBASE_COLOR;
    768 
    769     /* Force into colour mode */
    770     hwp->writeMiscOut(hwp, miscOut | 0x01);
    771 
    772     vgaHWBlankScreen(scrninfp, FALSE);
    773 
    774     /*
    775      * 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 
    844 void
    845 vgaHWRestoreMode(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 
    875 void
    876 vgaHWRestoreColormap(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 
    900 void
    901 vgaHWRestore(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 
    913 void
    914 vgaHWSaveFonts(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 
   1015 void
   1016 vgaHWSaveMode(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 
   1050 void
   1051 vgaHWSaveColormap(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 
   1148 void
   1149 vgaHWSave(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 
   1170 Bool
   1171 vgaHWInit(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         for (i = 0; i < 16; i++)
   1318             if ((i & (1 << BIT_PLANE)) != 0)
   1319                 regp->Attribute[i] = WHITE_VALUE;
   1320             else
   1321                 regp->Attribute[i] = BLACK_VALUE;
   1322 
   1323         regp->Attribute[16] = 0x01;     /* -VGA2- *//* wrong for the ET4000 */
   1324         if (!hwp->ShowOverscan)
   1325             regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
   1326     }
   1327     else {
   1328         regp->Attribute[0] = 0x00;      /* standard colormap translation */
   1329         regp->Attribute[1] = 0x01;
   1330         regp->Attribute[2] = 0x02;
   1331         regp->Attribute[3] = 0x03;
   1332         regp->Attribute[4] = 0x04;
   1333         regp->Attribute[5] = 0x05;
   1334         regp->Attribute[6] = 0x06;
   1335         regp->Attribute[7] = 0x07;
   1336         regp->Attribute[8] = 0x08;
   1337         regp->Attribute[9] = 0x09;
   1338         regp->Attribute[10] = 0x0A;
   1339         regp->Attribute[11] = 0x0B;
   1340         regp->Attribute[12] = 0x0C;
   1341         regp->Attribute[13] = 0x0D;
   1342         regp->Attribute[14] = 0x0E;
   1343         regp->Attribute[15] = 0x0F;
   1344         if (depth == 4)
   1345             regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
   1346         else
   1347             regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
   1348         /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
   1349     }
   1350     regp->Attribute[18] = 0x0F;
   1351     regp->Attribute[19] = 0x00;
   1352     regp->Attribute[20] = 0x00;
   1353 
   1354     return TRUE;
   1355 }
   1356 
   1357     /*
   1358      * OK, so much for theory.  Now, let's deal with the >real< world...
   1359      *
   1360      * The above CRTC settings are precise in theory, except that many, if not
   1361      * most, VGA clones fail to reset the blanking signal when the character or
   1362      * line counter reaches [HV]Total.  In this case, the signal is only
   1363      * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
   1364      * the case may be) at the start of the >next< scanline or frame, which
   1365      * means only part of the screen shows.  This affects how null overscans
   1366      * are to be implemented on such adapters.
   1367      *
   1368      * Henceforth, VGA cores that implement this broken, but unfortunately
   1369      * common, behaviour are to be designated as KGA's, in honour of Koen
   1370      * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
   1371      * a series of events that led to the discovery of this problem.
   1372      *
   1373      * Some VGA's are KGA's only in the horizontal, or only in the vertical,
   1374      * some in both, others in neither.  Don't let anyone tell you there is
   1375      * such a thing as a VGA "standard"...  And, thank the Creator for the fact
   1376      * that Hilbert spaces are not yet implemented in this industry.
   1377      *
   1378      * The following implements a trick suggested by David Dawes.  This sets
   1379      * [HV]BlankEnd to zero if the blanking interval does not already contain a
   1380      * 0-point, and decrements it by one otherwise.  In the latter case, this
   1381      * will produce a left and/or top overscan which the colourmap code will
   1382      * (still) need to ensure is as close to black as possible.  This will make
   1383      * the behaviour consistent across all chipsets, while allowing all
   1384      * chipsets to display the entire screen.  Non-KGA drivers can ignore the
   1385      * following in their own copy of this code.
   1386      *
   1387      * --  TSI @ UQV,  1998.08.21
   1388      */
   1389 
   1390 CARD32
   1391 vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
   1392                unsigned int Flags)
   1393 {
   1394     int nExtBits = (nBits < 6) ? 0 : nBits - 6;
   1395     CARD32 ExtBits;
   1396     CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
   1397 
   1398     regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
   1399         | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
   1400     regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
   1401         | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
   1402     ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
   1403 
   1404     /* First the horizontal case */
   1405     if ((Flags & KGA_FIX_OVERSCAN)
   1406         && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
   1407         int i = (regp->CRTC[3] & 0x1F)
   1408             | ((regp->CRTC[5] & 0x80) >> 2)
   1409             | ExtBits;
   1410 
   1411         if (Flags & KGA_ENABLE_ON_ZERO) {
   1412             if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
   1413                         & (0x3F | ExtBitMask)))
   1414                 && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
   1415                 i = 0;
   1416         }
   1417         else if (Flags & KGA_BE_TOT_DEC)
   1418             i--;
   1419         regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
   1420         regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
   1421         ExtBits = i & ExtBitMask;
   1422     }
   1423     return ExtBits >> 6;
   1424 }
   1425 
   1426     /*
   1427      * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
   1428      * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
   1429      * very first scanline in a double- or multi-scanned mode.  This last case
   1430      * needs further investigation.
   1431      */
   1432 CARD32
   1433 vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
   1434                unsigned int Flags)
   1435 {
   1436     CARD32 ExtBits;
   1437     CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
   1438     CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
   1439 
   1440     /* If width is not known nBits should be 0. In this
   1441      * case BitMask is set to 0 so we can check for it. */
   1442     CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
   1443     int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
   1444 
   1445     regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
   1446     ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
   1447 
   1448     if ((Flags & KGA_FIX_OVERSCAN)
   1449         && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
   1450         /* Null top overscan */
   1451     {
   1452         int i = regp->CRTC[22] | ExtBits;
   1453 
   1454         if (Flags & KGA_ENABLE_ON_ZERO) {
   1455             if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
   1456                  || ((i > VBlankStart) &&       /* 8-bit case */
   1457                      ((i & 0x7F) > (VBlankStart & 0x7F)))) &&   /* 7-bit case */
   1458                 !(regp->CRTC[9] & 0x9F))        /* 1 scanline/row */
   1459                 i = 0;
   1460             else
   1461                 i = (i - 1);
   1462         }
   1463         else if (Flags & KGA_BE_TOT_DEC)
   1464             i = (i - 1);
   1465 
   1466         regp->CRTC[22] = i & 0xFF;
   1467         ExtBits = i & 0xFF00;
   1468     }
   1469     return ExtBits >> 8;
   1470 }
   1471 
   1472 /*
   1473  * these are some more hardware specific helpers, formerly in vga.c
   1474  */
   1475 static void
   1476 vgaHWGetHWRecPrivate(void)
   1477 {
   1478     if (vgaHWPrivateIndex < 0)
   1479         vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
   1480     return;
   1481 }
   1482 
   1483 static void
   1484 vgaHWFreeRegs(vgaRegPtr regp)
   1485 {
   1486     free(regp->CRTC);
   1487 
   1488     regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
   1489 
   1490     regp->numCRTC =
   1491         regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
   1492 }
   1493 
   1494 static Bool
   1495 vgaHWAllocRegs(vgaRegPtr regp)
   1496 {
   1497     unsigned char *buf;
   1498 
   1499     if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
   1500          regp->numAttribute) == 0)
   1501         return FALSE;
   1502 
   1503     buf = calloc(regp->numCRTC +
   1504                  regp->numSequencer +
   1505                  regp->numGraphics + regp->numAttribute, 1);
   1506     if (!buf)
   1507         return FALSE;
   1508 
   1509     regp->CRTC = buf;
   1510     regp->Sequencer = regp->CRTC + regp->numCRTC;
   1511     regp->Graphics = regp->Sequencer + regp->numSequencer;
   1512     regp->Attribute = regp->Graphics + regp->numGraphics;
   1513 
   1514     return TRUE;
   1515 }
   1516 
   1517 Bool
   1518 vgaHWAllocDefaultRegs(vgaRegPtr regp)
   1519 {
   1520     regp->numCRTC = VGA_NUM_CRTC;
   1521     regp->numSequencer = VGA_NUM_SEQ;
   1522     regp->numGraphics = VGA_NUM_GFX;
   1523     regp->numAttribute = VGA_NUM_ATTR;
   1524 
   1525     return vgaHWAllocRegs(regp);
   1526 }
   1527 
   1528 Bool
   1529 vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
   1530                   int numGraphics, int numAttribute)
   1531 {
   1532 #define VGAHWMINNUM(regtype) \
   1533 	((newMode.num##regtype < regp->num##regtype) ? \
   1534 	 (newMode.num##regtype) : (regp->num##regtype))
   1535 #define VGAHWCOPYREGSET(regtype) \
   1536 	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
   1537 
   1538     vgaRegRec newMode, newSaved;
   1539     vgaRegPtr regp;
   1540 
   1541     regp = &VGAHWPTR(scrp)->ModeReg;
   1542     memcpy(&newMode, regp, sizeof(vgaRegRec));
   1543 
   1544     /* allocate space for new registers */
   1545 
   1546     regp = &newMode;
   1547     regp->numCRTC = numCRTC;
   1548     regp->numSequencer = numSequencer;
   1549     regp->numGraphics = numGraphics;
   1550     regp->numAttribute = numAttribute;
   1551     if (!vgaHWAllocRegs(regp))
   1552         return FALSE;
   1553 
   1554     regp = &VGAHWPTR(scrp)->SavedReg;
   1555     memcpy(&newSaved, regp, sizeof(vgaRegRec));
   1556 
   1557     regp = &newSaved;
   1558     regp->numCRTC = numCRTC;
   1559     regp->numSequencer = numSequencer;
   1560     regp->numGraphics = numGraphics;
   1561     regp->numAttribute = numAttribute;
   1562     if (!vgaHWAllocRegs(regp)) {
   1563         vgaHWFreeRegs(&newMode);
   1564         return FALSE;
   1565     }
   1566 
   1567     /* allocations succeeded, copy register data into new space */
   1568 
   1569     regp = &VGAHWPTR(scrp)->ModeReg;
   1570     VGAHWCOPYREGSET(CRTC);
   1571     VGAHWCOPYREGSET(Sequencer);
   1572     VGAHWCOPYREGSET(Graphics);
   1573     VGAHWCOPYREGSET(Attribute);
   1574 
   1575     regp = &VGAHWPTR(scrp)->SavedReg;
   1576     VGAHWCOPYREGSET(CRTC);
   1577     VGAHWCOPYREGSET(Sequencer);
   1578     VGAHWCOPYREGSET(Graphics);
   1579     VGAHWCOPYREGSET(Attribute);
   1580 
   1581     /* free old register arrays */
   1582 
   1583     regp = &VGAHWPTR(scrp)->ModeReg;
   1584     vgaHWFreeRegs(regp);
   1585     memcpy(regp, &newMode, sizeof(vgaRegRec));
   1586 
   1587     regp = &VGAHWPTR(scrp)->SavedReg;
   1588     vgaHWFreeRegs(regp);
   1589     memcpy(regp, &newSaved, sizeof(vgaRegRec));
   1590 
   1591     return TRUE;
   1592 
   1593 #undef VGAHWMINNUM
   1594 #undef VGAHWCOPYREGSET
   1595 }
   1596 
   1597 Bool
   1598 vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
   1599 {
   1600     vgaHWFreeRegs(dst);
   1601 
   1602     memcpy(dst, src, sizeof(vgaRegRec));
   1603 
   1604     if (!vgaHWAllocRegs(dst))
   1605         return FALSE;
   1606 
   1607     memcpy(dst->CRTC, src->CRTC, src->numCRTC);
   1608     memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
   1609     memcpy(dst->Graphics, src->Graphics, src->numGraphics);
   1610     memcpy(dst->Attribute, src->Attribute, src->numAttribute);
   1611 
   1612     return TRUE;
   1613 }
   1614 
   1615 Bool
   1616 vgaHWGetHWRec(ScrnInfoPtr scrp)
   1617 {
   1618     vgaRegPtr regp;
   1619     vgaHWPtr hwp;
   1620     int i;
   1621 
   1622     /*
   1623      * Let's make sure that the private exists and allocate one.
   1624      */
   1625     vgaHWGetHWRecPrivate();
   1626     /*
   1627      * New privates are always set to NULL, so we can check if the allocation
   1628      * has already been done.
   1629      */
   1630     if (VGAHWPTR(scrp))
   1631         return TRUE;
   1632     hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
   1633     regp = &VGAHWPTR(scrp)->ModeReg;
   1634 
   1635     if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
   1636         (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
   1637         free(hwp);
   1638         return FALSE;
   1639     }
   1640 
   1641     if (scrp->bitsPerPixel == 1) {
   1642         rgb blackColour = scrp->display->blackColour,
   1643             whiteColour = scrp->display->whiteColour;
   1644 
   1645         if (blackColour.red > 0x3F)
   1646             blackColour.red = 0x3F;
   1647         if (blackColour.green > 0x3F)
   1648             blackColour.green = 0x3F;
   1649         if (blackColour.blue > 0x3F)
   1650             blackColour.blue = 0x3F;
   1651 
   1652         if (whiteColour.red > 0x3F)
   1653             whiteColour.red = 0x3F;
   1654         if (whiteColour.green > 0x3F)
   1655             whiteColour.green = 0x3F;
   1656         if (whiteColour.blue > 0x3F)
   1657             whiteColour.blue = 0x3F;
   1658 
   1659         if ((blackColour.red == whiteColour.red) &&
   1660             (blackColour.green == whiteColour.green) &&
   1661             (blackColour.blue == whiteColour.blue)) {
   1662             blackColour.red ^= 0x3F;
   1663             blackColour.green ^= 0x3F;
   1664             blackColour.blue ^= 0x3F;
   1665         }
   1666 
   1667         /*
   1668          * initialize default colormap for monochrome
   1669          */
   1670         for (i = 0; i < 3; i++)
   1671             regp->DAC[i] = 0x00;
   1672         for (i = 3; i < 768; i++)
   1673             regp->DAC[i] = 0x3F;
   1674         i = BLACK_VALUE * 3;
   1675         regp->DAC[i++] = blackColour.red;
   1676         regp->DAC[i++] = blackColour.green;
   1677         regp->DAC[i] = blackColour.blue;
   1678         i = WHITE_VALUE * 3;
   1679         regp->DAC[i++] = whiteColour.red;
   1680         regp->DAC[i++] = whiteColour.green;
   1681         regp->DAC[i] = whiteColour.blue;
   1682         i = OVERSCAN_VALUE * 3;
   1683         regp->DAC[i++] = 0x00;
   1684         regp->DAC[i++] = 0x00;
   1685         regp->DAC[i] = 0x00;
   1686     }
   1687     else {
   1688         /* Set all colours to black */
   1689         for (i = 0; i < 768; i++)
   1690             regp->DAC[i] = 0x00;
   1691         /* ... and the overscan */
   1692         if (scrp->depth >= 4)
   1693             regp->Attribute[OVERSCAN] = 0xFF;
   1694     }
   1695     if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
   1696         xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
   1697         xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
   1698         regp->DAC[765] = 0x3F;
   1699         regp->DAC[766] = 0x00;
   1700         regp->DAC[767] = 0x3F;
   1701         regp->Attribute[OVERSCAN] = 0xFF;
   1702         hwp->ShowOverscan = TRUE;
   1703     }
   1704     else
   1705         hwp->ShowOverscan = FALSE;
   1706 
   1707     hwp->paletteEnabled = FALSE;
   1708     hwp->cmapSaved = FALSE;
   1709     hwp->MapSize = 0;
   1710     hwp->pScrn = scrp;
   1711 
   1712     hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
   1713 
   1714     return TRUE;
   1715 }
   1716 
   1717 void
   1718 vgaHWFreeHWRec(ScrnInfoPtr scrp)
   1719 {
   1720     if (vgaHWPrivateIndex >= 0) {
   1721         vgaHWPtr hwp = VGAHWPTR(scrp);
   1722 
   1723         if (!hwp)
   1724             return;
   1725 
   1726         pci_device_close_io(hwp->dev, hwp->io);
   1727 
   1728         free(hwp->FontInfo1);
   1729         free(hwp->FontInfo2);
   1730         free(hwp->TextInfo);
   1731 
   1732         vgaHWFreeRegs(&hwp->ModeReg);
   1733         vgaHWFreeRegs(&hwp->SavedReg);
   1734 
   1735         free(hwp);
   1736         VGAHWPTRLVAL(scrp) = NULL;
   1737     }
   1738 }
   1739 
   1740 Bool
   1741 vgaHWMapMem(ScrnInfoPtr scrp)
   1742 {
   1743     vgaHWPtr hwp = VGAHWPTR(scrp);
   1744 
   1745     if (hwp->Base)
   1746         return TRUE;
   1747 
   1748     /* If not set, initialise with the defaults */
   1749     if (hwp->MapSize == 0)
   1750         hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
   1751     if (hwp->MapPhys == 0)
   1752         hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
   1753 
   1754     /*
   1755      * Map as VIDMEM_MMIO_32BIT because WC
   1756      * is bad when there is page flipping.
   1757      * XXX This is not correct but we do it
   1758      * for now.
   1759      */
   1760     DebugF("Mapping VGAMem\n");
   1761     pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
   1762                           PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
   1763     return hwp->Base != NULL;
   1764 }
   1765 
   1766 void
   1767 vgaHWUnmapMem(ScrnInfoPtr scrp)
   1768 {
   1769     vgaHWPtr hwp = VGAHWPTR(scrp);
   1770 
   1771     if (hwp->Base == NULL)
   1772         return;
   1773 
   1774     DebugF("Unmapping VGAMem\n");
   1775     pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
   1776     hwp->Base = NULL;
   1777 }
   1778 
   1779 int
   1780 vgaHWGetIndex(void)
   1781 {
   1782     return vgaHWPrivateIndex;
   1783 }
   1784 
   1785 void
   1786 vgaHWGetIOBase(vgaHWPtr hwp)
   1787 {
   1788     hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
   1789         VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
   1790     xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
   1791                    "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
   1792 }
   1793 
   1794 void
   1795 vgaHWLock(vgaHWPtr hwp)
   1796 {
   1797     /* Protect CRTC[0-7] */
   1798     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
   1799 }
   1800 
   1801 void
   1802 vgaHWUnlock(vgaHWPtr hwp)
   1803 {
   1804     /* Unprotect CRTC[0-7] */
   1805     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
   1806 }
   1807 
   1808 void
   1809 vgaHWEnable(vgaHWPtr hwp)
   1810 {
   1811     hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
   1812 }
   1813 
   1814 void
   1815 vgaHWDisable(vgaHWPtr hwp)
   1816 {
   1817     hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
   1818 }
   1819 
   1820 static void
   1821 vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
   1822                  VisualPtr pVisual)
   1823 {
   1824     vgaHWPtr hwp = VGAHWPTR(pScrn);
   1825     int i, index;
   1826 
   1827     for (i = 0; i < numColors; i++) {
   1828         index = indices[i];
   1829         hwp->writeDacWriteAddr(hwp, index);
   1830         DACDelay(hwp);
   1831         hwp->writeDacData(hwp, colors[index].red);
   1832         DACDelay(hwp);
   1833         hwp->writeDacData(hwp, colors[index].green);
   1834         DACDelay(hwp);
   1835         hwp->writeDacData(hwp, colors[index].blue);
   1836         DACDelay(hwp);
   1837     }
   1838 
   1839     /* This shouldn't be necessary, but we'll play safe. */
   1840     hwp->disablePalette(hwp);
   1841 }
   1842 
   1843 static void
   1844 vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
   1845 {
   1846     vgaHWPtr hwp = VGAHWPTR(pScrn);
   1847 
   1848     if (overscan < 0 || overscan > 255)
   1849         return;
   1850 
   1851     hwp->enablePalette(hwp);
   1852     hwp->writeAttr(hwp, OVERSCAN, overscan);
   1853 
   1854 #ifdef DEBUGOVERSCAN
   1855     {
   1856         int ov = hwp->readAttr(hwp, OVERSCAN);
   1857         int red, green, blue;
   1858 
   1859         hwp->writeDacReadAddr(hwp, ov);
   1860         red = hwp->readDacData(hwp);
   1861         green = hwp->readDacData(hwp);
   1862         blue = hwp->readDacData(hwp);
   1863         ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
   1864                ov, red, green, blue);
   1865     }
   1866 #endif
   1867 
   1868     hwp->disablePalette(hwp);
   1869 }
   1870 
   1871 Bool
   1872 vgaHWHandleColormaps(ScreenPtr pScreen)
   1873 {
   1874     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1875 
   1876     if (pScrn->depth > 1 && pScrn->depth <= 8) {
   1877         return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
   1878                                    pScrn->rgbBits, vgaHWLoadPalette,
   1879                                    pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
   1880                                    CMAP_RELOAD_ON_MODE_SWITCH);
   1881     }
   1882     return TRUE;
   1883 }
   1884 
   1885 /* ----------------------- DDC support ------------------------*/
   1886 /*
   1887  * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
   1888  * to read out EDID at a faster rate. Allowed maximum is 25kHz with
   1889  * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
   1890  * readback, enable access to cr00-cr07.
   1891  */
   1892 
   1893 /* vertical timings */
   1894 #define DISPLAY_END 0x04
   1895 #define BLANK_START DISPLAY_END
   1896 #define SYNC_START BLANK_START
   1897 #define SYNC_END 0x09
   1898 #define BLANK_END SYNC_END
   1899 #define V_TOTAL BLANK_END
   1900 /* this function doesn't have to be reentrant for our purposes */
   1901 struct _vgaDdcSave {
   1902     unsigned char cr03;
   1903     unsigned char cr06;
   1904     unsigned char cr07;
   1905     unsigned char cr09;
   1906     unsigned char cr10;
   1907     unsigned char cr11;
   1908     unsigned char cr12;
   1909     unsigned char cr15;
   1910     unsigned char cr16;
   1911     unsigned char msr;
   1912 };
   1913 
   1914 void
   1915 vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
   1916 {
   1917     vgaHWPtr hwp = VGAHWPTR(pScrn);
   1918     unsigned char tmp;
   1919     struct _vgaDdcSave *save;
   1920 
   1921     switch (speed) {
   1922     case DDC_FAST:
   1923 
   1924         if (hwp->ddc != NULL)
   1925             break;
   1926         hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
   1927         save = (struct _vgaDdcSave *) hwp->ddc;
   1928         /* Lightpen register disable - allow access to cr10 & 11; just in case */
   1929         save->cr03 = hwp->readCrtc(hwp, 0x03);
   1930         hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
   1931         save->cr12 = hwp->readCrtc(hwp, 0x12);
   1932         hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
   1933         save->cr15 = hwp->readCrtc(hwp, 0x15);
   1934         hwp->writeCrtc(hwp, 0x15, BLANK_START);
   1935         save->cr10 = hwp->readCrtc(hwp, 0x10);
   1936         hwp->writeCrtc(hwp, 0x10, SYNC_START);
   1937         save->cr11 = hwp->readCrtc(hwp, 0x11);
   1938         /* unprotect group 1 registers; just in case ... */
   1939         hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
   1940         save->cr16 = hwp->readCrtc(hwp, 0x16);
   1941         hwp->writeCrtc(hwp, 0x16, BLANK_END);
   1942         save->cr06 = hwp->readCrtc(hwp, 0x06);
   1943         hwp->writeCrtc(hwp, 0x06, V_TOTAL);
   1944         /* all values have less than 8 bit - mask out 9th and 10th bits */
   1945         save->cr09 = hwp->readCrtc(hwp, 0x09);
   1946         hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
   1947         save->cr07 = hwp->readCrtc(hwp, 0x07);
   1948         hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
   1949         /* vsync polarity negative & ensure a 25MHz clock */
   1950         save->msr = hwp->readMiscOut(hwp);
   1951         hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
   1952         break;
   1953     case DDC_SLOW:
   1954         if (hwp->ddc == NULL)
   1955             break;
   1956         save = (struct _vgaDdcSave *) hwp->ddc;
   1957         hwp->writeMiscOut(hwp, save->msr);
   1958         hwp->writeCrtc(hwp, 0x07, save->cr07);
   1959         tmp = hwp->readCrtc(hwp, 0x09);
   1960         hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
   1961         hwp->writeCrtc(hwp, 0x06, save->cr06);
   1962         hwp->writeCrtc(hwp, 0x16, save->cr16);
   1963         hwp->writeCrtc(hwp, 0x11, save->cr11);
   1964         hwp->writeCrtc(hwp, 0x10, save->cr10);
   1965         hwp->writeCrtc(hwp, 0x15, save->cr15);
   1966         hwp->writeCrtc(hwp, 0x12, save->cr12);
   1967         hwp->writeCrtc(hwp, 0x03, save->cr03);
   1968         free(save);
   1969         hwp->ddc = NULL;
   1970         break;
   1971     default:
   1972         break;
   1973     }
   1974 }
   1975 
   1976 DDC1SetSpeedProc
   1977 vgaHWddc1SetSpeedWeak(void)
   1978 {
   1979     return vgaHWddc1SetSpeed;
   1980 }
   1981 
   1982 SaveScreenProcPtr
   1983 vgaHWSaveScreenWeak(void)
   1984 {
   1985     return vgaHWSaveScreen;
   1986 }
   1987 
   1988 /*
   1989  * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
   1990  */
   1991 void
   1992 xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
   1993               void (*ProtectRegs) (ScrnInfoPtr, Bool),
   1994               void (*BlankScreen) (ScrnInfoPtr, Bool),
   1995               unsigned long vertsyncreg, int maskval, int knownclkindex,
   1996               int knownclkvalue)
   1997 {
   1998     register int status = vertsyncreg;
   1999     unsigned long i, cnt, rcnt, sync;
   2000     vgaHWPtr hwp = VGAHWPTR(pScrn);
   2001 
   2002     /* First save registers that get written on */
   2003     (*ClockFunc) (pScrn, CLK_REG_SAVE);
   2004 
   2005     if (num > MAXCLOCKS)
   2006         num = MAXCLOCKS;
   2007 
   2008     for (i = 0; i < num; i++) {
   2009         if (ProtectRegs)
   2010             (*ProtectRegs) (pScrn, TRUE);
   2011         if (!(*ClockFunc) (pScrn, i)) {
   2012             pScrn->clock[i] = -1;
   2013             continue;
   2014         }
   2015         if (ProtectRegs)
   2016             (*ProtectRegs) (pScrn, FALSE);
   2017         if (BlankScreen)
   2018             (*BlankScreen) (pScrn, FALSE);
   2019 
   2020         usleep(50000);          /* let VCO stabilise */
   2021 
   2022         cnt = 0;
   2023         sync = 200000;
   2024 
   2025         while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
   2026             if (sync-- == 0)
   2027                 goto finish;
   2028         /* Something appears to be happening, so reset sync count */
   2029         sync = 200000;
   2030         while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
   2031             if (sync-- == 0)
   2032                 goto finish;
   2033         /* Something appears to be happening, so reset sync count */
   2034         sync = 200000;
   2035         while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
   2036             if (sync-- == 0)
   2037                 goto finish;
   2038 
   2039         for (rcnt = 0; rcnt < 5; rcnt++) {
   2040             while (!(pci_io_read8(hwp->io, status) & maskval))
   2041                 cnt++;
   2042             while ((pci_io_read8(hwp->io, status) & maskval))
   2043                 cnt++;
   2044         }
   2045 
   2046  finish:
   2047         pScrn->clock[i] = cnt ? cnt : -1;
   2048         if (BlankScreen)
   2049             (*BlankScreen) (pScrn, TRUE);
   2050     }
   2051 
   2052     for (i = 0; i < num; i++) {
   2053         if (i != knownclkindex) {
   2054             if (pScrn->clock[i] == -1) {
   2055                 pScrn->clock[i] = 0;
   2056             }
   2057             else {
   2058                 pScrn->clock[i] = (int) (0.5 +
   2059                                          (((float) knownclkvalue) *
   2060                                           pScrn->clock[knownclkindex]) /
   2061                                          (pScrn->clock[i]));
   2062                 /* Round to nearest 10KHz */
   2063                 pScrn->clock[i] += 5;
   2064                 pScrn->clock[i] /= 10;
   2065                 pScrn->clock[i] *= 10;
   2066             }
   2067         }
   2068     }
   2069 
   2070     pScrn->clock[knownclkindex] = knownclkvalue;
   2071     pScrn->numClocks = num;
   2072 
   2073     /* Restore registers that were written on */
   2074     (*ClockFunc) (pScrn, CLK_REG_RESTORE);
   2075 }