1 /* 2 * Copyright 2000 through 2004 by Marc Aurele La France (TSI @ UQV), tsi (at) 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 * DRI support by: 23 * Manuel Teira 24 * Leif Delgass <ldelgass (at) retinalburn.net> 25 */ 26 27 #ifndef ___ATIMACH64IO_H___ 28 29 #if !defined(___ATI_H___) && defined(XFree86Module) 30 # error Missing #include "ati.h" before #include "atimach64io.h" 31 # undef XFree86Module 32 #endif 33 34 #define ___ATIMACH64IO_H___ 1 35 36 #include "atiregs.h" 37 #include "atistruct.h" 38 39 #include "compiler.h" 40 41 /* 42 * A few important notes on some of the I/O statements provided: 43 * 44 * inl/outl 32-bit R/W through PIO space. The register is specified as the 45 * actual PIO address. These are actually defined in compiler.h. 46 * 47 * inb/outb 8-bit counterparts to inl/outl. 48 * 49 * inm/outm 32-bit R/W through MMIO space. The register is specified as 50 * the actual MMIO offset (with Block 1 following Block 0), which, 51 * in this case, is equivalent to the register's IOPortTag from 52 * atiregs.h. Can be used for those few non-FIFO'ed registers 53 * outside of Block 0's first 256 bytes. inm() can also be used 54 * for FIFO'ed registers if, and only if, it can be guaranteed to 55 * not have been previously FIFO'ed (e.g. when the engine is 56 * idle). pATI->pBlock array elements must have been previously 57 * set up by ATIMapApertures(). 58 * 59 * outf 32-bit write through MMIO cache. Identical to outm() but 60 * intended for FIFO'ed registers. There is no inf() provided. 61 * 62 * inr/outr 32-bit R/W through PIO or MMIO. Which one depends on the 63 * machine architecture. The register is specified as a IOPortTag 64 * from atiregs.h. Can only be used for registers in the first 65 * 256 bytes of MMIO space (in Block 0). Note that all of these 66 * registers are non-FIFO'ed. 67 * 68 * in8/out8 8-bit counterparts to inr/outr. 69 * 70 * For portability reasons, inr/outr/in8/out8 should be used in preference to 71 * inl/outl/inb/outb to/from any register space starting with CRTC_H_TOTAL_DISP 72 * but before DST_OFF_PITCH (in the order defined by atiregs.h). None of 73 * inm/outm/outf should ever be used for these registers. 74 * 75 * outf()'s should be grouped together as much as possible, while respecting 76 * any ordering constraints the engine might impose. Groups larger than 16 77 * outf()'s should be split up into two or more groups as needed (but not 78 * necessarily wanted). The outf() groups that result should be immediately 79 * preceded by an ATIMach64WaitForFIFO(n) call, where "n" is the number of 80 * outf()'s in the group with the exception that groups containing a single 81 * outf() should not be thus preceded. This means "n" should not be less than 82 * 2, nor larger than 16. 83 */ 84 85 /* 86 * Cave canem (or it WILL bite you): All Mach64 non-VGA registers are 87 * ================================ little-endian, no matter how they are 88 * accessed (nor by what). 89 */ 90 91 /* I/O decoding definitions */ 92 typedef enum 93 { 94 SPARSE_IO, 95 BLOCK_IO 96 } ATIIODecodingType; 97 98 #define inm(_Register) \ 99 MMIO_IN32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \ 100 (_Register) & MM_IO_SELECT) 101 #define outm(_Register, _Value) \ 102 MMIO_OUT32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \ 103 (_Register) & MM_IO_SELECT, _Value) 104 105 #ifdef AVOID_CPIO 106 107 # define inr(_Register) \ 108 MMIO_IN32(pATI->pBlock[0], (_Register) & MM_IO_SELECT) 109 # define outr(_Register, _Value) \ 110 MMIO_OUT32(pATI->pBlock[0], (_Register) & MM_IO_SELECT, _Value) 111 112 # define in8(_Register) \ 113 MMIO_IN8(pATI->pBlock[0], \ 114 (_Register) & (MM_IO_SELECT | IO_BYTE_SELECT)) 115 # define out8(_Register, _Value) \ 116 MMIO_OUT8(pATI->pBlock[0], \ 117 (_Register) & (MM_IO_SELECT | IO_BYTE_SELECT), _Value) 118 119 /* Cause a cpp syntax error if any of these are used */ 120 #undef inb 121 #undef inl 122 #undef outb 123 #undef outl 124 125 #define inb() /* Nothing */ 126 #define inl() /* Nothing */ 127 #define outb() /* Nothing */ 128 #define outl() /* Nothing */ 129 130 #else /* AVOID_CPIO */ 131 132 # define ATIIOPort(_PortTag) \ 133 (((pATI->CPIODecoding == SPARSE_IO) ? \ 134 ((_PortTag) & (SPARSE_IO_SELECT | IO_BYTE_SELECT)) : \ 135 ((_PortTag) & (BLOCK_IO_SELECT | IO_BYTE_SELECT))) | \ 136 pATI->CPIOBase) 137 138 # define inr(_Register) \ 139 inl(ATIIOPort(_Register)) 140 # define outr(_Register, _Value) \ 141 outl(ATIIOPort(_Register), _Value) 142 143 # define in8(_Register) \ 144 inb(ATIIOPort(_Register)) 145 # define out8(_Register, _Value) \ 146 outb(ATIIOPort(_Register), _Value) 147 148 #endif /* AVOID_CPIO */ 149 150 extern void ATIMach64PollEngineStatus(ATIPtr); 151 152 /* 153 * MMIO cache definitions. 154 * 155 * Many FIFO'ed registers can be cached by the driver. Registers that qualify 156 * for caching must not contain values that can change without driver 157 * intervention. Thus registers that contain hardware counters, strobe lines, 158 * etc., cannot be cached. This caching is intended to minimise FIFO use. 159 * There is therefore not much point to enable it for non-FIFO'ed registers. 160 * 161 * The cache for a particular 32-bit register is enabled by coding a 162 * CacheRegister() line for that register in the ATIMach64Set() function. The 163 * integrity of the cache for a particular register should be verified by the 164 * ATIMach64Sync() function. This code should be kept in register order, as 165 * defined in atiregs.h. 166 */ 167 #define CacheByte(___Register) pATI->MMIOCached[CacheSlotOf(___Register) >> 3] 168 #define CacheBit(___Register) (0x80U >> (CacheSlotOf(___Register) & 0x07U)) 169 170 #define RegisterIsCached(__Register) \ 171 (CacheByte(__Register) & CacheBit(__Register)) 172 #define CacheSlot(__Register) pATI->MMIOCache[CacheSlotOf(__Register)] 173 174 #define CacheRegister(__Register) \ 175 CacheByte(__Register) |= CacheBit(__Register) 176 #define UncacheRegister(__Register) \ 177 CacheByte(__Register) &= ~CacheBit(__Register) 178 179 /* This would be quite a bit slower as a function */ 180 #define outf(_Register, _Value) \ 181 do \ 182 { \ 183 CARD32 _IOValue = (_Value); \ 184 \ 185 if (!RegisterIsCached(_Register) || \ 186 (_IOValue != CacheSlot(_Register))) \ 187 { \ 188 while (!pATI->nAvailableFIFOEntries--) \ 189 ATIMach64PollEngineStatus(pATI); \ 190 MMIO_OUT32(pATI->pBlock[GetBits(_Register, BLOCK_SELECT)], \ 191 (_Register) & MM_IO_SELECT, _IOValue); \ 192 CacheSlot(_Register) = _IOValue; \ 193 pATI->EngineIsBusy = TRUE; \ 194 } \ 195 } while (0) 196 197 /* 198 * This is no longer as critical, especially for _n == 1. However, 199 * there is still a need to ensure _n <= pATI->nFIFOEntries. 200 */ 201 #define ATIMach64WaitForFIFO(_pATI, _n) \ 202 while ((_pATI)->nAvailableFIFOEntries < (_n)) \ 203 ATIMach64PollEngineStatus(_pATI) 204 205 #define ATIMach64WaitForIdle(_pATI) \ 206 while ((_pATI)->EngineIsBusy) \ 207 ATIMach64PollEngineStatus(_pATI) 208 209 #ifdef XF86DRI_DEVEL 210 211 /* 212 * DRI Sync and Lock definitions. 213 */ 214 215 #define ATIDRIWaitForIdle(_pATI) \ 216 do { \ 217 ATIDRIServerInfoPtr pATIDRIServer = _pATI->pDRIServerInfo; \ 218 int ret; \ 219 \ 220 if (pATIDRIServer && pATI->directRenderingEnabled) { \ 221 /* Wait for DMA to complete */ \ 222 ret = drmCommandNone(_pATI->drmFD, DRM_MACH64_IDLE); \ 223 if (ret) { \ 224 drmCommandNone(_pATI->drmFD, DRM_MACH64_RESET); \ 225 } \ 226 \ 227 /* Force updating of FIFO entry counters */ \ 228 pATI->EngineIsBusy = TRUE; \ 229 ATIMach64PollEngineStatus(_pATI); \ 230 } else { \ 231 ATIMach64WaitForIdle(_pATI); \ 232 } \ 233 } while (0) 234 235 /* 236 * Set upon DRISwapContext and when DRI accesses the GPU engine 237 * from within the server, see DRIInitBuffers/DRIMoveBuffers. 238 * 239 * Forces the EXA software paths to sync before accessing the FB memory. 240 */ 241 static __inline__ void ATIDRIMarkSyncInt(ScrnInfoPtr _pScrInfo) 242 { 243 ATIPtr _pATI=ATIPTR(_pScrInfo); 244 #ifdef USE_EXA 245 if (_pATI->useEXA) 246 exaMarkSync(_pScrInfo->pScreen); 247 #endif 248 } 249 250 /* 251 * Set upon DRISwapContext and when the server acquires the DRI lock. 252 * 253 * Forces the EXA accelerated paths to sync before accessing the GPU engine. 254 */ 255 static __inline__ void ATIDRIMarkSyncExt(ScrnInfoPtr _pScrInfo) 256 { 257 ATIPtr _pATI=ATIPTR(_pScrInfo); 258 _pATI->NeedDRISync = TRUE; 259 } 260 261 static __inline__ void ATIDRISync(ScrnInfoPtr _pScrInfo) 262 { 263 ATIPtr _pATI=ATIPTR(_pScrInfo); 264 #ifdef USE_EXA 265 if (_pATI->directRenderingEnabled && _pATI->pExa) 266 { 267 if (_pATI->NeedDRISync) exaWaitSync(_pScrInfo->pScreen); 268 } 269 #endif 270 } 271 272 #define ATIDRILock(_pScrInfo) \ 273 do \ 274 { \ 275 ATIPtr _pATI=ATIPTR(_pScrInfo); \ 276 if (_pATI->directRenderingEnabled) \ 277 { \ 278 DRILock(_pScrInfo->pScreen, 0); \ 279 ATIDRIMarkSyncExt(_pScrInfo); \ 280 } \ 281 } while (0) 282 283 #define ATIDRIUnlock(_pScrInfo) \ 284 do \ 285 { \ 286 ATIPtr _pATI=ATIPTR(_pScrInfo); \ 287 if (_pATI->directRenderingEnabled) \ 288 { \ 289 DRIUnlock(_pScrInfo->pScreen); \ 290 } \ 291 } while (0) 292 293 #else /* XF86DRI_DEVEL */ 294 295 296 #define ATIDRIWaitForIdle(_pATI) 297 #define ATIDRILock(_pScrInfo) 298 #define ATIDRIUnlock(_pScrInfo) 299 #define ATIDRISync(_pScrInfo) 300 301 #endif /* XF86DRI_DEVEL */ 302 303 304 /* 305 * An outf() variant to write two registers such that the second register is 306 * is always written whenever either is to be changed. 307 */ 308 #define outq(_Register1, _Register2, _Value1, _Value2) \ 309 do \ 310 { \ 311 CARD32 _IOValue1 = (_Value1), \ 312 _IOValue2 = (_Value2); \ 313 \ 314 if (!RegisterIsCached(_Register1) || \ 315 (_IOValue1 != CacheSlot(_Register1))) \ 316 { \ 317 ATIMach64WaitForFIFO(pATI, 2); \ 318 pATI->nAvailableFIFOEntries -= 2; \ 319 MMIO_OUT32(pATI->pBlock[GetBits(_Register1, BLOCK_SELECT)], \ 320 (_Register1) & MM_IO_SELECT, _IOValue1); \ 321 MMIO_OUT32(pATI->pBlock[GetBits(_Register2, BLOCK_SELECT)], \ 322 (_Register2) & MM_IO_SELECT, _IOValue2); \ 323 CacheSlot(_Register1) = _IOValue1; \ 324 CacheSlot(_Register2) = _IOValue2; \ 325 pATI->EngineIsBusy = TRUE; \ 326 } \ 327 else if (!RegisterIsCached(_Register2) || \ 328 (_IOValue2 != CacheSlot(_Register2))) \ 329 { \ 330 while (!pATI->nAvailableFIFOEntries--) \ 331 ATIMach64PollEngineStatus(pATI); \ 332 MMIO_OUT32(pATI->pBlock[GetBits(_Register2, BLOCK_SELECT)], \ 333 (_Register2) & MM_IO_SELECT, _IOValue2); \ 334 CacheSlot(_Register2) = _IOValue2; \ 335 pATI->EngineIsBusy = TRUE; \ 336 } \ 337 } while (0) 338 339 extern void ATIMach64AccessPLLReg(ATIPtr, const CARD8, const Bool); 340 341 #define ATIMach64GetPLLReg(_Index) \ 342 ( \ 343 ATIMach64AccessPLLReg(pATI, _Index, FALSE), \ 344 in8(CLOCK_CNTL + 2) \ 345 ) 346 #define ATIMach64PutPLLReg(_Index, _Value) \ 347 do \ 348 { \ 349 ATIMach64AccessPLLReg(pATI, _Index, TRUE); \ 350 out8(CLOCK_CNTL + 2, _Value); \ 351 } while (0) 352 353 #define ATIMach64GetLCDReg(_Index) \ 354 ( \ 355 out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)), \ 356 inr(LCD_DATA) \ 357 ) 358 #define ATIMach64PutLCDReg(_Index, _Value) \ 359 do \ 360 { \ 361 out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)); \ 362 outr(LCD_DATA, _Value); \ 363 } while (0) 364 365 #define ATIMach64GetTVReg(_Index) \ 366 ( \ 367 out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)), \ 368 inr(TV_OUT_DATA) \ 369 ) 370 #define ATIMach64PutTVReg(_Index, _Value) \ 371 do \ 372 { \ 373 out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)); \ 374 outr(TV_OUT_DATA, _Value); \ 375 } while (0) 376 377 /* 378 * Block transfer definitions. 379 */ 380 381 #if defined(GCCUSESGAS) && \ 382 (defined(i386) || defined(__i386) || defined(__i386__)) 383 384 #define ATIMove32(_pDst, _pSrc, _nCount) \ 385 do \ 386 { \ 387 long d0, d1, d2; \ 388 __asm__ __volatile__ \ 389 ( \ 390 "cld\n\t" \ 391 "rep ; movsl" \ 392 : "=&c" (d0), \ 393 "=&D" (d1), \ 394 "=&S" (d2) \ 395 : "0" (_nCount), \ 396 "1" (_pDst), \ 397 "2" (_pSrc) \ 398 : "memory" \ 399 ); \ 400 } while (0) 401 402 #endif 403 404 /* 405 * Return the MMIO address of register, used for HOST_DATA_X only. 406 */ 407 #define ATIHostDataAddr(_Register) \ 408 ((CARD8 *)pATI->pBlock[GetBits(_Register, BLOCK_SELECT)] + \ 409 ((_Register) & MM_IO_SELECT)) 410 411 #endif /* ___ATIMACH64IO_H___ */ 412