Home | History | Annotate | Line # | Download | only in src
      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