vgaHW.c revision ed6184df
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 83static 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 90static 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 */ 161static void 162stdWriteCrtc(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 168static CARD8 169stdReadCrtc(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 175static void 176stdWriteGr(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 182static CARD8 183stdReadGr(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 189static void 190stdWriteSeq(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 196static CARD8 197stdReadSeq(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 203static CARD8 204stdReadST00(vgaHWPtr hwp) 205{ 206 return pci_io_read8(hwp->io, VGA_IN_STAT_0); 207} 208 209static CARD8 210stdReadST01(vgaHWPtr hwp) 211{ 212 return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET); 213} 214 215static CARD8 216stdReadFCR(vgaHWPtr hwp) 217{ 218 return pci_io_read8(hwp->io, VGA_FEATURE_R); 219} 220 221static void 222stdWriteFCR(vgaHWPtr hwp, CARD8 value) 223{ 224 pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value); 225} 226 227static void 228stdWriteAttr(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 240static CARD8 241stdReadAttr(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 253static void 254stdWriteMiscOut(vgaHWPtr hwp, CARD8 value) 255{ 256 pci_io_write8(hwp->io, VGA_MISC_OUT_W, value); 257} 258 259static CARD8 260stdReadMiscOut(vgaHWPtr hwp) 261{ 262 return pci_io_read8(hwp->io, VGA_MISC_OUT_R); 263} 264 265static void 266stdEnablePalette(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 273static void 274stdDisablePalette(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 281static void 282stdWriteDacMask(vgaHWPtr hwp, CARD8 value) 283{ 284 pci_io_write8(hwp->io, VGA_DAC_MASK, value); 285} 286 287static CARD8 288stdReadDacMask(vgaHWPtr hwp) 289{ 290 return pci_io_read8(hwp->io, VGA_DAC_MASK); 291} 292 293static void 294stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) 295{ 296 pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value); 297} 298 299static void 300stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) 301{ 302 pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value); 303} 304 305static void 306stdWriteDacData(vgaHWPtr hwp, CARD8 value) 307{ 308 pci_io_write8(hwp->io, VGA_DAC_DATA, value); 309} 310 311static CARD8 312stdReadDacData(vgaHWPtr hwp) 313{ 314 return pci_io_read8(hwp->io, VGA_DAC_DATA); 315} 316 317static CARD8 318stdReadEnable(vgaHWPtr hwp) 319{ 320 return pci_io_read8(hwp->io, VGA_ENABLE); 321} 322 323static void 324stdWriteEnable(vgaHWPtr hwp, CARD8 value) 325{ 326 pci_io_write8(hwp->io, VGA_ENABLE, value); 327} 328 329void 330vgaHWSetStdFuncs(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 369static void 370mmioWriteCrtc(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 376static CARD8 377mmioReadCrtc(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 383static void 384mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) 385{ 386 moutb(VGA_GRAPH_INDEX, index); 387 moutb(VGA_GRAPH_DATA, value); 388} 389 390static CARD8 391mmioReadGr(vgaHWPtr hwp, CARD8 index) 392{ 393 moutb(VGA_GRAPH_INDEX, index); 394 return minb(VGA_GRAPH_DATA); 395} 396 397static void 398mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) 399{ 400 moutb(VGA_SEQ_INDEX, index); 401 moutb(VGA_SEQ_DATA, value); 402} 403 404static CARD8 405mmioReadSeq(vgaHWPtr hwp, CARD8 index) 406{ 407 moutb(VGA_SEQ_INDEX, index); 408 return minb(VGA_SEQ_DATA); 409} 410 411static CARD8 412mmioReadST00(vgaHWPtr hwp) 413{ 414 return minb(VGA_IN_STAT_0); 415} 416 417static CARD8 418mmioReadST01(vgaHWPtr hwp) 419{ 420 return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 421} 422 423static CARD8 424mmioReadFCR(vgaHWPtr hwp) 425{ 426 return minb(VGA_FEATURE_R); 427} 428 429static void 430mmioWriteFCR(vgaHWPtr hwp, CARD8 value) 431{ 432 moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value); 433} 434 435static void 436mmioWriteAttr(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 448static CARD8 449mmioReadAttr(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 461static void 462mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value) 463{ 464 moutb(VGA_MISC_OUT_W, value); 465} 466 467static CARD8 468mmioReadMiscOut(vgaHWPtr hwp) 469{ 470 return minb(VGA_MISC_OUT_R); 471} 472 473static void 474mmioEnablePalette(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 481static void 482mmioDisablePalette(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 489static void 490mmioWriteDacMask(vgaHWPtr hwp, CARD8 value) 491{ 492 moutb(VGA_DAC_MASK, value); 493} 494 495static CARD8 496mmioReadDacMask(vgaHWPtr hwp) 497{ 498 return minb(VGA_DAC_MASK); 499} 500 501static void 502mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) 503{ 504 moutb(VGA_DAC_READ_ADDR, value); 505} 506 507static void 508mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) 509{ 510 moutb(VGA_DAC_WRITE_ADDR, value); 511} 512 513static void 514mmioWriteDacData(vgaHWPtr hwp, CARD8 value) 515{ 516 moutb(VGA_DAC_DATA, value); 517} 518 519static CARD8 520mmioReadDacData(vgaHWPtr hwp) 521{ 522 return minb(VGA_DAC_DATA); 523} 524 525static CARD8 526mmioReadEnable(vgaHWPtr hwp) 527{ 528 return minb(VGA_ENABLE); 529} 530 531static void 532mmioWriteEnable(vgaHWPtr hwp, CARD8 value) 533{ 534 moutb(VGA_ENABLE, value); 535} 536 537void 538vgaHWSetMmioFuncs(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 573void 574vgaHWProtect(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 607vgaHWProtectProc * 608vgaHWProtectWeak(void) 609{ 610 return vgaHWProtect; 611} 612 613/* 614 * vgaHWBlankScreen -- blank the screen. 615 */ 616 617void 618vgaHWBlankScreen(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 637vgaHWBlankScreenProc * 638vgaHWBlankScreenWeak(void) 639{ 640 return vgaHWBlankScreen; 641} 642 643/* 644 * vgaHWSaveScreen -- blank the screen. 645 */ 646 647Bool 648vgaHWSaveScreen(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 677void 678vgaHWDPMSSet(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 722void 723vgaHWSeqReset(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 731void 732vgaHWRestoreFonts(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 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 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 1390CARD32 1391vgaHWHBlankKGA(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 */ 1432CARD32 1433vgaHWVBlankKGA(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 */ 1475static void 1476vgaHWGetHWRecPrivate(void) 1477{ 1478 if (vgaHWPrivateIndex < 0) 1479 vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); 1480 return; 1481} 1482 1483static void 1484vgaHWFreeRegs(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 1494static Bool 1495vgaHWAllocRegs(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 1517Bool 1518vgaHWAllocDefaultRegs(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 1528Bool 1529vgaHWSetRegCounts(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 1597Bool 1598vgaHWCopyReg(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 1615Bool 1616vgaHWGetHWRec(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 1717void 1718vgaHWFreeHWRec(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 1740Bool 1741vgaHWMapMem(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 1766void 1767vgaHWUnmapMem(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 1779int 1780vgaHWGetIndex(void) 1781{ 1782 return vgaHWPrivateIndex; 1783} 1784 1785void 1786vgaHWGetIOBase(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 1794void 1795vgaHWLock(vgaHWPtr hwp) 1796{ 1797 /* Protect CRTC[0-7] */ 1798 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80); 1799} 1800 1801void 1802vgaHWUnlock(vgaHWPtr hwp) 1803{ 1804 /* Unprotect CRTC[0-7] */ 1805 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80); 1806} 1807 1808void 1809vgaHWEnable(vgaHWPtr hwp) 1810{ 1811 hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01); 1812} 1813 1814void 1815vgaHWDisable(vgaHWPtr hwp) 1816{ 1817 hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01); 1818} 1819 1820static void 1821vgaHWLoadPalette(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 1843static void 1844vgaHWSetOverscan(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 1871Bool 1872vgaHWHandleColormaps(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 */ 1901struct _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 1914void 1915vgaHWddc1SetSpeed(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 1976DDC1SetSpeedProc 1977vgaHWddc1SetSpeedWeak(void) 1978{ 1979 return vgaHWddc1SetSpeed; 1980} 1981 1982SaveScreenProcPtr 1983vgaHWSaveScreenWeak(void) 1984{ 1985 return vgaHWSaveScreen; 1986} 1987 1988/* 1989 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ... 1990 */ 1991void 1992xf86GetClocks(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} 2076