/* * Copyright © 2004 Eric Anholt * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Eric Anholt not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Eric Anholt makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _ATI_DMA_H_ #define _ATI_DMA_H_ #define CCE_DEBUG 1 #if !CCE_DEBUG #define DMA_PACKET0(reg, count) \ (ATI_CCE_PACKET0 | (((count) - 1) << 16) | ((reg) >> 2)) #else #define DMA_PACKET0(reg, count) \ (__packet0count = (count), __reg = (reg), \ ATI_CCE_PACKET0 | (((count) - 1) << 16) | ((reg) >> 2)) #endif #define DMA_PACKET1(reg1, reg2) \ (ATI_CCE_PACKET1 | \ (((reg2) >> 2) << ATI_CCE_PACKET1_REG_2_SHIFT) | ((reg1) >> 2)) #define DMA_PACKET3(type, count) \ ((type) | (((count) - 1) << 16)) #if !CCE_DEBUG #define RING_LOCALS CARD32 *__head; int __count #define BEGIN_DMA(n) \ do { \ if ((atis->indirectBuffer->used + 4*(n)) > \ atis->indirectBuffer->size) { \ ATIFlushIndirect(atis, 1); \ } \ __head = (CARD32 *)((char *)atis->indirectBuffer->address + \ atis->indirectBuffer->used); \ __count = 0; \ } while (0) #define END_DMA() do { \ atis->indirectBuffer->used += __count * 4; \ } while (0) #else #define RING_LOCALS \ CARD32 *__head; int __count, __total, __reg, __packet0count #define BEGIN_DMA(n) \ do { \ if ((atis->indirectBuffer->used + 4*(n)) > \ atis->indirectBuffer->size) { \ ATIFlushIndirect(atis, 1); \ } \ __head = (CARD32 *)((char *)atis->indirectBuffer->address + \ atis->indirectBuffer->used); \ __count = 0; \ __total = n; \ __reg = 0; \ __packet0count = 0; \ } while (0) #define END_DMA() do { \ if (__count != __total) \ FatalError("count != total (%d vs %d) at %s:%d\n", \ __count, __total, __FILE__, __LINE__); \ atis->indirectBuffer->used += __count * 4; \ } while (0) #endif #define OUT_RING(val) do { \ __head[__count++] = (val); \ } while (0) #define OUT_RING_REG(reg, val) do { \ if (__reg != reg) \ FatalError("unexpected reg (0x%x vs 0x%x) at %s:%d\n", \ reg, __reg, __FILE__, __LINE__); \ if (__packet0count-- <= 0) \ FatalError("overrun of packet0 at %s:%d\n", \ __FILE__, __LINE__); \ __head[__count++] = (val); \ __reg += 4; \ } while (0) #define OUT_RING_F(x) OUT_RING(GET_FLOAT_BITS(x)) #define OUT_REG(reg, val) \ do { \ OUT_RING(DMA_PACKET0(reg, 1)); \ OUT_RING(val); \ } while (0) #define TIMEOUT_LOCALS struct timeval _target, _curtime static inline Bool tv_le(struct timeval *tv1, struct timeval *tv2) { if (tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec < tv2->tv_usec)) return TRUE; else return FALSE; } #define WHILE_NOT_TIMEOUT(_timeout) \ gettimeofday(&_target, NULL); \ _target.tv_usec += ((_timeout) * 1000000); \ _target.tv_sec += _target.tv_usec / 1000000; \ _target.tv_usec = _target.tv_usec % 1000000; \ while (gettimeofday(&_curtime, NULL), tv_le(&_curtime, &_target)) #define TIMEDOUT() (!tv_le(&_curtime, &_target)) dmaBuf * ATIGetDMABuffer(ATIScreenInfo *atis); void ATIFlushIndirect(ATIScreenInfo *atis, Bool discard); void ATIDMASetup(ScreenPtr pScreen); void ATIDMATeardown(ScreenPtr pScreen); #endif /* _ATI_DMA_H_ */