1/* 2 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as-is" without express or implied warranty. 13 * 14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include <string.h> 28#include <stdio.h> 29#include <stdint.h> 30 31#include "ati.h" 32#include "atibus.h" 33#include "atichip.h" 34#include "atimach64io.h" 35#include "atimach64version.h" 36#include "atiprobe.h" 37#include "atividmem.h" 38#include "atiwonderio.h" 39 40#ifndef AVOID_CPIO 41 42/* 43 * ATIVGAWonderProbe -- 44 * 45 * This function determines if ATI extended VGA registers can be accessed 46 * through the I/O port specified by pATI->CPIO_VGAWonder. If not, the 47 * function resets pATI->CPIO_VGAWonder to zero. 48 */ 49static void 50ATIVGAWonderProbe 51( 52 pciVideoPtr pVideo, 53 ATIPtr pATI 54) 55{ 56 CARD8 IOValue1, IOValue2, IOValue3, IOValue4, IOValue5, IOValue6; 57 58 if (!pATI->OptionProbeSparse) 59 { 60 xf86Msg(X_WARNING, 61 MACH64_NAME ": Expected VGA Wonder capability at I/O port" 62 " 0x%04lX will not be probed\n" 63 "set option \"probe_sparse\" to force probing.\n", 64 pATI->CPIO_VGAWonder); 65 66 pATI->CPIO_VGAWonder = 0; 67 return; 68 } 69 70 if (pVideo && !xf86IsPrimaryPci(pVideo) && 71 (pATI->Chip <= ATI_CHIP_88800GXD)) 72 { 73 /* Set up extended VGA register addressing */ 74 PutReg(GRAX, 0x50U, GetByte(pATI->CPIO_VGAWonder, 0)); 75 PutReg(GRAX, 0x51U, GetByte(pATI->CPIO_VGAWonder, 1) | 0x80U); 76 } 77 /* 78 * Register 0xBB is used by the BIOS to keep track of various 79 * things (monitor type, etc.). Except for 18800-x's, register 80 * 0xBC must be zero and causes the adapter to enter a test mode 81 * when written to with a non-zero value. 82 */ 83 IOValue1 = inb(pATI->CPIO_VGAWonder); 84 IOValue2 = ATIGetExtReg(IOValue1); 85 IOValue3 = ATIGetExtReg(0xBBU); 86 ATIPutExtReg(0xBBU, IOValue3 ^ 0xAAU); 87 IOValue4 = ATIGetExtReg(0xBBU); 88 ATIPutExtReg(0xBBU, IOValue3 ^ 0x55U); 89 IOValue5 = ATIGetExtReg(0xBBU); 90 ATIPutExtReg(0xBBU, IOValue3); 91 IOValue6 = ATIGetExtReg(0xBCU); 92 ATIPutExtReg(IOValue1, IOValue2); 93 94 if ((IOValue4 == (IOValue3 ^ 0xAAU)) && 95 (IOValue5 == (IOValue3 ^ 0x55U)) && 96 (IOValue6 == 0)) 97 { 98 xf86MsgVerb(X_INFO, 3, 99 MACH64_NAME ": VGA Wonder at I/O port 0x%04lX detected.\n", 100 pATI->CPIO_VGAWonder); 101 } 102 else 103 { 104 xf86Msg(X_WARNING, 105 MACH64_NAME ": Expected VGA Wonder capability at I/O port" 106 " 0x%04lX was not detected.\n", pATI->CPIO_VGAWonder); 107 pATI->CPIO_VGAWonder = 0; 108 } 109} 110 111#endif /* AVOID_CPIO */ 112 113/* 114 * ATIMach64Detect -- 115 * 116 * This function determines if a Mach64 is detectable at a particular base 117 * address. 118 */ 119static Bool 120ATIMach64Detect 121( 122 ATIPtr pATI, 123 const CARD16 ChipType, 124 const ATIChipType Chip 125) 126{ 127 CARD32 IOValue, bus_cntl, gen_test_cntl; 128 Bool DetectSuccess = FALSE; 129 130 (void)ATIMapApertures(-1, pATI); /* Ignore errors */ 131 132#ifdef AVOID_CPIO 133 134 if (!pATI->pBlock[0]) 135 { 136 ATIUnmapApertures(-1, pATI); 137 return FALSE; 138 } 139 140#endif /* AVOID_CPIO */ 141 142 /* Make sure any Mach64 is not in some weird state */ 143 bus_cntl = inr(BUS_CNTL); 144 if (Chip < ATI_CHIP_264VTB) 145 outr(BUS_CNTL, 146 (bus_cntl & ~(BUS_HOST_ERR_INT_EN | BUS_FIFO_ERR_INT_EN)) | 147 (BUS_HOST_ERR_INT | BUS_FIFO_ERR_INT)); 148 else if (Chip < ATI_CHIP_264VT4) 149 outr(BUS_CNTL, (bus_cntl & ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT); 150 151 gen_test_cntl = inr(GEN_TEST_CNTL); 152 IOValue = gen_test_cntl & 153 (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN); 154 outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN); 155 outr(GEN_TEST_CNTL, IOValue); 156 outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN); 157 158 /* See if a Mach64 answers */ 159 IOValue = inr(SCRATCH_REG0); 160 161 /* Test odd bits */ 162 outr(SCRATCH_REG0, 0x55555555U); 163 if (inr(SCRATCH_REG0) == 0x55555555U) 164 { 165 /* Test even bits */ 166 outr(SCRATCH_REG0, 0xAAAAAAAAU); 167 if (inr(SCRATCH_REG0) == 0xAAAAAAAAU) 168 { 169 /* 170 * *Something* has a R/W 32-bit register at this address. Try to 171 * make sure it's a Mach64. The following assumes that ATI will 172 * not be producing any more adapters that do not register 173 * themselves in PCI configuration space. 174 */ 175 ATIMach64ChipID(pATI, ChipType); 176 if ((pATI->Chip != ATI_CHIP_Mach64) || 177 (pATI->CPIODecoding == BLOCK_IO)) 178 DetectSuccess = TRUE; 179 } 180 } 181 182 /* Restore clobbered register value */ 183 outr(SCRATCH_REG0, IOValue); 184 185 /* If no Mach64 was detected, return now */ 186 if (!DetectSuccess) 187 { 188 outr(GEN_TEST_CNTL, gen_test_cntl); 189 outr(BUS_CNTL, bus_cntl); 190 ATIUnmapApertures(-1, pATI); 191 return FALSE; 192 } 193 194 ATIUnmapApertures(-1, pATI); 195 return TRUE; 196} 197 198#ifdef AVOID_CPIO 199 200/* 201 * ATIMach64Probe -- 202 * 203 * This function looks for a Mach64 at a particular MMIO address and returns an 204 * ATIRec if one is found. 205 */ 206static ATIPtr 207ATIMach64Probe 208( 209 ATIPtr pATI, 210 pciVideoPtr pVideo, 211 const ATIChipType Chip 212) 213{ 214 CARD16 ChipType = PCI_DEV_DEVICE_ID(pVideo); 215 216 pATI->MMIOInLinear = FALSE; 217 218 /* 219 * Probe through auxiliary MMIO aperture if one exists. Because such 220 * apertures can be enabled/disabled only through PCI, this probes no 221 * further. 222 */ 223 if ((PCI_REGION_SIZE(pVideo, 2) >= (1 << 12)) && 224 (pATI->Block0Base = PCI_REGION_BASE(pVideo, 2, REGION_MEM)) && 225 (pATI->Block0Base != 0xfffff000)) 226 { 227 pATI->Block0Base += 0x00000400U; 228 if (ATIMach64Detect(pATI, ChipType, Chip)) 229 return pATI; 230 231 return NULL; 232 } 233 234 /* 235 * Probe through the primary MMIO aperture that exists at the tail end 236 * of the linear aperture. Test for both 8MB and 4MB linear apertures. 237 */ 238 if ((PCI_REGION_SIZE(pVideo, 0) >= (1 << 22)) && 239 (pATI->Block0Base = PCI_REGION_BASE(pVideo, 0, REGION_MEM))) 240 { 241 pATI->MMIOInLinear = TRUE; 242 pATI->Block0Base += 0x007FFC00U; 243 if ((PCI_REGION_SIZE(pVideo, 0) >= (1 << 23)) && 244 ATIMach64Detect(pATI, ChipType, Chip)) 245 return pATI; 246 247 pATI->Block0Base -= 0x00400000U; 248 if (ATIMach64Detect(pATI, ChipType, Chip)) 249 return pATI; 250 } 251 252 return NULL; 253} 254 255#else /* AVOID_CPIO */ 256 257/* 258 * ATIMach64Probe -- 259 * 260 * This function looks for a Mach64 at a particular PIO address and returns an 261 * ATIRec if one is found. 262 */ 263static ATIPtr 264ATIMach64Probe 265( 266 ATIPtr pATI, 267 pciVideoPtr pVideo, 268 const ATIChipType Chip 269) 270{ 271 CARD32 IOValue; 272 CARD16 ChipType = PCI_DEV_DEVICE_ID(pVideo); 273 274 if ((pATI->CPIODecoding == BLOCK_IO) && 275 (PCI_REGION_SIZE(pVideo, 1) < (1 << 8))) 276 return NULL; 277 278 if (!ATIMach64Detect(pATI, ChipType, Chip)) 279 { 280 return NULL; 281 } 282 283 /* 284 * Determine VGA capability. VGA can always be enabled on integrated 285 * controllers. For the GX/CX, it's a board strap. 286 */ 287 if (pATI->Chip >= ATI_CHIP_264CT) 288 { 289 pATI->VGAAdapter = TRUE; 290 } 291 else 292 { 293 IOValue = inr(CONFIG_STATUS64_0); 294 pATI->BusType = GetBits(IOValue, CFG_BUS_TYPE); 295 IOValue &= (CFG_VGA_EN | CFG_CHIP_EN); 296 if (pATI->Chip == ATI_CHIP_88800CX) 297 IOValue |= CFG_VGA_EN; 298 if (IOValue == (CFG_VGA_EN | CFG_CHIP_EN)) 299 { 300 pATI->VGAAdapter = TRUE; 301 pATI->CPIO_VGAWonder = 0x01CEU; 302 } 303 } 304 305 return pATI; 306} 307 308static void 309ATIAssignVGA 310( 311 pciVideoPtr pVideo, 312 ATIPtr pATI 313) 314{ 315 if (pATI->CPIO_VGAWonder) 316 { 317 ATIVGAWonderProbe(pVideo, pATI); 318 if (!pATI->CPIO_VGAWonder) 319 { 320 /* 321 * Some adapters are reputed to append ATI extended VGA registers 322 * to the VGA Graphics controller registers. In particular, 0x01CE 323 * cannot, in general, be used in a PCI environment due to routing 324 * of I/O through the bus tree. 325 */ 326 pATI->CPIO_VGAWonder = GRAX; 327 ATIVGAWonderProbe(pVideo, pATI); 328 } 329 } 330} 331 332/* 333 * ATIFindVGA -- 334 * 335 * This function determines if a VGA associated with an ATI PCI adapter is 336 * shareable. 337 */ 338static void 339ATIFindVGA 340( 341 pciVideoPtr pVideo, 342 ATIPtr pATI 343) 344{ 345 /* 346 * An ATI PCI adapter has been detected at this point, and its VGA, if 347 * any, is shareable. Ensure the VGA isn't in sleep mode. 348 */ 349 outb(GENENA, 0x16U); 350 outb(GENVS, 0x01U); 351 outb(GENENA, 0x0EU); 352 353 ATIAssignVGA(pVideo, pATI); 354} 355 356#endif /* AVOID_CPIO */ 357 358/* 359 * ATIMach64ProbeIO -- 360 * 361 * This function determines the IO method and IO base of the ATI PCI adapter. 362 */ 363Bool 364ATIMach64ProbeIO 365( 366 pciVideoPtr pVideo, 367 ATIPtr pATI 368) 369{ 370 /* Next, look for sparse I/O Mach64's */ 371 if (!PCI_REGION_SIZE(pVideo, 1)) 372 { 373 374#ifndef AVOID_CPIO 375 376 static const unsigned long Mach64SparseIOBases[] = { 377 0x02ECU, 378 0x01CCU, 379 0x01C8U 380 }; 381 uint32_t PciReg; 382 uint32_t j; 383 384#ifndef XSERVER_LIBPCIACCESS 385 pciConfigPtr pPCI = pVideo->thisCard; 386 387 if (pPCI == NULL) 388 return FALSE; 389#endif 390 391 PCI_READ_LONG(pVideo, &PciReg, PCI_REG_USERCONFIG); 392 j = PciReg & 0x03U; 393 394 if (j == 0x03U) 395 { 396 xf86Msg(X_WARNING, MACH64_NAME ": " 397 "PCI Mach64 in slot %d:%d:%d cannot be enabled\n" 398 "because it has neither a block, nor a sparse, I/O base.\n", 399 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo)); 400 401 return FALSE; 402 } 403 404 /* Possibly fix block I/O indicator */ 405 if (PciReg & 0x00000004U) 406 { 407 PciReg &= ~0x00000004U; 408 PCI_WRITE_LONG(pVideo, PciReg, PCI_REG_USERCONFIG); 409 } 410 411 /* FIXME: 412 * Should not probe at sparse I/O bases which have been registered to 413 * other PCI devices. The old ATIProbe() would scan the PCI space and 414 * build a list of registered I/O ports. If there was a conflict 415 * between a mach64 sparse I/O base and a registered I/0 port, probing 416 * that port was not allowed... 417 * 418 * We just add an option and let the user decide, this will not work 419 * with "X -configure" though... 420 */ 421 if (!pATI->OptionProbeSparse) 422 { 423 xf86Msg(X_WARNING, MACH64_NAME ": " 424 "PCI Mach64 in slot %d:%d:%d will not be probed\n" 425 "set option \"probe_sparse\" to force sparse I/O probing.\n", 426 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo)); 427 428 return FALSE; 429 } 430 431 pATI->CPIOBase = Mach64SparseIOBases[j]; 432 pATI->CPIODecoding = SPARSE_IO; 433 pATI->PCIInfo = pVideo; 434 435#else /* AVOID_CPIO */ 436 437 /* The adapter's CPIO base is of little concern here */ 438 pATI->CPIOBase = 0; 439 pATI->CPIODecoding = SPARSE_IO; 440 pATI->PCIInfo = pVideo; 441 442#endif /* AVOID_CPIO */ 443 444 } 445 446 /* Lastly, look for block I/O devices */ 447 if (PCI_REGION_SIZE(pVideo, 1)) 448 { 449 pATI->CPIOBase = PCI_REGION_BASE(pVideo, 1, REGION_IO); 450 pATI->CPIODecoding = BLOCK_IO; 451 pATI->PCIInfo = pVideo; 452 } 453 454 if (!ATIMach64Probe(pATI, pVideo, pATI->Chip)) 455 { 456 xf86Msg(X_WARNING, MACH64_NAME ": " 457 "Mach64 in slot %d:%d:%d could not be detected!\n", 458 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo)); 459 460 return FALSE; 461 } 462 463 xf86Msg(X_INFO, MACH64_NAME ": " 464 "Mach64 in slot %d:%d:%d detected.\n", 465 PCI_DEV_BUS(pVideo), PCI_DEV_DEV(pVideo), PCI_DEV_FUNC(pVideo)); 466 467#ifndef AVOID_CPIO 468 469 if (pATI->VGAAdapter) 470 ATIFindVGA(pVideo, pATI); 471 472#endif /* AVOID_CPIO */ 473 474 return TRUE; 475} 476