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 79/* Use a private definition of this here */ 80#undef VGAHWPTR 81#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr 82#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p))) 83 84static int vgaHWPrivateIndex = -1; 85 86#define DAC_TEST_MASK 0x3F 87 88#ifdef NEED_SAVED_CMAP 89/* This default colourmap is used only when it can't be read from the VGA */ 90 91static CARD8 defaultDAC[768] = 92{ 93 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42, 94 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42, 95 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63, 96 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63, 97 0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11, 98 14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24, 99 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40, 100 45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63, 101 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63, 102 63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 103 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 104 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0, 105 0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 106 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 107 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63, 108 63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 109 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 110 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31, 111 31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 112 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 113 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63, 114 63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 115 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 116 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45, 117 45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 118 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 119 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28, 120 28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 121 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 122 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0, 123 0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 124 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 125 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28, 126 28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 127 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 128 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14, 129 14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 130 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 131 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28, 132 28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 133 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 134 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20, 135 20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 136 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 137 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16, 138 16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 139 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 140 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0, 141 0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 142 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 143 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16, 144 16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 145 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 146 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8, 147 8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 148 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 149 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16, 150 16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 151 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 152 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11, 153 11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 154 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}; 158#endif /* NEED_SAVED_CMAP */ 159 160/* 161 * Standard VGA versions of the register access functions. 162 */ 163static void 164stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) 165{ 166 outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); 167 outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET, value); 168} 169 170static CARD8 171stdReadCrtc(vgaHWPtr hwp, CARD8 index) 172{ 173 outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); 174 return inb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET); 175} 176 177static void 178stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) 179{ 180 outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); 181 outb(hwp->PIOOffset + VGA_GRAPH_DATA, value); 182} 183 184static CARD8 185stdReadGr(vgaHWPtr hwp, CARD8 index) 186{ 187 outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); 188 return inb(hwp->PIOOffset + VGA_GRAPH_DATA); 189} 190 191static void 192stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) 193{ 194 outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); 195 outb(hwp->PIOOffset + VGA_SEQ_DATA, value); 196} 197 198static CARD8 199stdReadSeq(vgaHWPtr hwp, CARD8 index) 200{ 201 outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); 202 return inb(hwp->PIOOffset + VGA_SEQ_DATA); 203} 204 205static CARD8 206stdReadST00(vgaHWPtr hwp) 207{ 208 return inb(hwp->PIOOffset + VGA_IN_STAT_0); 209} 210 211static CARD8 212stdReadST01(vgaHWPtr hwp) 213{ 214 return inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); 215} 216 217static CARD8 218stdReadFCR(vgaHWPtr hwp) 219{ 220 return inb(hwp->PIOOffset + VGA_FEATURE_R); 221} 222 223static void 224stdWriteFCR(vgaHWPtr hwp, CARD8 value) 225{ 226 outb(hwp->IOBase + hwp->PIOOffset + VGA_FEATURE_W_OFFSET,value); 227} 228 229static void 230stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) 231{ 232 if (hwp->paletteEnabled) 233 index &= ~0x20; 234 else 235 index |= 0x20; 236 237 (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); 238 outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); 239 outb(hwp->PIOOffset + VGA_ATTR_DATA_W, value); 240} 241 242static CARD8 243stdReadAttr(vgaHWPtr hwp, CARD8 index) 244{ 245 if (hwp->paletteEnabled) 246 index &= ~0x20; 247 else 248 index |= 0x20; 249 250 (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); 251 outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); 252 return inb(hwp->PIOOffset + VGA_ATTR_DATA_R); 253} 254 255static void 256stdWriteMiscOut(vgaHWPtr hwp, CARD8 value) 257{ 258 outb(hwp->PIOOffset + VGA_MISC_OUT_W, value); 259} 260 261static CARD8 262stdReadMiscOut(vgaHWPtr hwp) 263{ 264 return inb(hwp->PIOOffset + VGA_MISC_OUT_R); 265} 266 267static void 268stdEnablePalette(vgaHWPtr hwp) 269{ 270 (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); 271 outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x00); 272 hwp->paletteEnabled = TRUE; 273} 274 275static void 276stdDisablePalette(vgaHWPtr hwp) 277{ 278 (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); 279 outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x20); 280 hwp->paletteEnabled = FALSE; 281} 282 283static void 284stdWriteDacMask(vgaHWPtr hwp, CARD8 value) 285{ 286 outb(hwp->PIOOffset + VGA_DAC_MASK, value); 287} 288 289static CARD8 290stdReadDacMask(vgaHWPtr hwp) 291{ 292 return inb(hwp->PIOOffset + VGA_DAC_MASK); 293} 294 295static void 296stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) 297{ 298 outb(hwp->PIOOffset + VGA_DAC_READ_ADDR, value); 299} 300 301static void 302stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) 303{ 304 outb(hwp->PIOOffset + VGA_DAC_WRITE_ADDR, value); 305} 306 307static void 308stdWriteDacData(vgaHWPtr hwp, CARD8 value) 309{ 310 outb(hwp->PIOOffset + VGA_DAC_DATA, value); 311} 312 313static CARD8 314stdReadDacData(vgaHWPtr hwp) 315{ 316 return inb(hwp->PIOOffset + VGA_DAC_DATA); 317} 318 319static CARD8 320stdReadEnable(vgaHWPtr hwp) 321{ 322 return inb(hwp->PIOOffset + VGA_ENABLE); 323} 324 325static void 326stdWriteEnable(vgaHWPtr hwp, CARD8 value) 327{ 328 outb(hwp->PIOOffset + VGA_ENABLE, value); 329} 330 331void 332vgaHWSetStdFuncs(vgaHWPtr hwp) 333{ 334 hwp->writeCrtc = stdWriteCrtc; 335 hwp->readCrtc = stdReadCrtc; 336 hwp->writeGr = stdWriteGr; 337 hwp->readGr = stdReadGr; 338 hwp->readST00 = stdReadST00; 339 hwp->readST01 = stdReadST01; 340 hwp->readFCR = stdReadFCR; 341 hwp->writeFCR = stdWriteFCR; 342 hwp->writeAttr = stdWriteAttr; 343 hwp->readAttr = stdReadAttr; 344 hwp->writeSeq = stdWriteSeq; 345 hwp->readSeq = stdReadSeq; 346 hwp->writeMiscOut = stdWriteMiscOut; 347 hwp->readMiscOut = stdReadMiscOut; 348 hwp->enablePalette = stdEnablePalette; 349 hwp->disablePalette = stdDisablePalette; 350 hwp->writeDacMask = stdWriteDacMask; 351 hwp->readDacMask = stdReadDacMask; 352 hwp->writeDacWriteAddr = stdWriteDacWriteAddr; 353 hwp->writeDacReadAddr = stdWriteDacReadAddr; 354 hwp->writeDacData = stdWriteDacData; 355 hwp->readDacData = stdReadDacData; 356 hwp->PIOOffset = 0; 357 hwp->readEnable = stdReadEnable; 358 hwp->writeEnable = stdWriteEnable; 359} 360 361/* 362 * MMIO versions of the register access functions. These require 363 * hwp->MemBase to be set in such a way that when the standard VGA port 364 * adderss is added the correct memory address results. 365 */ 366 367#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p))) 368#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v)) 369 370static void 371mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) 372{ 373 moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); 374 moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value); 375} 376 377static CARD8 378mmioReadCrtc(vgaHWPtr hwp, CARD8 index) 379{ 380 moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); 381 return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET); 382} 383 384static void 385mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) 386{ 387 moutb(VGA_GRAPH_INDEX, index); 388 moutb(VGA_GRAPH_DATA, value); 389} 390 391static CARD8 392mmioReadGr(vgaHWPtr hwp, CARD8 index) 393{ 394 moutb(VGA_GRAPH_INDEX, index); 395 return minb(VGA_GRAPH_DATA); 396} 397 398static void 399mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) 400{ 401 moutb(VGA_SEQ_INDEX, index); 402 moutb(VGA_SEQ_DATA, value); 403} 404 405static CARD8 406mmioReadSeq(vgaHWPtr hwp, CARD8 index) 407{ 408 moutb(VGA_SEQ_INDEX, index); 409 return minb(VGA_SEQ_DATA); 410} 411 412static CARD8 413mmioReadST00(vgaHWPtr hwp) 414{ 415 return minb(VGA_IN_STAT_0); 416} 417 418static CARD8 419mmioReadST01(vgaHWPtr hwp) 420{ 421 return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 422} 423 424static CARD8 425mmioReadFCR(vgaHWPtr hwp) 426{ 427 return minb(VGA_FEATURE_R); 428} 429 430static void 431mmioWriteFCR(vgaHWPtr hwp, CARD8 value) 432{ 433 moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET,value); 434} 435 436static void 437mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) 438{ 439 if (hwp->paletteEnabled) 440 index &= ~0x20; 441 else 442 index |= 0x20; 443 444 (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 445 moutb(VGA_ATTR_INDEX, index); 446 moutb(VGA_ATTR_DATA_W, value); 447} 448 449static CARD8 450mmioReadAttr(vgaHWPtr hwp, CARD8 index) 451{ 452 if (hwp->paletteEnabled) 453 index &= ~0x20; 454 else 455 index |= 0x20; 456 457 (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 458 moutb(VGA_ATTR_INDEX, index); 459 return minb(VGA_ATTR_DATA_R); 460} 461 462static void 463mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value) 464{ 465 moutb(VGA_MISC_OUT_W, value); 466} 467 468static CARD8 469mmioReadMiscOut(vgaHWPtr hwp) 470{ 471 return minb(VGA_MISC_OUT_R); 472} 473 474static void 475mmioEnablePalette(vgaHWPtr hwp) 476{ 477 (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 478 moutb(VGA_ATTR_INDEX, 0x00); 479 hwp->paletteEnabled = TRUE; 480} 481 482static void 483mmioDisablePalette(vgaHWPtr hwp) 484{ 485 (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); 486 moutb(VGA_ATTR_INDEX, 0x20); 487 hwp->paletteEnabled = FALSE; 488} 489 490static void 491mmioWriteDacMask(vgaHWPtr hwp, CARD8 value) 492{ 493 moutb(VGA_DAC_MASK, value); 494} 495 496static CARD8 497mmioReadDacMask(vgaHWPtr hwp) 498{ 499 return minb(VGA_DAC_MASK); 500} 501 502static void 503mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) 504{ 505 moutb(VGA_DAC_READ_ADDR, value); 506} 507 508static void 509mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) 510{ 511 moutb(VGA_DAC_WRITE_ADDR, value); 512} 513 514static void 515mmioWriteDacData(vgaHWPtr hwp, CARD8 value) 516{ 517 moutb(VGA_DAC_DATA, value); 518} 519 520static CARD8 521mmioReadDacData(vgaHWPtr hwp) 522{ 523 return minb(VGA_DAC_DATA); 524} 525 526static CARD8 527mmioReadEnable(vgaHWPtr hwp) 528{ 529 return minb(VGA_ENABLE); 530} 531 532static void 533mmioWriteEnable(vgaHWPtr hwp, CARD8 value) 534{ 535 moutb(VGA_ENABLE, value); 536} 537 538void 539vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset) 540{ 541 hwp->writeCrtc = mmioWriteCrtc; 542 hwp->readCrtc = mmioReadCrtc; 543 hwp->writeGr = mmioWriteGr; 544 hwp->readGr = mmioReadGr; 545 hwp->readST00 = mmioReadST00; 546 hwp->readST01 = mmioReadST01; 547 hwp->readFCR = mmioReadFCR; 548 hwp->writeFCR = mmioWriteFCR; 549 hwp->writeAttr = mmioWriteAttr; 550 hwp->readAttr = mmioReadAttr; 551 hwp->writeSeq = mmioWriteSeq; 552 hwp->readSeq = mmioReadSeq; 553 hwp->writeMiscOut = mmioWriteMiscOut; 554 hwp->readMiscOut = mmioReadMiscOut; 555 hwp->enablePalette = mmioEnablePalette; 556 hwp->disablePalette = mmioDisablePalette; 557 hwp->writeDacMask = mmioWriteDacMask; 558 hwp->readDacMask = mmioReadDacMask; 559 hwp->writeDacWriteAddr = mmioWriteDacWriteAddr; 560 hwp->writeDacReadAddr = mmioWriteDacReadAddr; 561 hwp->writeDacData = mmioWriteDacData; 562 hwp->readDacData = mmioReadDacData; 563 hwp->MMIOBase = base; 564 hwp->MMIOOffset = offset; 565 hwp->readEnable = mmioReadEnable; 566 hwp->writeEnable = mmioWriteEnable; 567} 568 569/* 570 * vgaHWProtect -- 571 * Protect VGA registers and memory from corruption during loads. 572 */ 573 574void 575vgaHWProtect(ScrnInfoPtr pScrn, Bool on) 576{ 577 vgaHWPtr hwp = VGAHWPTR(pScrn); 578 579 unsigned char tmp; 580 581 if (pScrn->vtSema) { 582 if (on) { 583 /* 584 * Turn off screen and disable sequencer. 585 */ 586 tmp = hwp->readSeq(hwp, 0x01); 587 588 vgaHWSeqReset(hwp, TRUE); /* start synchronous reset */ 589 hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */ 590 591 hwp->enablePalette(hwp); 592 } else { 593 /* 594 * Reenable sequencer, then turn on screen. 595 */ 596 597 tmp = hwp->readSeq(hwp, 0x01); 598 599 hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */ 600 vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */ 601 602 hwp->disablePalette(hwp); 603 } 604 } 605} 606 607vgaHWProtectProc *vgaHWProtectWeak(void) { 608 return vgaHWProtect; 609} 610 611/* 612 * vgaHWBlankScreen -- blank the screen. 613 */ 614 615void 616vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on) 617{ 618 vgaHWPtr hwp = VGAHWPTR(pScrn); 619 unsigned char scrn; 620 621 scrn = hwp->readSeq(hwp, 0x01); 622 623 if (on) { 624 scrn &= ~0x20; /* enable screen */ 625 } else { 626 scrn |= 0x20; /* blank screen */ 627 } 628 629 vgaHWSeqReset(hwp, TRUE); 630 hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ 631 vgaHWSeqReset(hwp, FALSE); 632} 633 634vgaHWBlankScreenProc *vgaHWBlankScreenWeak(void) { 635 return vgaHWBlankScreen; 636} 637 638/* 639 * vgaHWSaveScreen -- blank the screen. 640 */ 641 642Bool 643vgaHWSaveScreen(ScreenPtr pScreen, int mode) 644{ 645 ScrnInfoPtr pScrn = NULL; 646 Bool on; 647 648 if (pScreen != NULL) 649 pScrn = xf86Screens[pScreen->myNum]; 650 651 on = xf86IsUnblank(mode); 652 653#if 0 654 if (on) 655 SetTimeSinceLastInputEvent(); 656#endif 657 658 if ((pScrn != NULL) && pScrn->vtSema) { 659 vgaHWBlankScreen(pScrn, on); 660 } 661 return TRUE; 662} 663 664 665/* 666 * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode 667 * 668 * This generic VGA function can only set the Off and On modes. If the 669 * Standby and Suspend modes are to be supported, a chip specific replacement 670 * for this function must be written. 671 */ 672 673void 674vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 675{ 676 unsigned char seq1 = 0, crtc17 = 0; 677 vgaHWPtr hwp = VGAHWPTR(pScrn); 678 679 if (!pScrn->vtSema) return; 680 681 switch (PowerManagementMode) { 682 case DPMSModeOn: 683 /* Screen: On; HSync: On, VSync: On */ 684 seq1 = 0x00; 685 crtc17 = 0x80; 686 break; 687 case DPMSModeStandby: 688 /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ 689 seq1 = 0x20; 690 crtc17 = 0x80; 691 break; 692 case DPMSModeSuspend: 693 /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ 694 seq1 = 0x20; 695 crtc17 = 0x80; 696 break; 697 case DPMSModeOff: 698 /* Screen: Off; HSync: Off, VSync: Off */ 699 seq1 = 0x20; 700 crtc17 = 0x00; 701 break; 702 } 703 hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ 704 seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20; 705 hwp->writeSeq(hwp, 0x01, seq1); 706 crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80; 707 usleep(10000); 708 hwp->writeCrtc(hwp, 0x17, crtc17); 709 hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ 710} 711 712 713/* 714 * vgaHWSeqReset 715 * perform a sequencer reset. 716 */ 717 718void 719vgaHWSeqReset(vgaHWPtr hwp, Bool start) 720{ 721 if (start) 722 hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ 723 else 724 hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ 725} 726 727 728void 729vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) 730{ 731#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 732 vgaHWPtr hwp = VGAHWPTR(scrninfp); 733 int savedIOBase; 734 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4; 735 Bool doMap = FALSE; 736 737 /* If nothing to do, return now */ 738 if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo) 739 return; 740 741 if (hwp->Base == NULL) { 742 doMap = TRUE; 743 if (!vgaHWMapMem(scrninfp)) { 744 xf86DrvMsg(scrninfp->scrnIndex, X_ERROR, 745 "vgaHWRestoreFonts: vgaHWMapMem() failed\n"); 746 return; 747 } 748 } 749 750 /* save the registers that are needed here */ 751 miscOut = hwp->readMiscOut(hwp); 752 attr10 = hwp->readAttr(hwp, 0x10); 753 gr1 = hwp->readGr(hwp, 0x01); 754 gr3 = hwp->readGr(hwp, 0x03); 755 gr4 = hwp->readGr(hwp, 0x04); 756 gr5 = hwp->readGr(hwp, 0x05); 757 gr6 = hwp->readGr(hwp, 0x06); 758 gr8 = hwp->readGr(hwp, 0x08); 759 seq2 = hwp->readSeq(hwp, 0x02); 760 seq4 = hwp->readSeq(hwp, 0x04); 761 762 /* save hwp->IOBase and temporarily set it for colour mode */ 763 savedIOBase = hwp->IOBase; 764 hwp->IOBase = VGA_IOBASE_COLOR; 765 766 /* Force into colour mode */ 767 hwp->writeMiscOut(hwp, miscOut | 0x01); 768 769 vgaHWBlankScreen(scrninfp, FALSE); 770 771 /* 772 * here we temporarily switch to 16 colour planar mode, to simply 773 * copy the font-info and saved text. 774 * 775 * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly! 776 */ 777#if 0 778 hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ 779#endif 780 781 hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ 782 hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ 783 hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ 784 785 if (scrninfp->depth == 4) { 786 /* GJA */ 787 hwp->writeGr(hwp, 0x03, 0x00); /* don't rotate, write unmodified */ 788 hwp->writeGr(hwp, 0x08, 0xFF); /* write all bits in a byte */ 789 hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */ 790 } 791 792#if SAVE_FONT1 793 if (hwp->FontInfo1) { 794 hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ 795 hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ 796 slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT); 797 } 798#endif 799 800#if SAVE_FONT2 801 if (hwp->FontInfo2) { 802 hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ 803 hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ 804 slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT); 805 } 806#endif 807 808#if SAVE_TEXT 809 if (hwp->TextInfo) { 810 hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ 811 hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ 812 slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT); 813 hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ 814 hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ 815 slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT, 816 hwp->Base, TEXT_AMOUNT); 817 } 818#endif 819 820 vgaHWBlankScreen(scrninfp, TRUE); 821 822 /* restore the registers that were changed */ 823 hwp->writeMiscOut(hwp, miscOut); 824 hwp->writeAttr(hwp, 0x10, attr10); 825 hwp->writeGr(hwp, 0x01, gr1); 826 hwp->writeGr(hwp, 0x03, gr3); 827 hwp->writeGr(hwp, 0x04, gr4); 828 hwp->writeGr(hwp, 0x05, gr5); 829 hwp->writeGr(hwp, 0x06, gr6); 830 hwp->writeGr(hwp, 0x08, gr8); 831 hwp->writeSeq(hwp, 0x02, seq2); 832 hwp->writeSeq(hwp, 0x04, seq4); 833 hwp->IOBase = savedIOBase; 834 835 if (doMap) 836 vgaHWUnmapMem(scrninfp); 837 838#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ 839} 840 841 842void 843vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore) 844{ 845 vgaHWPtr hwp = VGAHWPTR(scrninfp); 846 int i; 847 848 if (restore->MiscOutReg & 0x01) 849 hwp->IOBase = VGA_IOBASE_COLOR; 850 else 851 hwp->IOBase = VGA_IOBASE_MONO; 852 853 hwp->writeMiscOut(hwp, restore->MiscOutReg); 854 855 for (i = 1; i < restore->numSequencer; i++) 856 hwp->writeSeq(hwp, i, restore->Sequencer[i]); 857 858 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ 859 hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80); 860 861 for (i = 0; i < restore->numCRTC; i++) 862 hwp->writeCrtc(hwp, i, restore->CRTC[i]); 863 864 for (i = 0; i < restore->numGraphics; i++) 865 hwp->writeGr(hwp, i, restore->Graphics[i]); 866 867 hwp->enablePalette(hwp); 868 for (i = 0; i < restore->numAttribute; i++) 869 hwp->writeAttr(hwp, i, restore->Attribute[i]); 870 hwp->disablePalette(hwp); 871} 872 873 874void 875vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore) 876{ 877 vgaHWPtr hwp = VGAHWPTR(scrninfp); 878 int i; 879 880#if 0 881 hwp->enablePalette(hwp); 882#endif 883 884 hwp->writeDacMask(hwp, 0xFF); 885 hwp->writeDacWriteAddr(hwp, 0x00); 886 for (i = 0; i < 768; i++) { 887 hwp->writeDacData(hwp, restore->DAC[i]); 888 DACDelay(hwp); 889 } 890 891 hwp->disablePalette(hwp); 892} 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, TEXT_AMOUNT); 993 } 994#endif /* SAVE_TEXT */ 995 996 /* Restore clobbered registers */ 997 hwp->writeAttr(hwp, 0x10, attr10); 998 hwp->writeSeq(hwp, 0x02, seq2); 999 hwp->writeSeq(hwp, 0x04, seq4); 1000 hwp->writeGr(hwp, 0x04, gr4); 1001 hwp->writeGr(hwp, 0x05, gr5); 1002 hwp->writeGr(hwp, 0x06, gr6); 1003 hwp->writeMiscOut(hwp, miscOut); 1004 hwp->IOBase = savedIOBase; 1005 1006 vgaHWBlankScreen(scrninfp, TRUE); 1007 1008 if (doMap) 1009 vgaHWUnmapMem(scrninfp); 1010 1011#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ 1012} 1013 1014void 1015vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save) 1016{ 1017 vgaHWPtr hwp = VGAHWPTR(scrninfp); 1018 int i; 1019 1020 save->MiscOutReg = hwp->readMiscOut(hwp); 1021 if (save->MiscOutReg & 0x01) 1022 hwp->IOBase = VGA_IOBASE_COLOR; 1023 else 1024 hwp->IOBase = VGA_IOBASE_MONO; 1025 1026 for (i = 0; i < save->numCRTC; i++) { 1027 save->CRTC[i] = hwp->readCrtc(hwp, i); 1028 DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]); 1029 } 1030 1031 hwp->enablePalette(hwp); 1032 for (i = 0; i < save->numAttribute; i++) { 1033 save->Attribute[i] = hwp->readAttr(hwp, i); 1034 DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]); 1035 } 1036 hwp->disablePalette(hwp); 1037 1038 for (i = 0; i < save->numGraphics; i++) { 1039 save->Graphics[i] = hwp->readGr(hwp, i); 1040 DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]); 1041 } 1042 1043 for (i = 1; i < save->numSequencer; i++) { 1044 save->Sequencer[i] = hwp->readSeq(hwp, i); 1045 DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]); 1046 } 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 } else { 1119 /* save the colourmap */ 1120 hwp->writeDacReadAddr(hwp, 0x02); 1121 for (i = 6; i < 768; i++) { 1122 save->DAC[i] = hwp->readDacData(hwp); 1123 DACDelay(hwp); 1124 switch (i % 3) { 1125 case 0: 1126 DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]); 1127 break; 1128 case 1: 1129 DebugF("0x%02x, ", save->DAC[i]); 1130 break; 1131 case 2: 1132 DebugF("0x%02x\n", save->DAC[i]); 1133 } 1134 } 1135 } 1136 1137 hwp->disablePalette(hwp); 1138 hwp->cmapSaved = TRUE; 1139#endif 1140} 1141 1142/* 1143 * vgaHWSave -- 1144 * save the current VGA state 1145 */ 1146 1147void 1148vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags) 1149{ 1150 if (save == NULL) 1151 return; 1152 1153 if (flags & VGA_SR_CMAP) 1154 vgaHWSaveColormap(scrninfp, save); 1155 1156 if (flags & VGA_SR_MODE) 1157 vgaHWSaveMode(scrninfp, save); 1158 1159 if (flags & VGA_SR_FONTS) 1160 vgaHWSaveFonts(scrninfp, save); 1161} 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 { 1192 regp->MiscOutReg = 0x23; 1193 if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40; 1194 if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80; 1195 } 1196 else 1197 { 1198 int VDisplay = mode->VDisplay; 1199 if (mode->Flags & V_DBLSCAN) 1200 VDisplay *= 2; 1201 if (mode->VScan > 1) 1202 VDisplay *= mode->VScan; 1203 if (VDisplay < 400) 1204 regp->MiscOutReg = 0xA3; /* +hsync -vsync */ 1205 else if (VDisplay < 480) 1206 regp->MiscOutReg = 0x63; /* -hsync +vsync */ 1207 else if (VDisplay < 768) 1208 regp->MiscOutReg = 0xE3; /* -hsync -vsync */ 1209 else 1210 regp->MiscOutReg = 0x23; /* +hsync +vsync */ 1211 } 1212 1213 regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2; 1214 1215 /* 1216 * Time Sequencer 1217 */ 1218 if (depth == 4) 1219 regp->Sequencer[0] = 0x02; 1220 else 1221 regp->Sequencer[0] = 0x00; 1222 if (mode->Flags & V_CLKDIV2) 1223 regp->Sequencer[1] = 0x09; 1224 else 1225 regp->Sequencer[1] = 0x01; 1226 if (depth == 1) 1227 regp->Sequencer[2] = 1 << BIT_PLANE; 1228 else 1229 regp->Sequencer[2] = 0x0F; 1230 regp->Sequencer[3] = 0x00; /* Font select */ 1231 if (depth < 8) 1232 regp->Sequencer[4] = 0x06; /* Misc */ 1233 else 1234 regp->Sequencer[4] = 0x0E; /* Misc */ 1235 1236 /* 1237 * CRTC Controller 1238 */ 1239 regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5; 1240 regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1; 1241 regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1; 1242 regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 1243 i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F); 1244 if (i < 0x80) 1245 regp->CRTC[3] |= i; 1246 regp->CRTC[4] = (mode->CrtcHSyncStart >> 3); 1247 regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 1248 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); 1249 regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF; 1250 regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8) 1251 | (((mode->CrtcVDisplay - 1) & 0x100) >> 7) 1252 | ((mode->CrtcVSyncStart & 0x100) >> 6) 1253 | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5) 1254 | 0x10 1255 | (((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 } else { 1303 regp->Graphics[4] = 0x00; 1304 if (depth == 4) 1305 regp->Graphics[5] = 0x02; 1306 else 1307 regp->Graphics[5] = 0x40; 1308 } 1309 regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ 1310 regp->Graphics[7] = 0x0F; 1311 regp->Graphics[8] = 0xFF; 1312 1313 if (depth == 1) { 1314 /* Initialise the Mono map according to which bit-plane gets used */ 1315 1316 Bool flipPixels = xf86GetFlipPixels(); 1317 1318 for (i=0; i<16; i++) 1319 if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) 1320 regp->Attribute[i] = WHITE_VALUE; 1321 else 1322 regp->Attribute[i] = BLACK_VALUE; 1323 1324 regp->Attribute[16] = 0x01; /* -VGA2- */ /* wrong for the ET4000 */ 1325 if (!hwp->ShowOverscan) 1326 regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */ 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 { 1408 int i = (regp->CRTC[3] & 0x1F) 1409 | ((regp->CRTC[5] & 0x80) >> 2) 1410 | ExtBits; 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 } else if (Flags & KGA_BE_TOT_DEC) 1417 i--; 1418 regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F); 1419 regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80); 1420 ExtBits = i & ExtBitMask; 1421 } 1422 return ExtBits >> 6; 1423} 1424 1425 /* 1426 * The vertical case is a little trickier. Some VGA's ignore bit 0x80 of 1427 * CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the 1428 * very first scanline in a double- or multi-scanned mode. This last case 1429 * needs further investigation. 1430 */ 1431CARD32 1432vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, 1433 unsigned int Flags) 1434{ 1435 CARD32 ExtBits; 1436 CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); 1437 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; 1438 /* If width is not known nBits should be 0. In this 1439 * case BitMask is set to 0 so we can check for it. */ 1440 CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); 1441 int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; 1442 regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1443 ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; 1444 1445 if ((Flags & KGA_FIX_OVERSCAN) 1446 && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) 1447 /* Null top overscan */ 1448 { 1449 int i = regp->CRTC[22] | ExtBits; 1450 if (Flags & KGA_ENABLE_ON_ZERO) { 1451 if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) 1452 || ((i > VBlankStart) && /* 8-bit case */ 1453 ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ 1454 !(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */ 1455 i = 0; 1456 else 1457 i = (i - 1); 1458 } else if (Flags & KGA_BE_TOT_DEC) 1459 i = (i - 1); 1460 1461 regp->CRTC[22] = i & 0xFF; 1462 ExtBits = i & 0xFF00; 1463 } 1464 return ExtBits >> 8; 1465} 1466 1467/* 1468 * these are some more hardware specific helpers, formerly in vga.c 1469 */ 1470static void 1471vgaHWGetHWRecPrivate(void) 1472{ 1473 if (vgaHWPrivateIndex < 0) 1474 vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); 1475 return; 1476} 1477 1478 1479static void 1480vgaHWFreeRegs(vgaRegPtr regp) 1481{ 1482 free(regp->CRTC); 1483 1484 regp->CRTC = 1485 regp->Sequencer = 1486 regp->Graphics = 1487 regp->Attribute = NULL; 1488 1489 regp->numCRTC = 1490 regp->numSequencer = 1491 regp->numGraphics = 1492 regp->numAttribute = 0; 1493} 1494 1495 1496 1497static Bool 1498vgaHWAllocRegs(vgaRegPtr regp) 1499{ 1500 unsigned char *buf; 1501 1502 if ((regp->numCRTC + regp->numSequencer + regp->numGraphics + 1503 regp->numAttribute) == 0) 1504 return FALSE; 1505 1506 buf = calloc(regp->numCRTC + 1507 regp->numSequencer + 1508 regp->numGraphics + 1509 regp->numAttribute, 1); 1510 if (!buf) 1511 return FALSE; 1512 1513 regp->CRTC = buf; 1514 regp->Sequencer = regp->CRTC + regp->numCRTC; 1515 regp->Graphics = regp->Sequencer + regp->numSequencer; 1516 regp->Attribute = regp->Graphics + regp->numGraphics; 1517 1518 return TRUE; 1519} 1520 1521 1522Bool 1523vgaHWAllocDefaultRegs(vgaRegPtr regp) 1524{ 1525 regp->numCRTC = VGA_NUM_CRTC; 1526 regp->numSequencer = VGA_NUM_SEQ; 1527 regp->numGraphics = VGA_NUM_GFX; 1528 regp->numAttribute = VGA_NUM_ATTR; 1529 1530 return vgaHWAllocRegs(regp); 1531} 1532 1533 1534Bool 1535vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer, 1536 int numGraphics, int numAttribute) 1537{ 1538#define VGAHWMINNUM(regtype) \ 1539 ((newMode.num##regtype < regp->num##regtype) ? \ 1540 (newMode.num##regtype) : (regp->num##regtype)) 1541#define VGAHWCOPYREGSET(regtype) \ 1542 memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype)) 1543 1544 vgaRegRec newMode, newSaved; 1545 vgaRegPtr regp; 1546 1547 regp = &VGAHWPTR(scrp)->ModeReg; 1548 memcpy (&newMode, regp, sizeof(vgaRegRec)); 1549 1550 /* allocate space for new registers */ 1551 1552 regp = &newMode; 1553 regp->numCRTC = numCRTC; 1554 regp->numSequencer = numSequencer; 1555 regp->numGraphics = numGraphics; 1556 regp->numAttribute = numAttribute; 1557 if (!vgaHWAllocRegs(regp)) 1558 return FALSE; 1559 1560 regp = &VGAHWPTR(scrp)->SavedReg; 1561 memcpy (&newSaved, regp, sizeof(vgaRegRec)); 1562 1563 regp = &newSaved; 1564 regp->numCRTC = numCRTC; 1565 regp->numSequencer = numSequencer; 1566 regp->numGraphics = numGraphics; 1567 regp->numAttribute = numAttribute; 1568 if (!vgaHWAllocRegs(regp)) { 1569 vgaHWFreeRegs(&newMode); 1570 return FALSE; 1571 } 1572 1573 /* allocations succeeded, copy register data into new space */ 1574 1575 regp = &VGAHWPTR(scrp)->ModeReg; 1576 VGAHWCOPYREGSET(CRTC); 1577 VGAHWCOPYREGSET(Sequencer); 1578 VGAHWCOPYREGSET(Graphics); 1579 VGAHWCOPYREGSET(Attribute); 1580 1581 regp = &VGAHWPTR(scrp)->SavedReg; 1582 VGAHWCOPYREGSET(CRTC); 1583 VGAHWCOPYREGSET(Sequencer); 1584 VGAHWCOPYREGSET(Graphics); 1585 VGAHWCOPYREGSET(Attribute); 1586 1587 /* free old register arrays */ 1588 1589 regp = &VGAHWPTR(scrp)->ModeReg; 1590 vgaHWFreeRegs(regp); 1591 memcpy(regp, &newMode, sizeof(vgaRegRec)); 1592 1593 regp = &VGAHWPTR(scrp)->SavedReg; 1594 vgaHWFreeRegs(regp); 1595 memcpy(regp, &newSaved, sizeof(vgaRegRec)); 1596 1597 return TRUE; 1598 1599#undef VGAHWMINNUM 1600#undef VGAHWCOPYREGSET 1601} 1602 1603 1604Bool 1605vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src) 1606{ 1607 vgaHWFreeRegs(dst); 1608 1609 memcpy(dst, src, sizeof(vgaRegRec)); 1610 1611 if (!vgaHWAllocRegs(dst)) 1612 return FALSE; 1613 1614 memcpy(dst->CRTC, src->CRTC, src->numCRTC); 1615 memcpy(dst->Sequencer, src->Sequencer, src->numSequencer); 1616 memcpy(dst->Graphics, src->Graphics, src->numGraphics); 1617 memcpy(dst->Attribute, src->Attribute, src->numAttribute); 1618 1619 return TRUE; 1620} 1621 1622 1623Bool 1624vgaHWGetHWRec(ScrnInfoPtr scrp) 1625{ 1626 vgaRegPtr regp; 1627 vgaHWPtr hwp; 1628 int i; 1629 1630 /* 1631 * Let's make sure that the private exists and allocate one. 1632 */ 1633 vgaHWGetHWRecPrivate(); 1634 /* 1635 * New privates are always set to NULL, so we can check if the allocation 1636 * has already been done. 1637 */ 1638 if (VGAHWPTR(scrp)) 1639 return TRUE; 1640 hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1); 1641 regp = &VGAHWPTR(scrp)->ModeReg; 1642 1643 if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) || 1644 (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) { 1645 free(hwp); 1646 return FALSE; 1647 } 1648 1649 if (scrp->bitsPerPixel == 1) { 1650 rgb blackColour = scrp->display->blackColour, 1651 whiteColour = scrp->display->whiteColour; 1652 1653 if (blackColour.red > 0x3F) blackColour.red = 0x3F; 1654 if (blackColour.green > 0x3F) blackColour.green = 0x3F; 1655 if (blackColour.blue > 0x3F) blackColour.blue = 0x3F; 1656 1657 if (whiteColour.red > 0x3F) whiteColour.red = 0x3F; 1658 if (whiteColour.green > 0x3F) whiteColour.green = 0x3F; 1659 if (whiteColour.blue > 0x3F) 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++) regp->DAC[i] = 0x00; 1673 for (i=3; i<768; i++) 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 } else { 1687 /* Set all colours to black */ 1688 for (i=0; i<768; i++) regp->DAC[i] = 0x00; 1689 /* ... and the overscan */ 1690 if (scrp->depth >= 4) 1691 regp->Attribute[OVERSCAN] = 0xFF; 1692 } 1693 if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) { 1694 xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan"); 1695 xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n"); 1696 regp->DAC[765] = 0x3F; 1697 regp->DAC[766] = 0x00; 1698 regp->DAC[767] = 0x3F; 1699 regp->Attribute[OVERSCAN] = 0xFF; 1700 hwp->ShowOverscan = TRUE; 1701 } else 1702 hwp->ShowOverscan = FALSE; 1703 1704 hwp->paletteEnabled = FALSE; 1705 hwp->cmapSaved = FALSE; 1706 hwp->MapSize = 0; 1707 hwp->pScrn = scrp; 1708 1709 /* Initialise the function pointers with the standard VGA versions */ 1710 vgaHWSetStdFuncs(hwp); 1711 1712 hwp->PIOOffset = scrp->domainIOBase; 1713 hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]); 1714 1715 return TRUE; 1716} 1717 1718 1719void 1720vgaHWFreeHWRec(ScrnInfoPtr scrp) 1721{ 1722 if (vgaHWPrivateIndex >= 0) { 1723 vgaHWPtr hwp = VGAHWPTR(scrp); 1724 1725 if (!hwp) 1726 return; 1727 1728 free(hwp->FontInfo1); 1729 free(hwp->FontInfo2); 1730 free(hwp->TextInfo); 1731 1732 vgaHWFreeRegs (&hwp->ModeReg); 1733 vgaHWFreeRegs (&hwp->SavedReg); 1734 1735 free(hwp); 1736 VGAHWPTRLVAL(scrp) = NULL; 1737 } 1738} 1739 1740 1741Bool 1742vgaHWMapMem(ScrnInfoPtr scrp) 1743{ 1744 vgaHWPtr hwp = VGAHWPTR(scrp); 1745 int scr_index = scrp->scrnIndex; 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 hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev, 1764 hwp->MapPhys, hwp->MapSize); 1765 return hwp->Base != NULL; 1766} 1767 1768 1769void 1770vgaHWUnmapMem(ScrnInfoPtr scrp) 1771{ 1772 vgaHWPtr hwp = VGAHWPTR(scrp); 1773 int scr_index = scrp->scrnIndex; 1774 1775 if (hwp->Base == NULL) 1776 return; 1777 1778 DebugF("Unmapping VGAMem\n"); 1779 xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize); 1780 hwp->Base = NULL; 1781} 1782 1783int 1784vgaHWGetIndex(void) 1785{ 1786 return vgaHWPrivateIndex; 1787} 1788 1789 1790void 1791vgaHWGetIOBase(vgaHWPtr hwp) 1792{ 1793 hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ? 1794 VGA_IOBASE_COLOR : VGA_IOBASE_MONO; 1795 xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3, 1796 "vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n", 1797 hwp->IOBase, hwp->PIOOffset); 1798} 1799 1800 1801void 1802vgaHWLock(vgaHWPtr hwp) 1803{ 1804 /* Protect CRTC[0-7] */ 1805 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80); 1806} 1807 1808void 1809vgaHWUnlock(vgaHWPtr hwp) 1810{ 1811 /* Unprotect CRTC[0-7] */ 1812 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80); 1813} 1814 1815 1816void 1817vgaHWEnable(vgaHWPtr hwp) 1818{ 1819 hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01); 1820} 1821 1822 1823void 1824vgaHWDisable(vgaHWPtr hwp) 1825{ 1826 hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01); 1827} 1828 1829 1830static void 1831vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 1832 VisualPtr pVisual) 1833{ 1834 vgaHWPtr hwp = VGAHWPTR(pScrn); 1835 int i, index; 1836 1837 for (i = 0; i < numColors; i++) { 1838 index = indices[i]; 1839 hwp->writeDacWriteAddr(hwp, index); 1840 DACDelay(hwp); 1841 hwp->writeDacData(hwp, colors[index].red); 1842 DACDelay(hwp); 1843 hwp->writeDacData(hwp, colors[index].green); 1844 DACDelay(hwp); 1845 hwp->writeDacData(hwp, colors[index].blue); 1846 DACDelay(hwp); 1847 } 1848 1849 /* This shouldn't be necessary, but we'll play safe. */ 1850 hwp->disablePalette(hwp); 1851} 1852 1853 1854static void 1855vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan) 1856{ 1857 vgaHWPtr hwp = VGAHWPTR(pScrn); 1858 1859 if (overscan < 0 || overscan > 255) 1860 return; 1861 1862 hwp->enablePalette(hwp); 1863 hwp->writeAttr(hwp, OVERSCAN, overscan); 1864 1865#ifdef DEBUGOVERSCAN 1866 { 1867 int ov = hwp->readAttr(hwp, OVERSCAN); 1868 int red, green, blue; 1869 1870 hwp->writeDacReadAddr(hwp, ov); 1871 red = hwp->readDacData(hwp); 1872 green = hwp->readDacData(hwp); 1873 blue = hwp->readDacData(hwp); 1874 ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n", 1875 ov, red, green, blue); 1876 } 1877#endif 1878 1879 hwp->disablePalette(hwp); 1880} 1881 1882 1883Bool 1884vgaHWHandleColormaps(ScreenPtr pScreen) 1885{ 1886 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1887 1888 if (pScrn->depth > 1 && pScrn->depth <= 8) { 1889 return xf86HandleColormaps(pScreen, 1 << pScrn->depth, 1890 pScrn->rgbBits, vgaHWLoadPalette, 1891 pScrn->depth > 4 ? vgaHWSetOverscan : NULL, 1892 CMAP_RELOAD_ON_MODE_SWITCH); 1893 } 1894 return TRUE; 1895} 1896 1897/* ----------------------- DDC support ------------------------*/ 1898/* 1899 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total 1900 * to read out EDID at a faster rate. Allowed maximum is 25kHz with 1901 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen 1902 * readback, enable access to cr00-cr07. 1903 */ 1904 1905/* vertical timings */ 1906#define DISPLAY_END 0x04 1907#define BLANK_START DISPLAY_END 1908#define SYNC_START BLANK_START 1909#define SYNC_END 0x09 1910#define BLANK_END SYNC_END 1911#define V_TOTAL BLANK_END 1912/* this function doesn't have to be reentrant for our purposes */ 1913struct _vgaDdcSave { 1914 unsigned char cr03; 1915 unsigned char cr06; 1916 unsigned char cr07; 1917 unsigned char cr09; 1918 unsigned char cr10; 1919 unsigned char cr11; 1920 unsigned char cr12; 1921 unsigned char cr15; 1922 unsigned char cr16; 1923 unsigned char msr; 1924}; 1925 1926void 1927vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) 1928{ 1929 vgaHWPtr hwp = VGAHWPTR(pScrn); 1930 unsigned char tmp; 1931 struct _vgaDdcSave* save; 1932 switch (speed) { 1933 case DDC_FAST: 1934 1935 if (hwp->ddc != NULL) break; 1936 hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1); 1937 save = (struct _vgaDdcSave *)hwp->ddc; 1938 /* Lightpen register disable - allow access to cr10 & 11; just in case */ 1939 save->cr03 = hwp->readCrtc(hwp, 0x03); 1940 hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80)); 1941 save->cr12 = hwp->readCrtc(hwp, 0x12); 1942 hwp->writeCrtc(hwp,0x12,DISPLAY_END); 1943 save->cr15 = hwp->readCrtc(hwp, 0x15); 1944 hwp->writeCrtc(hwp,0x15,BLANK_START); 1945 save->cr10 = hwp->readCrtc(hwp, 0x10); 1946 hwp->writeCrtc(hwp,0x10,SYNC_START); 1947 save->cr11 = hwp->readCrtc(hwp, 0x11); 1948 /* unprotect group 1 registers; just in case ...*/ 1949 hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END)); 1950 save->cr16 = hwp->readCrtc(hwp, 0x16); 1951 hwp->writeCrtc(hwp,0x16,BLANK_END); 1952 save->cr06 = hwp->readCrtc(hwp, 0x06); 1953 hwp->writeCrtc(hwp,0x06,V_TOTAL); 1954 /* all values have less than 8 bit - mask out 9th and 10th bits */ 1955 save->cr09 = hwp->readCrtc(hwp, 0x09); 1956 hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF)); 1957 save->cr07 = hwp->readCrtc(hwp, 0x07); 1958 hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10)); 1959 /* vsync polarity negativ & ensure a 25MHz clock */ 1960 save->msr = hwp->readMiscOut(hwp); 1961 hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80)); 1962 break; 1963 case DDC_SLOW: 1964 if (hwp->ddc == NULL) break; 1965 save = (struct _vgaDdcSave *)hwp->ddc; 1966 hwp->writeMiscOut(hwp,save->msr); 1967 hwp->writeCrtc(hwp,0x07,save->cr07); 1968 tmp = hwp->readCrtc(hwp, 0x09); 1969 hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF))); 1970 hwp->writeCrtc(hwp,0x06,save->cr06); 1971 hwp->writeCrtc(hwp,0x16,save->cr16); 1972 hwp->writeCrtc(hwp,0x11,save->cr11); 1973 hwp->writeCrtc(hwp,0x10,save->cr10); 1974 hwp->writeCrtc(hwp,0x15,save->cr15); 1975 hwp->writeCrtc(hwp,0x12,save->cr12); 1976 hwp->writeCrtc(hwp,0x03,save->cr03); 1977 free(save); 1978 hwp->ddc = NULL; 1979 break; 1980 default: 1981 break; 1982 } 1983} 1984 1985DDC1SetSpeedProc 1986vgaHWddc1SetSpeedWeak(void) 1987{ 1988 return vgaHWddc1SetSpeed; 1989} 1990 1991SaveScreenProcPtr vgaHWSaveScreenWeak(void) 1992{ 1993 return vgaHWSaveScreen; 1994} 1995