vgaHW.c revision 9b06bd19
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 Bool flipPixels = xf86GetFlipPixels(); 1318 1319 for (i = 0; i < 16; i++) 1320 if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) 1321 regp->Attribute[i] = WHITE_VALUE; 1322 else 1323 regp->Attribute[i] = BLACK_VALUE; 1324 1325 regp->Attribute[16] = 0x01; /* -VGA2- *//* wrong for the ET4000 */ 1326 if (!hwp->ShowOverscan) 1327 regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */ 1328 } 1329 else { 1330 regp->Attribute[0] = 0x00; /* standard colormap translation */ 1331 regp->Attribute[1] = 0x01; 1332 regp->Attribute[2] = 0x02; 1333 regp->Attribute[3] = 0x03; 1334 regp->Attribute[4] = 0x04; 1335 regp->Attribute[5] = 0x05; 1336 regp->Attribute[6] = 0x06; 1337 regp->Attribute[7] = 0x07; 1338 regp->Attribute[8] = 0x08; 1339 regp->Attribute[9] = 0x09; 1340 regp->Attribute[10] = 0x0A; 1341 regp->Attribute[11] = 0x0B; 1342 regp->Attribute[12] = 0x0C; 1343 regp->Attribute[13] = 0x0D; 1344 regp->Attribute[14] = 0x0E; 1345 regp->Attribute[15] = 0x0F; 1346 if (depth == 4) 1347 regp->Attribute[16] = 0x81; /* wrong for the ET4000 */ 1348 else 1349 regp->Attribute[16] = 0x41; /* wrong for the ET4000 */ 1350 /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */ 1351 } 1352 regp->Attribute[18] = 0x0F; 1353 regp->Attribute[19] = 0x00; 1354 regp->Attribute[20] = 0x00; 1355 1356 return TRUE; 1357} 1358 1359 /* 1360 * OK, so much for theory. Now, let's deal with the >real< world... 1361 * 1362 * The above CRTC settings are precise in theory, except that many, if not 1363 * most, VGA clones fail to reset the blanking signal when the character or 1364 * line counter reaches [HV]Total. In this case, the signal is only 1365 * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as 1366 * the case may be) at the start of the >next< scanline or frame, which 1367 * means only part of the screen shows. This affects how null overscans 1368 * are to be implemented on such adapters. 1369 * 1370 * Henceforth, VGA cores that implement this broken, but unfortunately 1371 * common, behaviour are to be designated as KGA's, in honour of Koen 1372 * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion 1373 * a series of events that led to the discovery of this problem. 1374 * 1375 * Some VGA's are KGA's only in the horizontal, or only in the vertical, 1376 * some in both, others in neither. Don't let anyone tell you there is 1377 * such a thing as a VGA "standard"... And, thank the Creator for the fact 1378 * that Hilbert spaces are not yet implemented in this industry. 1379 * 1380 * The following implements a trick suggested by David Dawes. This sets 1381 * [HV]BlankEnd to zero if the blanking interval does not already contain a 1382 * 0-point, and decrements it by one otherwise. In the latter case, this 1383 * will produce a left and/or top overscan which the colourmap code will 1384 * (still) need to ensure is as close to black as possible. This will make 1385 * the behaviour consistent across all chipsets, while allowing all 1386 * chipsets to display the entire screen. Non-KGA drivers can ignore the 1387 * following in their own copy of this code. 1388 * 1389 * -- TSI @ UQV, 1998.08.21 1390 */ 1391 1392CARD32 1393vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, 1394 unsigned int Flags) 1395{ 1396 int nExtBits = (nBits < 6) ? 0 : nBits - 6; 1397 CARD32 ExtBits; 1398 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; 1399 1400 regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) 1401 | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); 1402 regp->CRTC[5] = (regp->CRTC[5] & ~0x80) 1403 | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); 1404 ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask; 1405 1406 /* First the horizontal case */ 1407 if ((Flags & KGA_FIX_OVERSCAN) 1408 && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) { 1409 int i = (regp->CRTC[3] & 0x1F) 1410 | ((regp->CRTC[5] & 0x80) >> 2) 1411 | ExtBits; 1412 1413 if (Flags & KGA_ENABLE_ON_ZERO) { 1414 if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1) 1415 & (0x3F | ExtBitMask))) 1416 && (mode->CrtcHBlankEnd == mode->CrtcHTotal)) 1417 i = 0; 1418 } 1419 else if (Flags & KGA_BE_TOT_DEC) 1420 i--; 1421 regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F); 1422 regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80); 1423 ExtBits = i & ExtBitMask; 1424 } 1425 return ExtBits >> 6; 1426} 1427 1428 /* 1429 * The vertical case is a little trickier. Some VGA's ignore bit 0x80 of 1430 * CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the 1431 * very first scanline in a double- or multi-scanned mode. This last case 1432 * needs further investigation. 1433 */ 1434CARD32 1435vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, 1436 unsigned int Flags) 1437{ 1438 CARD32 ExtBits; 1439 CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); 1440 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; 1441 1442 /* If width is not known nBits should be 0. In this 1443 * case BitMask is set to 0 so we can check for it. */ 1444 CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); 1445 int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; 1446 1447 regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1448 ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; 1449 1450 if ((Flags & KGA_FIX_OVERSCAN) 1451 && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) 1452 /* Null top overscan */ 1453 { 1454 int i = regp->CRTC[22] | ExtBits; 1455 1456 if (Flags & KGA_ENABLE_ON_ZERO) { 1457 if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) 1458 || ((i > VBlankStart) && /* 8-bit case */ 1459 ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ 1460 !(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */ 1461 i = 0; 1462 else 1463 i = (i - 1); 1464 } 1465 else if (Flags & KGA_BE_TOT_DEC) 1466 i = (i - 1); 1467 1468 regp->CRTC[22] = i & 0xFF; 1469 ExtBits = i & 0xFF00; 1470 } 1471 return ExtBits >> 8; 1472} 1473 1474/* 1475 * these are some more hardware specific helpers, formerly in vga.c 1476 */ 1477static void 1478vgaHWGetHWRecPrivate(void) 1479{ 1480 if (vgaHWPrivateIndex < 0) 1481 vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); 1482 return; 1483} 1484 1485static void 1486vgaHWFreeRegs(vgaRegPtr regp) 1487{ 1488 free(regp->CRTC); 1489 1490 regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL; 1491 1492 regp->numCRTC = 1493 regp->numSequencer = regp->numGraphics = regp->numAttribute = 0; 1494} 1495 1496static Bool 1497vgaHWAllocRegs(vgaRegPtr regp) 1498{ 1499 unsigned char *buf; 1500 1501 if ((regp->numCRTC + regp->numSequencer + regp->numGraphics + 1502 regp->numAttribute) == 0) 1503 return FALSE; 1504 1505 buf = calloc(regp->numCRTC + 1506 regp->numSequencer + 1507 regp->numGraphics + regp->numAttribute, 1); 1508 if (!buf) 1509 return FALSE; 1510 1511 regp->CRTC = buf; 1512 regp->Sequencer = regp->CRTC + regp->numCRTC; 1513 regp->Graphics = regp->Sequencer + regp->numSequencer; 1514 regp->Attribute = regp->Graphics + regp->numGraphics; 1515 1516 return TRUE; 1517} 1518 1519Bool 1520vgaHWAllocDefaultRegs(vgaRegPtr regp) 1521{ 1522 regp->numCRTC = VGA_NUM_CRTC; 1523 regp->numSequencer = VGA_NUM_SEQ; 1524 regp->numGraphics = VGA_NUM_GFX; 1525 regp->numAttribute = VGA_NUM_ATTR; 1526 1527 return vgaHWAllocRegs(regp); 1528} 1529 1530Bool 1531vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer, 1532 int numGraphics, int numAttribute) 1533{ 1534#define VGAHWMINNUM(regtype) \ 1535 ((newMode.num##regtype < regp->num##regtype) ? \ 1536 (newMode.num##regtype) : (regp->num##regtype)) 1537#define VGAHWCOPYREGSET(regtype) \ 1538 memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype)) 1539 1540 vgaRegRec newMode, newSaved; 1541 vgaRegPtr regp; 1542 1543 regp = &VGAHWPTR(scrp)->ModeReg; 1544 memcpy(&newMode, regp, sizeof(vgaRegRec)); 1545 1546 /* allocate space for new registers */ 1547 1548 regp = &newMode; 1549 regp->numCRTC = numCRTC; 1550 regp->numSequencer = numSequencer; 1551 regp->numGraphics = numGraphics; 1552 regp->numAttribute = numAttribute; 1553 if (!vgaHWAllocRegs(regp)) 1554 return FALSE; 1555 1556 regp = &VGAHWPTR(scrp)->SavedReg; 1557 memcpy(&newSaved, regp, sizeof(vgaRegRec)); 1558 1559 regp = &newSaved; 1560 regp->numCRTC = numCRTC; 1561 regp->numSequencer = numSequencer; 1562 regp->numGraphics = numGraphics; 1563 regp->numAttribute = numAttribute; 1564 if (!vgaHWAllocRegs(regp)) { 1565 vgaHWFreeRegs(&newMode); 1566 return FALSE; 1567 } 1568 1569 /* allocations succeeded, copy register data into new space */ 1570 1571 regp = &VGAHWPTR(scrp)->ModeReg; 1572 VGAHWCOPYREGSET(CRTC); 1573 VGAHWCOPYREGSET(Sequencer); 1574 VGAHWCOPYREGSET(Graphics); 1575 VGAHWCOPYREGSET(Attribute); 1576 1577 regp = &VGAHWPTR(scrp)->SavedReg; 1578 VGAHWCOPYREGSET(CRTC); 1579 VGAHWCOPYREGSET(Sequencer); 1580 VGAHWCOPYREGSET(Graphics); 1581 VGAHWCOPYREGSET(Attribute); 1582 1583 /* free old register arrays */ 1584 1585 regp = &VGAHWPTR(scrp)->ModeReg; 1586 vgaHWFreeRegs(regp); 1587 memcpy(regp, &newMode, sizeof(vgaRegRec)); 1588 1589 regp = &VGAHWPTR(scrp)->SavedReg; 1590 vgaHWFreeRegs(regp); 1591 memcpy(regp, &newSaved, sizeof(vgaRegRec)); 1592 1593 return TRUE; 1594 1595#undef VGAHWMINNUM 1596#undef VGAHWCOPYREGSET 1597} 1598 1599Bool 1600vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src) 1601{ 1602 vgaHWFreeRegs(dst); 1603 1604 memcpy(dst, src, sizeof(vgaRegRec)); 1605 1606 if (!vgaHWAllocRegs(dst)) 1607 return FALSE; 1608 1609 memcpy(dst->CRTC, src->CRTC, src->numCRTC); 1610 memcpy(dst->Sequencer, src->Sequencer, src->numSequencer); 1611 memcpy(dst->Graphics, src->Graphics, src->numGraphics); 1612 memcpy(dst->Attribute, src->Attribute, src->numAttribute); 1613 1614 return TRUE; 1615} 1616 1617Bool 1618vgaHWGetHWRec(ScrnInfoPtr scrp) 1619{ 1620 vgaRegPtr regp; 1621 vgaHWPtr hwp; 1622 int i; 1623 1624 /* 1625 * Let's make sure that the private exists and allocate one. 1626 */ 1627 vgaHWGetHWRecPrivate(); 1628 /* 1629 * New privates are always set to NULL, so we can check if the allocation 1630 * has already been done. 1631 */ 1632 if (VGAHWPTR(scrp)) 1633 return TRUE; 1634 hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1); 1635 regp = &VGAHWPTR(scrp)->ModeReg; 1636 1637 if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) || 1638 (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) { 1639 free(hwp); 1640 return FALSE; 1641 } 1642 1643 if (scrp->bitsPerPixel == 1) { 1644 rgb blackColour = scrp->display->blackColour, 1645 whiteColour = scrp->display->whiteColour; 1646 1647 if (blackColour.red > 0x3F) 1648 blackColour.red = 0x3F; 1649 if (blackColour.green > 0x3F) 1650 blackColour.green = 0x3F; 1651 if (blackColour.blue > 0x3F) 1652 blackColour.blue = 0x3F; 1653 1654 if (whiteColour.red > 0x3F) 1655 whiteColour.red = 0x3F; 1656 if (whiteColour.green > 0x3F) 1657 whiteColour.green = 0x3F; 1658 if (whiteColour.blue > 0x3F) 1659 whiteColour.blue = 0x3F; 1660 1661 if ((blackColour.red == whiteColour.red) && 1662 (blackColour.green == whiteColour.green) && 1663 (blackColour.blue == whiteColour.blue)) { 1664 blackColour.red ^= 0x3F; 1665 blackColour.green ^= 0x3F; 1666 blackColour.blue ^= 0x3F; 1667 } 1668 1669 /* 1670 * initialize default colormap for monochrome 1671 */ 1672 for (i = 0; i < 3; i++) 1673 regp->DAC[i] = 0x00; 1674 for (i = 3; i < 768; i++) 1675 regp->DAC[i] = 0x3F; 1676 i = BLACK_VALUE * 3; 1677 regp->DAC[i++] = blackColour.red; 1678 regp->DAC[i++] = blackColour.green; 1679 regp->DAC[i] = blackColour.blue; 1680 i = WHITE_VALUE * 3; 1681 regp->DAC[i++] = whiteColour.red; 1682 regp->DAC[i++] = whiteColour.green; 1683 regp->DAC[i] = whiteColour.blue; 1684 i = OVERSCAN_VALUE * 3; 1685 regp->DAC[i++] = 0x00; 1686 regp->DAC[i++] = 0x00; 1687 regp->DAC[i] = 0x00; 1688 } 1689 else { 1690 /* Set all colours to black */ 1691 for (i = 0; i < 768; i++) 1692 regp->DAC[i] = 0x00; 1693 /* ... and the overscan */ 1694 if (scrp->depth >= 4) 1695 regp->Attribute[OVERSCAN] = 0xFF; 1696 } 1697 if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) { 1698 xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan"); 1699 xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n"); 1700 regp->DAC[765] = 0x3F; 1701 regp->DAC[766] = 0x00; 1702 regp->DAC[767] = 0x3F; 1703 regp->Attribute[OVERSCAN] = 0xFF; 1704 hwp->ShowOverscan = TRUE; 1705 } 1706 else 1707 hwp->ShowOverscan = FALSE; 1708 1709 hwp->paletteEnabled = FALSE; 1710 hwp->cmapSaved = FALSE; 1711 hwp->MapSize = 0; 1712 hwp->pScrn = scrp; 1713 1714 hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]); 1715 1716 return TRUE; 1717} 1718 1719void 1720vgaHWFreeHWRec(ScrnInfoPtr scrp) 1721{ 1722 if (vgaHWPrivateIndex >= 0) { 1723 vgaHWPtr hwp = VGAHWPTR(scrp); 1724 1725 if (!hwp) 1726 return; 1727 1728 pci_device_close_io(hwp->dev, hwp->io); 1729 1730 free(hwp->FontInfo1); 1731 free(hwp->FontInfo2); 1732 free(hwp->TextInfo); 1733 1734 vgaHWFreeRegs(&hwp->ModeReg); 1735 vgaHWFreeRegs(&hwp->SavedReg); 1736 1737 free(hwp); 1738 VGAHWPTRLVAL(scrp) = NULL; 1739 } 1740} 1741 1742Bool 1743vgaHWMapMem(ScrnInfoPtr scrp) 1744{ 1745 vgaHWPtr hwp = VGAHWPTR(scrp); 1746 1747 if (hwp->Base) 1748 return TRUE; 1749 1750 /* If not set, initialise with the defaults */ 1751 if (hwp->MapSize == 0) 1752 hwp->MapSize = VGA_DEFAULT_MEM_SIZE; 1753 if (hwp->MapPhys == 0) 1754 hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR; 1755 1756 /* 1757 * Map as VIDMEM_MMIO_32BIT because WC 1758 * is bad when there is page flipping. 1759 * XXX This is not correct but we do it 1760 * for now. 1761 */ 1762 DebugF("Mapping VGAMem\n"); 1763 pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize, 1764 PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base); 1765 return hwp->Base != NULL; 1766} 1767 1768void 1769vgaHWUnmapMem(ScrnInfoPtr scrp) 1770{ 1771 vgaHWPtr hwp = VGAHWPTR(scrp); 1772 1773 if (hwp->Base == NULL) 1774 return; 1775 1776 DebugF("Unmapping VGAMem\n"); 1777 pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize); 1778 hwp->Base = NULL; 1779} 1780 1781int 1782vgaHWGetIndex(void) 1783{ 1784 return vgaHWPrivateIndex; 1785} 1786 1787void 1788vgaHWGetIOBase(vgaHWPtr hwp) 1789{ 1790 hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ? 1791 VGA_IOBASE_COLOR : VGA_IOBASE_MONO; 1792 xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3, 1793 "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase); 1794} 1795 1796void 1797vgaHWLock(vgaHWPtr hwp) 1798{ 1799 /* Protect CRTC[0-7] */ 1800 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80); 1801} 1802 1803void 1804vgaHWUnlock(vgaHWPtr hwp) 1805{ 1806 /* Unprotect CRTC[0-7] */ 1807 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80); 1808} 1809 1810void 1811vgaHWEnable(vgaHWPtr hwp) 1812{ 1813 hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01); 1814} 1815 1816void 1817vgaHWDisable(vgaHWPtr hwp) 1818{ 1819 hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01); 1820} 1821 1822static void 1823vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, 1824 VisualPtr pVisual) 1825{ 1826 vgaHWPtr hwp = VGAHWPTR(pScrn); 1827 int i, index; 1828 1829 for (i = 0; i < numColors; i++) { 1830 index = indices[i]; 1831 hwp->writeDacWriteAddr(hwp, index); 1832 DACDelay(hwp); 1833 hwp->writeDacData(hwp, colors[index].red); 1834 DACDelay(hwp); 1835 hwp->writeDacData(hwp, colors[index].green); 1836 DACDelay(hwp); 1837 hwp->writeDacData(hwp, colors[index].blue); 1838 DACDelay(hwp); 1839 } 1840 1841 /* This shouldn't be necessary, but we'll play safe. */ 1842 hwp->disablePalette(hwp); 1843} 1844 1845static void 1846vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan) 1847{ 1848 vgaHWPtr hwp = VGAHWPTR(pScrn); 1849 1850 if (overscan < 0 || overscan > 255) 1851 return; 1852 1853 hwp->enablePalette(hwp); 1854 hwp->writeAttr(hwp, OVERSCAN, overscan); 1855 1856#ifdef DEBUGOVERSCAN 1857 { 1858 int ov = hwp->readAttr(hwp, OVERSCAN); 1859 int red, green, blue; 1860 1861 hwp->writeDacReadAddr(hwp, ov); 1862 red = hwp->readDacData(hwp); 1863 green = hwp->readDacData(hwp); 1864 blue = hwp->readDacData(hwp); 1865 ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n", 1866 ov, red, green, blue); 1867 } 1868#endif 1869 1870 hwp->disablePalette(hwp); 1871} 1872 1873Bool 1874vgaHWHandleColormaps(ScreenPtr pScreen) 1875{ 1876 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1877 1878 if (pScrn->depth > 1 && pScrn->depth <= 8) { 1879 return xf86HandleColormaps(pScreen, 1 << pScrn->depth, 1880 pScrn->rgbBits, vgaHWLoadPalette, 1881 pScrn->depth > 4 ? vgaHWSetOverscan : NULL, 1882 CMAP_RELOAD_ON_MODE_SWITCH); 1883 } 1884 return TRUE; 1885} 1886 1887/* ----------------------- DDC support ------------------------*/ 1888/* 1889 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total 1890 * to read out EDID at a faster rate. Allowed maximum is 25kHz with 1891 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen 1892 * readback, enable access to cr00-cr07. 1893 */ 1894 1895/* vertical timings */ 1896#define DISPLAY_END 0x04 1897#define BLANK_START DISPLAY_END 1898#define SYNC_START BLANK_START 1899#define SYNC_END 0x09 1900#define BLANK_END SYNC_END 1901#define V_TOTAL BLANK_END 1902/* this function doesn't have to be reentrant for our purposes */ 1903struct _vgaDdcSave { 1904 unsigned char cr03; 1905 unsigned char cr06; 1906 unsigned char cr07; 1907 unsigned char cr09; 1908 unsigned char cr10; 1909 unsigned char cr11; 1910 unsigned char cr12; 1911 unsigned char cr15; 1912 unsigned char cr16; 1913 unsigned char msr; 1914}; 1915 1916void 1917vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) 1918{ 1919 vgaHWPtr hwp = VGAHWPTR(pScrn); 1920 unsigned char tmp; 1921 struct _vgaDdcSave *save; 1922 1923 switch (speed) { 1924 case DDC_FAST: 1925 1926 if (hwp->ddc != NULL) 1927 break; 1928 hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1); 1929 save = (struct _vgaDdcSave *) hwp->ddc; 1930 /* Lightpen register disable - allow access to cr10 & 11; just in case */ 1931 save->cr03 = hwp->readCrtc(hwp, 0x03); 1932 hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80)); 1933 save->cr12 = hwp->readCrtc(hwp, 0x12); 1934 hwp->writeCrtc(hwp, 0x12, DISPLAY_END); 1935 save->cr15 = hwp->readCrtc(hwp, 0x15); 1936 hwp->writeCrtc(hwp, 0x15, BLANK_START); 1937 save->cr10 = hwp->readCrtc(hwp, 0x10); 1938 hwp->writeCrtc(hwp, 0x10, SYNC_START); 1939 save->cr11 = hwp->readCrtc(hwp, 0x11); 1940 /* unprotect group 1 registers; just in case ... */ 1941 hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END)); 1942 save->cr16 = hwp->readCrtc(hwp, 0x16); 1943 hwp->writeCrtc(hwp, 0x16, BLANK_END); 1944 save->cr06 = hwp->readCrtc(hwp, 0x06); 1945 hwp->writeCrtc(hwp, 0x06, V_TOTAL); 1946 /* all values have less than 8 bit - mask out 9th and 10th bits */ 1947 save->cr09 = hwp->readCrtc(hwp, 0x09); 1948 hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF)); 1949 save->cr07 = hwp->readCrtc(hwp, 0x07); 1950 hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10)); 1951 /* vsync polarity negative & ensure a 25MHz clock */ 1952 save->msr = hwp->readMiscOut(hwp); 1953 hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80)); 1954 break; 1955 case DDC_SLOW: 1956 if (hwp->ddc == NULL) 1957 break; 1958 save = (struct _vgaDdcSave *) hwp->ddc; 1959 hwp->writeMiscOut(hwp, save->msr); 1960 hwp->writeCrtc(hwp, 0x07, save->cr07); 1961 tmp = hwp->readCrtc(hwp, 0x09); 1962 hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF))); 1963 hwp->writeCrtc(hwp, 0x06, save->cr06); 1964 hwp->writeCrtc(hwp, 0x16, save->cr16); 1965 hwp->writeCrtc(hwp, 0x11, save->cr11); 1966 hwp->writeCrtc(hwp, 0x10, save->cr10); 1967 hwp->writeCrtc(hwp, 0x15, save->cr15); 1968 hwp->writeCrtc(hwp, 0x12, save->cr12); 1969 hwp->writeCrtc(hwp, 0x03, save->cr03); 1970 free(save); 1971 hwp->ddc = NULL; 1972 break; 1973 default: 1974 break; 1975 } 1976} 1977 1978DDC1SetSpeedProc 1979vgaHWddc1SetSpeedWeak(void) 1980{ 1981 return vgaHWddc1SetSpeed; 1982} 1983 1984SaveScreenProcPtr 1985vgaHWSaveScreenWeak(void) 1986{ 1987 return vgaHWSaveScreen; 1988} 1989 1990/* 1991 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ... 1992 */ 1993void 1994xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int), 1995 void (*ProtectRegs) (ScrnInfoPtr, Bool), 1996 void (*BlankScreen) (ScrnInfoPtr, Bool), 1997 unsigned long vertsyncreg, int maskval, int knownclkindex, 1998 int knownclkvalue) 1999{ 2000 register int status = vertsyncreg; 2001 unsigned long i, cnt, rcnt, sync; 2002 vgaHWPtr hwp = VGAHWPTR(pScrn); 2003 2004 /* First save registers that get written on */ 2005 (*ClockFunc) (pScrn, CLK_REG_SAVE); 2006 2007 if (num > MAXCLOCKS) 2008 num = MAXCLOCKS; 2009 2010 for (i = 0; i < num; i++) { 2011 if (ProtectRegs) 2012 (*ProtectRegs) (pScrn, TRUE); 2013 if (!(*ClockFunc) (pScrn, i)) { 2014 pScrn->clock[i] = -1; 2015 continue; 2016 } 2017 if (ProtectRegs) 2018 (*ProtectRegs) (pScrn, FALSE); 2019 if (BlankScreen) 2020 (*BlankScreen) (pScrn, FALSE); 2021 2022 usleep(50000); /* let VCO stabilise */ 2023 2024 cnt = 0; 2025 sync = 200000; 2026 2027 while ((pci_io_read8(hwp->io, status) & maskval) == 0x00) 2028 if (sync-- == 0) 2029 goto finish; 2030 /* Something appears to be happening, so reset sync count */ 2031 sync = 200000; 2032 while ((pci_io_read8(hwp->io, status) & maskval) == maskval) 2033 if (sync-- == 0) 2034 goto finish; 2035 /* Something appears to be happening, so reset sync count */ 2036 sync = 200000; 2037 while ((pci_io_read8(hwp->io, status) & maskval) == 0x00) 2038 if (sync-- == 0) 2039 goto finish; 2040 2041 for (rcnt = 0; rcnt < 5; rcnt++) { 2042 while (!(pci_io_read8(hwp->io, status) & maskval)) 2043 cnt++; 2044 while ((pci_io_read8(hwp->io, status) & maskval)) 2045 cnt++; 2046 } 2047 2048 finish: 2049 pScrn->clock[i] = cnt ? cnt : -1; 2050 if (BlankScreen) 2051 (*BlankScreen) (pScrn, TRUE); 2052 } 2053 2054 for (i = 0; i < num; i++) { 2055 if (i != knownclkindex) { 2056 if (pScrn->clock[i] == -1) { 2057 pScrn->clock[i] = 0; 2058 } 2059 else { 2060 pScrn->clock[i] = (int) (0.5 + 2061 (((float) knownclkvalue) * 2062 pScrn->clock[knownclkindex]) / 2063 (pScrn->clock[i])); 2064 /* Round to nearest 10KHz */ 2065 pScrn->clock[i] += 5; 2066 pScrn->clock[i] /= 10; 2067 pScrn->clock[i] *= 10; 2068 } 2069 } 2070 } 2071 2072 pScrn->clock[knownclkindex] = knownclkvalue; 2073 pScrn->numClocks = num; 2074 2075 /* Restore registers that were written on */ 2076 (*ClockFunc) (pScrn, CLK_REG_RESTORE); 2077} 2078