summaryrefslogtreecommitdiff
path: root/hw/kdrive/ati/ati_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/ati/ati_dma.c')
-rw-r--r--hw/kdrive/ati/ati_dma.c1036
1 files changed, 0 insertions, 1036 deletions
diff --git a/hw/kdrive/ati/ati_dma.c b/hw/kdrive/ati/ati_dma.c
deleted file mode 100644
index f75ff12e7..000000000
--- a/hw/kdrive/ati/ati_dma.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-/*
- * 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.
- */
-/* $Header$ */
-
-#include <sys/time.h>
-
-#include "ati.h"
-#include "ati_reg.h"
-#include "ati_dma.h"
-#include "ati_draw.h"
-
-#ifdef USE_DRI
-#include "radeon_common.h"
-#include "r128_common.h"
-#include "ati_sarea.h"
-#endif /* USE_DRI */
-
-#include "agp.h"
-
-#define DEBUG_FIFO 0
-
-extern CARD32 r128_cce_microcode[];
-extern CARD32 radeon_cp_microcode[][2];
-extern CARD32 r200_cp_microcode[][2];
-extern CARD32 r300_cp_microcode[][2];
-
-static void
-ATIDebugFifo(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
-
- if (atic->is_radeon) {
- ErrorF("RADEON_REG_CP_CSQ_CNTL: 0x%08x\n",
- MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL));
- ErrorF("RADEON_REG_CP_CSQ_STAT: 0x%08x\n",
- MMIO_IN32(mmio, RADEON_REG_CP_CSQ_STAT));
- ErrorF("RADEON_REG_RBBM_STATUS: 0x%08x\n",
- MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS));
- ErrorF("RADEON_REG_RB3D_DSTCACHE_CTLSTAT: 0x%08x\n",
- MMIO_IN32(mmio, RADEON_REG_RB3D_DSTCACHE_CTLSTAT));
- } else {
- ErrorF("R128_REG_PM4_BUFFER_CNTL: 0x%08x\n",
- MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL));
- ErrorF("R128_REG_PM4_STAT: 0x%08x\n",
- MMIO_IN32(mmio, R128_REG_PM4_STAT));
- ErrorF("R128_REG_GUI_STAT: 0x%08x\n",
- MMIO_IN32(mmio, R128_REG_GUI_STAT));
- ErrorF("R128_REG_PC_NGUI_CTLSTAT: 0x%08x\n",
- MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT));
- }
-}
-
-static void
-ATIUploadMicrocode(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- int i;
-
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_ADDR, 0);
- if (atic->is_radeon && atic->is_r300) {
- for (i = 0; i < 256; i++) {
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH,
- r300_cp_microcode[i][1]);
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL,
- r300_cp_microcode[i][0]);
- }
- } else if (atic->is_radeon && atic->is_r200) {
- for (i = 0; i < 256; i++) {
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH,
- r200_cp_microcode[i][1]);
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL,
- r200_cp_microcode[i][0]);
- }
- } else if (atic->is_radeon && atic->is_r100) {
- for (i = 0; i < 256; i++) {
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH,
- radeon_cp_microcode[i][1]);
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL,
- radeon_cp_microcode[i][0]);
- }
- } else {
- for (i = 0; i < 256; i++) {
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH,
- r128_cce_microcode[i * 2]);
- MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL,
- r128_cce_microcode[i * 2 + 1]);
- }
- }
-}
-
-/* Required when reading from video memory after acceleration to make sure all
- * data has been flushed to video memory from the pixel cache.
- */
-static void
-ATIFlushPixelCache(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- CARD32 temp;
- TIMEOUT_LOCALS;
-
- if (atic->is_radeon) {
- temp = MMIO_IN32(mmio, RADEON_REG_RB3D_DSTCACHE_CTLSTAT);
- temp |= RADEON_RB3D_DC_FLUSH_ALL;
- MMIO_OUT32(mmio, RADEON_REG_RB3D_DSTCACHE_CTLSTAT, temp);
-
- WHILE_NOT_TIMEOUT(.2) {
- if ((MMIO_IN32(mmio, RADEON_REG_RB3D_DSTCACHE_CTLSTAT) &
- RADEON_RB3D_DC_BUSY) == 0)
- break;
- }
- } else {
- temp = MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT);
- temp |= R128_PC_FLUSH_ALL;
- MMIO_OUT32(mmio, R128_REG_PC_NGUI_CTLSTAT, temp);
-
- WHILE_NOT_TIMEOUT(.2) {
- if ((MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT) &
- R128_PC_BUSY) != R128_PC_BUSY)
- break;
- }
- }
- if (TIMEDOUT())
- ErrorF("Timeout flushing pixel cache.\n");
-}
-
-static void
-ATIEngineReset(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- CARD32 clockcntlindex, mclkcntl;
-
-#if DEBUG_FIFO
- ErrorF("Engine Reset!\n");
- ATIDebugFifo(atis);
-#endif
-
- ATIFlushPixelCache(atis);
-
- clockcntlindex = MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX);
- if (atic->is_r300)
- R300CGWorkaround(atis);
-
- if (atic->is_radeon) {
- CARD32 host_path_cntl;
-
- mclkcntl = INPLL(mmio, RADEON_REG_MCLK_CNTL);
-
- OUTPLL(mmio, RADEON_REG_MCLK_CNTL, mclkcntl |
- RADEON_FORCEON_MCLKA |
- RADEON_FORCEON_MCLKB |
- RADEON_FORCEON_YCLKA |
- RADEON_FORCEON_YCLKB |
- RADEON_FORCEON_MC |
- RADEON_FORCEON_AIC);
-
- host_path_cntl = MMIO_IN32(mmio, RADEON_REG_HOST_PATH_CNTL);
-
- if (atic->is_r300) {
- MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET,
- RADEON_SOFT_RESET_CP |
- RADEON_SOFT_RESET_HI |
- RADEON_SOFT_RESET_E2);
- } else {
- MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET,
- RADEON_SOFT_RESET_CP |
- RADEON_SOFT_RESET_SE |
- RADEON_SOFT_RESET_RE |
- RADEON_SOFT_RESET_PP |
- RADEON_SOFT_RESET_E2 |
- RADEON_SOFT_RESET_RB);
- }
- MMIO_IN32(mmio, RADEON_REG_RBBM_SOFT_RESET);
- MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET, 0);
-
- MMIO_OUT32(mmio, RADEON_REG_HOST_PATH_CNTL, host_path_cntl |
- RADEON_HDP_SOFT_RESET);
- MMIO_IN32(mmio, RADEON_REG_HOST_PATH_CNTL);
- MMIO_OUT32(mmio, RADEON_REG_HOST_PATH_CNTL, host_path_cntl);
-
- MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, clockcntlindex);
- OUTPLL(mmio, RADEON_REG_MCLK_CNTL, mclkcntl);
- if (atic->is_r300)
- R300CGWorkaround(atis);
- } else {
- CARD32 temp;
-
- mclkcntl = INPLL(mmio, R128_REG_MCLK_CNTL);
-
- OUTPLL(mmio, R128_REG_MCLK_CNTL,
- mclkcntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
-
- temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL);
- MMIO_OUT32(mmio, R128_REG_GEN_RESET_CNTL,
- temp | R128_SOFT_RESET_GUI);
- temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL);
- MMIO_OUT32(mmio, R128_REG_GEN_RESET_CNTL,
- temp & ~R128_SOFT_RESET_GUI);
- temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL);
-
- OUTPLL(mmio, R128_REG_MCLK_CNTL, mclkcntl);
- MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, clockcntlindex);
- }
-#ifdef USE_DRI
- if (atis->using_dri) {
- ATIDRIDMAReset(atis);
- ATIDRIDMAStart(atis);
- }
-#endif
-}
-
-static void
-ATIWaitAvailMMIO(ATIScreenInfo *atis, int n)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- TIMEOUT_LOCALS;
-
- if (atis->mmio_avail >= n) {
- atis->mmio_avail -= n;
- return;
- }
- if (atic->is_radeon) {
- WHILE_NOT_TIMEOUT(.2) {
- atis->mmio_avail = MMIO_IN32(mmio,
- RADEON_REG_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
- if (atis->mmio_avail >= n)
- break;
- }
- } else {
- WHILE_NOT_TIMEOUT(.2) {
- atis->mmio_avail = MMIO_IN32(mmio, R128_REG_GUI_STAT) &
- 0xfff;
- if (atis->mmio_avail >= n)
- break;
- }
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout waiting for %d MMIO slots.\n", n);
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
- atis->mmio_avail -= n;
-}
-
-static int
-ATIGetAvailPrimary(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
-
- if (atic->is_radeon) {
- int csq_stat, diff;
-
- csq_stat = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_STAT);
- if (atic->is_r200)
- diff = ((csq_stat & R200_CSQ_WPTR_PRIMARY_MASK) >> 9) -
- (csq_stat & R200_CSQ_RPTR_PRIMARY_MASK);
- else
- diff = ((csq_stat & RADEON_CSQ_WPTR_PRIMARY_MASK) >> 8) -
- (csq_stat & RADEON_CSQ_RPTR_PRIMARY_MASK);
-
- if (diff < 0)
- return -diff;
- else
- return atis->cce_pri_size - diff;
- } else {
- return MMIO_IN32(mmio, R128_REG_PM4_STAT) &
- R128_PM4_FIFOCNT_MASK;
- }
-}
-
-static void
-ATIWaitAvailPrimary(ATIScreenInfo *atis, int n)
-{
- TIMEOUT_LOCALS;
-
- if (atis->cce_pri_avail >= n) {
- atis->cce_pri_avail -= n;
- return;
- }
-
- WHILE_NOT_TIMEOUT(.2) {
- if (atis->cce_pri_avail >= n)
- break;
- atis->cce_pri_avail = ATIGetAvailPrimary(atis);
- if (atis->cce_pri_avail >= n)
- break;
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout waiting for %d CCE slots (%d avail).\n", n,
- atis->cce_pri_avail);
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
- atis->cce_pri_avail -= n;
-}
-
-void
-ATIWaitIdle(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- TIMEOUT_LOCALS;
-
- if (atis->indirectBuffer != NULL)
- ATIFlushIndirect(atis, 0);
-
-#ifdef USE_DRI
- if (atis->using_dri) {
- int ret = 0;
- int cmd = (atic->is_radeon ? DRM_RADEON_CP_IDLE :
- DRM_R128_CCE_IDLE);
- WHILE_NOT_TIMEOUT(2) {
- ret = drmCommandNone(atic->drmFd, cmd);
- if (ret != -EBUSY)
- break;
- }
- if (TIMEDOUT()) {
- ATIDebugFifo(atis);
- FatalError("Timed out idling CCE (card hung)\n");
- }
- if (ret != 0)
- ErrorF("Failed to idle DMA, returned %d\n", ret);
- return;
- }
-#endif
-
- if (!atic->is_radeon && (atis->using_pseudo || atis->using_dma)) {
- ATIWaitAvailPrimary(atis, atis->cce_pri_size);
-
- WHILE_NOT_TIMEOUT(.2) {
- if ((MMIO_IN32(mmio, R128_REG_PM4_STAT) &
- (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)) == 0)
- break;
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout idling CCE, resetting...\n");
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
- }
-
- /* Radeon CP idle is the same as MMIO idle. */
- if (atis->using_pio || atic->is_radeon) {
- /* Empty the fifo */
- ATIWaitAvailMMIO(atis, 64);
-
- if (atic->is_radeon) {
- WHILE_NOT_TIMEOUT(.2) {
- if ((MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) &
- RADEON_RBBM_ACTIVE) == 0)
- break;
- }
- } else {
- WHILE_NOT_TIMEOUT(.2) {
- if ((MMIO_IN32(mmio, R128_REG_GUI_STAT) &
- R128_GUI_ACTIVE) == 0)
- break;
- }
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout idling accelerator, resetting...\n");
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
- }
-
- ATIFlushPixelCache(atis);
-
-#if DEBUG_FIFO
- ErrorF("Idle?\n");
- ATIDebugFifo(atis);
-#endif
-}
-
-dmaBuf *
-ATIGetDMABuffer(ATIScreenInfo *atis)
-{
- dmaBuf *buf;
-
- buf = (dmaBuf *)xalloc(sizeof(dmaBuf));
- if (buf == NULL)
- return NULL;
-
-#ifdef USE_DRI
- if (atis->using_dri) {
- buf->drmBuf = ATIDRIGetBuffer(atis);
- if (buf->drmBuf == NULL) {
- xfree(buf);
- return NULL;
- }
- buf->size = buf->drmBuf->total;
- buf->used = buf->drmBuf->used;
- buf->address = buf->drmBuf->address;
- return buf;
- }
-#endif /* USE_DRI */
-
- if (atis->using_dma)
- buf->size = atis->ring_len / 2;
- else
- buf->size = 512 * 1024;
- buf->address = xalloc(buf->size);
- if (buf->address == NULL) {
- xfree(buf);
- return NULL;
- }
- buf->used = 0;
-
- return buf;
-}
-
-/* Decode a type-3 packet into MMIO register writes. Only some type-3 packets
- * supported, and only partially.
- */
-static void
-ATIDispatchPacket3MMIO(ATIScreenInfo *atis, CARD32 header, CARD32 *addr,
- int count)
-{
- ATICardInfo *atic = atis->atic;
- char *mmio = atic->reg_base;
- CARD32 settings;
- int i = 0;
-
- settings = addr[i++];
-
- if ((settings & ATI_GMC_SRC_PITCH_OFFSET_CNTL) != 0)
- MMIO_OUT32(mmio, ATI_REG_SRC_PITCH_OFFSET, addr[i++]);
- if ((settings & ATI_GMC_DST_PITCH_OFFSET_CNTL) != 0)
- MMIO_OUT32(mmio, ATI_REG_DST_PITCH_OFFSET, addr[i++]);
- if ((settings & ATI_GMC_BRUSH_MASK) == ATI_GMC_BRUSH_SOLID_COLOR)
- MMIO_OUT32(mmio, ATI_REG_DP_BRUSH_FRGD_CLR, addr[i++]);
-
- switch (header & (ATI_CCE_PACKETTYPE_MASK |
- ATI_CCE_PACKET3_IT_OPCODE_MASK))
- {
- case ATI_CCE_PACKET3_PAINT_MULTI:
- while (i < count) {
- MMIO_OUT32(mmio, ATI_REG_DST_Y_X,
- (addr[i] >> 16) | (addr[i] << 16));
- i++;
- MMIO_OUT32(mmio, ATI_REG_DST_HEIGHT_WIDTH,
- (addr[i] >> 16) | (addr[i] << 16));
- i++;
- }
- break;
- case ATI_CCE_PACKET3_BITBLT_MULTI:
- while (i < count) {
- MMIO_OUT32(mmio, ATI_REG_SRC_Y_X,
- (addr[i] >> 16) | (addr[i] << 16));
- i++;
- MMIO_OUT32(mmio, ATI_REG_DST_Y_X,
- (addr[i] >> 16) | (addr[i] << 16));
- i++;
- MMIO_OUT32(mmio, ATI_REG_DST_HEIGHT_WIDTH,
- (addr[i] >> 16) | (addr[i] << 16));
- i++;
- }
- break;
- default:
- ErrorF("Unsupported packet: 0x%x\n", header);
- }
-}
-
-/* Dispatch packets by decoding them and writing to registers. Doesn't support
- * the type 3 packets.
- */
-static void
-ATIDispatchIndirectMMIO(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- dmaBuf *buf = atis->indirectBuffer;
- char *mmio = atic->reg_base;
- CARD32 *addr;
- CARD32 reg;
- int i, n, count;
-
- addr = (CARD32 *)((char *)buf->address + atis->indirectStart);
- count = (buf->used - atis->indirectStart) / 4;
-
- for (i = 0; i < count; i++) {
- CARD32 header = addr[i];
-
- switch (header & ATI_CCE_PACKETTYPE_MASK)
- {
- case ATI_CCE_PACKET0:
- n = ((header & ATI_CCE_PACKET0_COUNT_MASK) >> 16) + 1;
- reg = (header & ATI_CCE_PACKET0_REG_MASK) << 2;
- ATIWaitAvailMMIO(atis, n);
- while (n > 0) {
- i++;
- MMIO_OUT32(mmio, reg, addr[i]);
- if ((header & ATI_CCE_PACKET0_ONE_REG_WR) == 0)
- reg += 4;
- n--;
- }
- break;
- case ATI_CCE_PACKET1:
- reg = (header & ATI_CCE_PACKET1_REG_1) << 2;
- MMIO_OUT32(mmio, reg, addr[++i]);
- reg = ((header & ATI_CCE_PACKET1_REG_2) >>
- ATI_CCE_PACKET1_REG_2_SHIFT) << 2;
- MMIO_OUT32(mmio, reg, addr[++i]);
- break;
- case ATI_CCE_PACKET2:
- /* PACKET2 is a no-op packet. */
- break;
- case ATI_CCE_PACKET3:
- n = ((header & ATI_CCE_PACKET3_COUNT_MASK) >> 16) + 1;
- ATIDispatchPacket3MMIO(atis, header, &addr[i], n);
- i += n;
- break;
- default:
- ErrorF("Unsupported packet: 0x%x\n", addr[i]);
- }
- }
-}
-
-/* Dispatch packets by sending them through the MMIO aperture. */
-static void
-R128DispatchIndirectPDMA(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- dmaBuf *buf = atis->indirectBuffer;
- char *mmio = atic->reg_base;
- CARD32 *addr;
- int count;
-
- addr = (CARD32 *)((char *)buf->address + atis->indirectStart);
- count = (buf->used - atis->indirectStart) / 4;
-
- while (count > 1) {
- ATIWaitAvailPrimary(atis, 2);
- MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_EVEN, *addr++);
- MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_ODD, *addr++);
- count -= 2;
- }
-
- /* Submit last DWORD if necessary. */
- if (count != 0) {
- ATIWaitAvailPrimary(atis, 2);
- MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_EVEN, *addr++);
- MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_ODD, ATI_CCE_PACKET2);
- }
-}
-
-/* Dispatch packets by sending them through the MMIO aperture, using the
- * primary CCE ring. */
-static void
-RadeonDispatchIndirectPDMA(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- dmaBuf *buf = atis->indirectBuffer;
- char *mmio = atic->reg_base;
- CARD32 *addr;
- int count, avail, reg, i;
- TIMEOUT_LOCALS;
-
- addr = (CARD32 *)((char *)buf->address + atis->indirectStart);
- count = (buf->used - atis->indirectStart) / 4;
-
- reg = RADEON_REG_CSQ_APER_PRIMARY;
- WHILE_NOT_TIMEOUT(3) {
- /* 3 seconds is empirical, using render_bench on an r100. */
- if (count <= 0)
- break;
- avail = ATIGetAvailPrimary(atis);
- for (i = 0; i < min(count, avail); i++) {
- MMIO_OUT32(mmio, reg, *addr++);
- if (reg == RADEON_REG_CSQ_APER_PRIMARY_END)
- reg = RADEON_REG_CSQ_APER_PRIMARY;
- else
- reg += 4;
- }
- count -= i;
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout submitting packets, resetting...\n");
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
-}
-
-
-/* Dispatch packets by writing them to the (primary) ring buffer, which happens
- * to be in framebuffer memory.
- */
-static void
-R128DispatchIndirectDMA(ATIScreenInfo *atis)
-{
- ATICardInfo *atic = atis->atic;
- dmaBuf *buf = atis->indirectBuffer;
- char *mmio = atic->reg_base;
- CARD32 *addr;
- int count, ring_count;
- TIMEOUT_LOCALS;
-
- addr = (CARD32 *)((char *)buf->address + atis->indirectStart);
- count = (buf->used - atis->indirectStart) / 4;
- ring_count = atis->ring_len / 4;
-
- WHILE_NOT_TIMEOUT(.2) {
- if (count <= 0)
- break;
-
- atis->ring_addr[atis->ring_write++] = *addr++;
- if (atis->ring_write >= ring_count)
- atis->ring_write = 0;
- while (atis->ring_write == atis->ring_read) {
- atis->ring_read = MMIO_IN32(mmio, ATI_REG_CCE_RPTR);
- }
- count--;
- }
- if (TIMEDOUT()) {
- ErrorF("Timeout submitting packets, resetting...\n");
- ATIEngineReset(atis);
- ATIDrawSetup(atis->screen->pScreen);
- }
-
- /* Workaround for some early Rage 128 ASIC spins where the CCE parser
- * may read up to 32 DWORDS beyond the end of the ring buffer memory
- * before wrapping around, if the ring buffer was empty and a <32 DWORD
- * packet that wraps around the end of the ring buffer is submitted.
- * To work around that, copy the beginning of the ring buffer past the
- * end if that may happen.
- */
- if (atis->ring_write < 32)
- memcpy(atis->ring_addr + ring_count, atis->ring_addr, 32 * 4);
-
- /* Update write pointer */
- MMIO_OUT32(mmio, ATI_REG_CCE_WPTR, atis->ring_write);
-}
-
-void
-ATIFlushIndirect(ATIScreenInfo *atis, Bool discard)
-{
- ATICardInfo *atic = atis->atic;
- dmaBuf *buf = atis->indirectBuffer;
-
- if ((atis->indirectStart == buf->used) && !discard)
- return;
-
-#if DEBUG_FIFO
- ErrorF("Dispatching %d DWORDS\n", (buf->used - atis->indirectStart) /
- 4);
-#endif
-
-#ifdef USE_DRI
- if (atis->using_dri) {
- buf->drmBuf->used = buf->used;
- ATIDRIDispatchIndirect(atis, discard);
- if (discard) {
- buf->drmBuf = ATIDRIGetBuffer(atis);
- buf->size = buf->drmBuf->total;
- buf->used = buf->drmBuf->used;
- buf->address = buf->drmBuf->address;
- atis->indirectStart = 0;
- } else {
- /* Start on a double word boundary */
- atis->indirectStart = buf->used = (buf->used + 7) & ~7;
- }
- return;
- }
-#endif /* USE_DRI */
-
- if (atis->using_dma && !atic->is_radeon)
- R128DispatchIndirectDMA(atis);
- else if (atis->using_pseudo) {
- if (atic->is_radeon)
- RadeonDispatchIndirectPDMA(atis);
- else
- R128DispatchIndirectPDMA(atis);
- } else
- ATIDispatchIndirectMMIO(atis);
-
- buf->used = 0;
- atis->indirectStart = 0;
-}
-
-static Bool
-ATIInitAGP(ScreenPtr pScreen, int size)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- ATICardInfo(pScreenPriv);
- AgpInfoPtr agp_info;
- int screennum = atis->screen->mynum;
-
- if (atic->is_radeon)
- return FALSE;
-
- if (!KdAgpGARTSupported())
- return FALSE;
-
- if (!KdAcquireGART(screennum))
- return FALSE;
-
- atis->agp_key = KdAllocateGARTMemory(screennum, size, 0, NULL);
- if (atis->agp_key == -1) {
- ErrorF("Failed to allocate %dKB GART memory\n", size/1024);
- KdReleaseGART(screennum);
- return FALSE;
- }
-
- if (!KdBindGARTMemory(screennum, atis->agp_key, 0)) {
- ErrorF("Failed to bind GART memory\n");
- KdReleaseGART(screennum);
- return FALSE;
- }
-
- agp_info = KdGetAGPInfo(screennum);
- if (agp_info == NULL) {
- KdUnbindGARTMemory(screennum, atis->agp_key);
- KdReleaseGART(screennum);
- return FALSE;
- }
-
- atis->agp_addr = KdMapDevice(agp_info->base, agp_info->size);
- if (atis->agp_addr == NULL) {
- ErrorF("Failed to map GART memory\n");
- KdUnbindGARTMemory(screennum, atis->agp_key);
- KdReleaseGART(screennum);
- free(agp_info);
- return FALSE;
- }
- KdSetMappedMode(agp_info->base, agp_info->size,
- KD_MAPPED_MODE_FRAMEBUFFER);
-
- atis->agp_size = size;
- free(agp_info);
-
- return TRUE;
-}
-
-static void
-ATIFiniAGP(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- int screennum = atis->screen->mynum;
-
- KdUnbindGARTMemory(screennum, atis->agp_key);
- KdReleaseGART(screennum);
- atis->agp_addr = NULL;
- atis->agp_size = 0;
-}
-
-static Bool
-ATIPseudoDMAInit(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- ATICardInfo(pScreenPriv);
- char *mmio = atic->reg_base;
-
- if (atic->is_r300)
- return FALSE;
-
- ATIUploadMicrocode(atis);
- ATIEngineReset(atis);
-
- if (atic->is_r200) {
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIPIO_INDDIS);
- atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) &
- R200_CSQ_CNT_PRIMARY_MASK;
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN);
- } if (atic->is_radeon) {
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIPIO_INDDIS);
- atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) &
- RADEON_CSQ_CNT_PRIMARY_MASK;
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN);
- } else {
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, R128_PM4_192PIO |
- R128_PM4_BUFFER_CNTL_NOUPDATE);
- atis->cce_pri_size = 192;
- MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL,
- R128_PM4_MICRO_FREERUN);
- }
-
- return TRUE;
-}
-
-static Bool
-ATIPseudoDMAFini(ScreenPtr pScreen)
-{ KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- ATICardInfo(pScreenPriv);
- char *mmio = atic->reg_base;
-
- if (atic->is_radeon) {
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, 0);
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIDIS_INDDIS);
- } else {
- MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, 0);
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL,
- R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
- }
- atis->cce_pri_size = 0;
-
- ATIEngineReset(atis);
-
- return TRUE;
-}
-
-static Bool
-ATIDMAInit(ScreenPtr pScreen, Bool use_agp)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- ATICardInfo(pScreenPriv);
- char *mmio = atic->reg_base;
- int dma_offset;
- CARD32 tmp;
-
- /* XXX: Not for radeons. Yet? */
- if (atic->is_radeon)
- return FALSE;
-
- if (use_agp) {
- if (1)
- return FALSE; /* XXX */
- /* Allocate a 1MB AGP space, but only use 128k + 128 for DMA.
- * XXX: Should use the rest for things like scratch space.
- */
- if (!ATIInitAGP(pScreen, 1024 * 1024))
- return FALSE;
- atis->ring_addr = atis->agp_addr;
- atis->ring_len = 128 * 1024;
- dma_offset = R128_AGP_OFFSET;
- } else {
- if (1)
- return FALSE; /* XXX */
- /* Allocate a 128K buffer, plus 32 DWORDS to give space for the
- * R128 ASIC bug workaround.
- */
- atis->dma_space = KdOffscreenAlloc(pScreen, 128 * 1024 + 128,
- 128, TRUE, NULL, NULL);
- if (atis->dma_space == NULL)
- return FALSE;
- atis->ring_addr = (CARD32 *)(atis->dma_space->offset +
- pScreenPriv->screen->memory_base);
- atis->ring_len = 128 * 1024;
- dma_offset = atis->dma_space->offset;
- }
-
- ATIUploadMicrocode(atis);
- ATIEngineReset(atis);
-
- atis->ring_read = 0;
- atis->ring_write = 0;
-
- tmp = MMIO_IN32(mmio, ATI_REG_BUS_CNTL);
- MMIO_OUT32(mmio, ATI_REG_BUS_CNTL, tmp & ~ATI_BUS_MASTER_DIS);
-
- MMIO_OUT32(mmio, ATI_REG_CCE_RB_BASE, dma_offset);
- MMIO_OUT32(mmio, ATI_REG_CCE_WPTR, atis->ring_write);
- MMIO_OUT32(mmio, ATI_REG_CCE_RPTR, atis->ring_read);
- MMIO_OUT32(mmio, ATI_REG_CCE_RPTR_ADDR, 0 /* XXX? */);
-
- if (atic->is_r200) {
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIBM_INDBM);
- atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) &
- R200_CSQ_CNT_PRIMARY_MASK;
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN);
- } else if (atic->is_radeon) {
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIBM_INDBM);
- atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) &
- RADEON_CSQ_CNT_PRIMARY_MASK;
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN);
- } else {
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_WM_CNTL,
- ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) |
- ((R128_WATERMARK_M/4) << R128_WMB_SHIFT) |
- ((R128_WATERMARK_N/4) << R128_WMC_SHIFT) |
- ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT));
- /* The sample code reads from an undocumneted register
- * (PM4_BUFFER_ADDR). Perhaps it's a write posting thing? Do
- * a read in case that's it.
- */
- MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL);
- if (use_agp) {
- /* XXX Magic num */
- MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 1);
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL,
- ATILog2(atis->ring_len) |
- R128_PM4_192BM |
- R128_PM4_BUFFER_CNTL_NOUPDATE);
- } else {
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL,
- ATILog2(atis->ring_len) |
- R128_PM4_192BM |
- R128_PM4_BUFFER_CNTL_NOUPDATE |
- R128_PM4_IN_FRAME_BUFFER);
- }
- atis->cce_pri_size = 192;
- MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL);
- MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL,
- R128_PM4_MICRO_FREERUN);
- }
-
- return TRUE;
-}
-
-static Bool
-ATIDMAFini(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
- ATICardInfo(pScreenPriv);
- char *mmio = atic->reg_base;
-
- if (atic->is_radeon) {
- MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, 0);
- MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL,
- RADEON_CSQ_PRIDIS_INDDIS);
- } else {
- MMIO_OUT32(mmio, ATI_REG_CCE_WPTR,
- atis->ring_write | R128_PM4_BUFFER_DL_DONE);
- MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, 0);
- MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL,
- R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
- }
- atis->cce_pri_size = 0;
-
- ATIEngineReset(atis);
-
- if (atis->using_agp)
- ATIFiniAGP(pScreen);
- else
- KdOffscreenFree(pScreen, atis->dma_space);
-
- return TRUE;
-}
-
-void
-ATIDMASetup(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ATICardInfo(pScreenPriv);
- ATIScreenInfo(pScreenPriv);
-
-#ifdef USE_DRI
- if (atis->using_dri)
- ATIDRIDMAStart(atis);
-#endif /* USE_DRI */
-
- if (!atis->using_dri) {
- atis->using_agp = FALSE;
- if (atic->is_agp && ATIDMAInit(pScreen, TRUE)) {
- atis->using_agp = TRUE;
- atis->using_dma = TRUE;
- } else if (ATIDMAInit(pScreen, FALSE)) {
- atis->using_agp = FALSE;
- atis->using_dma = TRUE;
- } else if (ATIPseudoDMAInit(pScreen))
- atis->using_pseudo = TRUE;
- else
- atis->using_pio = TRUE;
- }
-
- atis->indirectBuffer = ATIGetDMABuffer(atis);
- if (atis->indirectBuffer == FALSE)
- FatalError("Failed to allocate DMA buffer.\n");
-
- if (atis->using_dri)
- ErrorF("Initialized %s DRI DMA\n",
- atis->using_agp ? "AGP" : "PCI");
- else if (atis->using_dma && atis->using_agp)
- ErrorF("Initialized AGP DMA\n");
- else if (atis->using_dma)
- ErrorF("Initialized framebuffer pseudo-DMA\n");
- else if (atis->using_pseudo)
- ErrorF("Initialized pseudo-DMA\n");
- else if (atis->using_pio)
- ErrorF("Initialized PIO\n");
-}
-
-void
-ATIDMATeardown(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ATIScreenInfo(pScreenPriv);
-
- ATIWaitIdle(atis);
-
-#ifdef USE_DRI
- if (atis->using_dri)
- ATIDRIDMAStop(atis);
-#endif /* USE_DRI */
-
- if (atis->using_dma)
- ATIDMAFini(pScreen);
-
- if (atis->using_pseudo)
- ATIPseudoDMAFini(pScreen);
-
- if (atis->using_pio || atis->using_pseudo || atis->using_dma) {
- xfree(atis->indirectBuffer->address);
- xfree(atis->indirectBuffer);
- }
- atis->indirectBuffer = NULL;
-
- atis->using_pio = FALSE;
- atis->using_pseudo = FALSE;
- atis->using_dma = FALSE;
- atis->using_agp = FALSE;
-}
-