195584Sanholt/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- 2152909Sanholt * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com 3152909Sanholt */ 4139749Simp/*- 595584Sanholt * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. 695584Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 795584Sanholt * All Rights Reserved. 895584Sanholt * 995584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 1095584Sanholt * copy of this software and associated documentation files (the "Software"), 1195584Sanholt * to deal in the Software without restriction, including without limitation 1295584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1395584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1495584Sanholt * Software is furnished to do so, subject to the following conditions: 1595584Sanholt * 1695584Sanholt * The above copyright notice and this permission notice (including the next 1795584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1895584Sanholt * Software. 1995584Sanholt * 2095584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2195584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2295584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2395584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2495584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2595584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2695584Sanholt * DEALINGS IN THE SOFTWARE. 2795584Sanholt * 2895584Sanholt * Authors: 2995584Sanholt * Gareth Hughes <gareth@valinux.com> 3095584Sanholt */ 3195584Sanholt 32152909Sanholt#include <sys/cdefs.h> 33152909Sanholt__FBSDID("$FreeBSD$"); 34152909Sanholt 3595584Sanholt#include "dev/drm/drmP.h" 36112015Sanholt#include "dev/drm/drm.h" 3795746Sanholt#include "dev/drm/r128_drm.h" 3895584Sanholt#include "dev/drm/r128_drv.h" 3995584Sanholt 4095584Sanholt#define R128_FIFO_DEBUG 0 4195584Sanholt 4295584Sanholt/* CCE microcode (from ATI) */ 4395584Sanholtstatic u32 r128_cce_microcode[] = { 4495584Sanholt 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 4595584Sanholt 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 4695584Sanholt 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, 4795584Sanholt 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, 4895584Sanholt 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, 4995584Sanholt 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 5095584Sanholt 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 5195584Sanholt 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 5295584Sanholt 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, 5395584Sanholt 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, 5495584Sanholt 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, 5595584Sanholt 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, 5695584Sanholt 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 5795584Sanholt 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 5895584Sanholt 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, 5995584Sanholt 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, 6095584Sanholt 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, 6195584Sanholt 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, 6295584Sanholt 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, 6395584Sanholt 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 6495584Sanholt 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 6595584Sanholt 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, 6695584Sanholt 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, 6795584Sanholt 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, 6895584Sanholt 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, 6995584Sanholt 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, 7095584Sanholt 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 7195584Sanholt 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 7295584Sanholt 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, 7395584Sanholt 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, 7495584Sanholt 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, 7595584Sanholt 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, 7695584Sanholt 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 7795584Sanholt 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 7895584Sanholt 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7995584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8095584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8195584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8295584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8395584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8495584Sanholt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8595584Sanholt}; 8695584Sanholt 87182080Srnolandstatic int R128_READ_PLL(struct drm_device * dev, int addr) 8895584Sanholt{ 8995584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 9095584Sanholt 9195584Sanholt R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); 9295584Sanholt return R128_READ(R128_CLOCK_CNTL_DATA); 9395584Sanholt} 9495584Sanholt 9595584Sanholt#if R128_FIFO_DEBUG 96145132Sanholtstatic void r128_status(drm_r128_private_t * dev_priv) 9795584Sanholt{ 98145132Sanholt printk("GUI_STAT = 0x%08x\n", 99145132Sanholt (unsigned int)R128_READ(R128_GUI_STAT)); 100145132Sanholt printk("PM4_STAT = 0x%08x\n", 101145132Sanholt (unsigned int)R128_READ(R128_PM4_STAT)); 102145132Sanholt printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", 103145132Sanholt (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); 104145132Sanholt printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", 105145132Sanholt (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); 106145132Sanholt printk("PM4_MICRO_CNTL = 0x%08x\n", 107145132Sanholt (unsigned int)R128_READ(R128_PM4_MICRO_CNTL)); 108145132Sanholt printk("PM4_BUFFER_CNTL = 0x%08x\n", 109145132Sanholt (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL)); 11095584Sanholt} 11195584Sanholt#endif 11295584Sanholt 11395584Sanholt/* ================================================================ 11495584Sanholt * Engine, FIFO control 11595584Sanholt */ 11695584Sanholt 117145132Sanholtstatic int r128_do_pixcache_flush(drm_r128_private_t * dev_priv) 11895584Sanholt{ 11995584Sanholt u32 tmp; 12095584Sanholt int i; 12195584Sanholt 122145132Sanholt tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; 123145132Sanholt R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); 12495584Sanholt 125145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 126145132Sanholt if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) { 12795584Sanholt return 0; 12895584Sanholt } 129145132Sanholt DRM_UDELAY(1); 13095584Sanholt } 13195584Sanholt 13295584Sanholt#if R128_FIFO_DEBUG 133145132Sanholt DRM_ERROR("failed!\n"); 13495584Sanholt#endif 135182080Srnoland return -EBUSY; 13695584Sanholt} 13795584Sanholt 138145132Sanholtstatic int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries) 13995584Sanholt{ 14095584Sanholt int i; 14195584Sanholt 142145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 143145132Sanholt int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; 144145132Sanholt if (slots >= entries) 145145132Sanholt return 0; 146145132Sanholt DRM_UDELAY(1); 14795584Sanholt } 14895584Sanholt 14995584Sanholt#if R128_FIFO_DEBUG 150145132Sanholt DRM_ERROR("failed!\n"); 15195584Sanholt#endif 152182080Srnoland return -EBUSY; 15395584Sanholt} 15495584Sanholt 155145132Sanholtstatic int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) 15695584Sanholt{ 15795584Sanholt int i, ret; 15895584Sanholt 159145132Sanholt ret = r128_do_wait_for_fifo(dev_priv, 64); 160145132Sanholt if (ret) 161145132Sanholt return ret; 16295584Sanholt 163145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 164145132Sanholt if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { 165145132Sanholt r128_do_pixcache_flush(dev_priv); 16695584Sanholt return 0; 16795584Sanholt } 168145132Sanholt DRM_UDELAY(1); 16995584Sanholt } 17095584Sanholt 17195584Sanholt#if R128_FIFO_DEBUG 172145132Sanholt DRM_ERROR("failed!\n"); 17395584Sanholt#endif 174182080Srnoland return -EBUSY; 17595584Sanholt} 17695584Sanholt 17795584Sanholt/* ================================================================ 17895584Sanholt * CCE control, initialization 17995584Sanholt */ 18095584Sanholt 18195584Sanholt/* Load the microcode for the CCE */ 182145132Sanholtstatic void r128_cce_load_microcode(drm_r128_private_t * dev_priv) 18395584Sanholt{ 18495584Sanholt int i; 18595584Sanholt 186145132Sanholt DRM_DEBUG("\n"); 18795584Sanholt 188145132Sanholt r128_do_wait_for_idle(dev_priv); 18995584Sanholt 190145132Sanholt R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); 191145132Sanholt for (i = 0; i < 256; i++) { 192145132Sanholt R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]); 193145132Sanholt R128_WRITE(R128_PM4_MICROCODE_DATAL, 194145132Sanholt r128_cce_microcode[i * 2 + 1]); 19595584Sanholt } 19695584Sanholt} 19795584Sanholt 19895584Sanholt/* Flush any pending commands to the CCE. This should only be used just 19995584Sanholt * prior to a wait for idle, as it informs the engine that the command 20095584Sanholt * stream is ending. 20195584Sanholt */ 202145132Sanholtstatic void r128_do_cce_flush(drm_r128_private_t * dev_priv) 20395584Sanholt{ 20495584Sanholt u32 tmp; 20595584Sanholt 206145132Sanholt tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE; 207145132Sanholt R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp); 20895584Sanholt} 20995584Sanholt 21095584Sanholt/* Wait for the CCE to go idle. 21195584Sanholt */ 212145132Sanholtint r128_do_cce_idle(drm_r128_private_t * dev_priv) 21395584Sanholt{ 21495584Sanholt int i; 21595584Sanholt 216145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 217145132Sanholt if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) { 218145132Sanholt int pm4stat = R128_READ(R128_PM4_STAT); 219145132Sanholt if (((pm4stat & R128_PM4_FIFOCNT_MASK) >= 220145132Sanholt dev_priv->cce_fifo_size) && 221145132Sanholt !(pm4stat & (R128_PM4_BUSY | 222145132Sanholt R128_PM4_GUI_ACTIVE))) { 223145132Sanholt return r128_do_pixcache_flush(dev_priv); 22495584Sanholt } 22595584Sanholt } 226145132Sanholt DRM_UDELAY(1); 22795584Sanholt } 22895584Sanholt 22995584Sanholt#if R128_FIFO_DEBUG 230145132Sanholt DRM_ERROR("failed!\n"); 231145132Sanholt r128_status(dev_priv); 23295584Sanholt#endif 233182080Srnoland return -EBUSY; 23495584Sanholt} 23595584Sanholt 23695584Sanholt/* Start the Concurrent Command Engine. 23795584Sanholt */ 238145132Sanholtstatic void r128_do_cce_start(drm_r128_private_t * dev_priv) 23995584Sanholt{ 240145132Sanholt r128_do_wait_for_idle(dev_priv); 24195584Sanholt 242145132Sanholt R128_WRITE(R128_PM4_BUFFER_CNTL, 243145132Sanholt dev_priv->cce_mode | dev_priv->ring.size_l2qw 244145132Sanholt | R128_PM4_BUFFER_CNTL_NOUPDATE); 245145132Sanholt R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ 246145132Sanholt R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); 24795584Sanholt 24895584Sanholt dev_priv->cce_running = 1; 24995584Sanholt} 25095584Sanholt 25195584Sanholt/* Reset the Concurrent Command Engine. This will not flush any pending 25295584Sanholt * commands, so you must wait for the CCE command stream to complete 25395584Sanholt * before calling this routine. 25495584Sanholt */ 255145132Sanholtstatic void r128_do_cce_reset(drm_r128_private_t * dev_priv) 25695584Sanholt{ 257145132Sanholt R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); 258145132Sanholt R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); 25995584Sanholt dev_priv->ring.tail = 0; 26095584Sanholt} 26195584Sanholt 26295584Sanholt/* Stop the Concurrent Command Engine. This will not flush any pending 26395584Sanholt * commands, so you must flush the command stream and wait for the CCE 26495584Sanholt * to go idle before calling this routine. 26595584Sanholt */ 266145132Sanholtstatic void r128_do_cce_stop(drm_r128_private_t * dev_priv) 26795584Sanholt{ 268145132Sanholt R128_WRITE(R128_PM4_MICRO_CNTL, 0); 269145132Sanholt R128_WRITE(R128_PM4_BUFFER_CNTL, 270145132Sanholt R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); 27195584Sanholt 27295584Sanholt dev_priv->cce_running = 0; 27395584Sanholt} 27495584Sanholt 27595584Sanholt/* Reset the engine. This will stop the CCE if it is running. 27695584Sanholt */ 277182080Srnolandstatic int r128_do_engine_reset(struct drm_device * dev) 27895584Sanholt{ 27995584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 28095584Sanholt u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; 28195584Sanholt 282145132Sanholt r128_do_pixcache_flush(dev_priv); 28395584Sanholt 284145132Sanholt clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); 285145132Sanholt mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); 28695584Sanholt 287145132Sanholt R128_WRITE_PLL(R128_MCLK_CNTL, 288145132Sanholt mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); 28995584Sanholt 290145132Sanholt gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); 29195584Sanholt 29295584Sanholt /* Taken from the sample code - do not change */ 293145132Sanholt R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); 294145132Sanholt R128_READ(R128_GEN_RESET_CNTL); 295145132Sanholt R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); 296145132Sanholt R128_READ(R128_GEN_RESET_CNTL); 29795584Sanholt 298145132Sanholt R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); 299145132Sanholt R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); 300145132Sanholt R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); 30195584Sanholt 30295584Sanholt /* Reset the CCE ring */ 303145132Sanholt r128_do_cce_reset(dev_priv); 30495584Sanholt 30595584Sanholt /* The CCE is no longer running after an engine reset */ 30695584Sanholt dev_priv->cce_running = 0; 30795584Sanholt 30895584Sanholt /* Reset any pending vertex, indirect buffers */ 309145132Sanholt r128_freelist_reset(dev); 31095584Sanholt 31195584Sanholt return 0; 31295584Sanholt} 31395584Sanholt 314182080Srnolandstatic void r128_cce_init_ring_buffer(struct drm_device * dev, 315145132Sanholt drm_r128_private_t * dev_priv) 31695584Sanholt{ 31795584Sanholt u32 ring_start; 31895584Sanholt u32 tmp; 31995584Sanholt 320145132Sanholt DRM_DEBUG("\n"); 32195584Sanholt 32295584Sanholt /* The manual (p. 2) says this address is in "VM space". This 32395584Sanholt * means it's an offset from the start of AGP space. 32495584Sanholt */ 325145132Sanholt#if __OS_HAS_AGP 326145132Sanholt if (!dev_priv->is_pci) 32795584Sanholt ring_start = dev_priv->cce_ring->offset - dev->agp->base; 32895584Sanholt else 32995584Sanholt#endif 330207067Srnoland ring_start = dev_priv->cce_ring->offset - dev->sg->vaddr; 33195584Sanholt 332145132Sanholt R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET); 33395584Sanholt 334145132Sanholt R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); 335145132Sanholt R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); 33695584Sanholt 33795584Sanholt /* Set watermark control */ 338145132Sanholt R128_WRITE(R128_PM4_BUFFER_WM_CNTL, 339145132Sanholt ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT) 340145132Sanholt | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT) 341145132Sanholt | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT) 342145132Sanholt | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT)); 34395584Sanholt 34495584Sanholt /* Force read. Why? Because it's in the examples... */ 345145132Sanholt R128_READ(R128_PM4_BUFFER_ADDR); 34695584Sanholt 34795584Sanholt /* Turn on bus mastering */ 348145132Sanholt tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS; 349145132Sanholt R128_WRITE(R128_BUS_CNTL, tmp); 35095584Sanholt} 35195584Sanholt 352182080Srnolandstatic int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) 35395584Sanholt{ 35495584Sanholt drm_r128_private_t *dev_priv; 35595584Sanholt 356145132Sanholt DRM_DEBUG("\n"); 35795584Sanholt 358145132Sanholt dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); 359145132Sanholt if (dev_priv == NULL) 360182080Srnoland return -ENOMEM; 36195584Sanholt 362145132Sanholt memset(dev_priv, 0, sizeof(drm_r128_private_t)); 36395584Sanholt 36495584Sanholt dev_priv->is_pci = init->is_pci; 36595584Sanholt 366145132Sanholt if (dev_priv->is_pci && !dev->sg) { 367145132Sanholt DRM_ERROR("PCI GART memory not allocated!\n"); 36895584Sanholt dev->dev_private = (void *)dev_priv; 369145132Sanholt r128_do_cleanup_cce(dev); 370182080Srnoland return -EINVAL; 37195584Sanholt } 37295584Sanholt 37395584Sanholt dev_priv->usec_timeout = init->usec_timeout; 374145132Sanholt if (dev_priv->usec_timeout < 1 || 375145132Sanholt dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { 376145132Sanholt DRM_DEBUG("TIMEOUT problem!\n"); 37795584Sanholt dev->dev_private = (void *)dev_priv; 378145132Sanholt r128_do_cleanup_cce(dev); 379182080Srnoland return -EINVAL; 38095584Sanholt } 38195584Sanholt 38295584Sanholt dev_priv->cce_mode = init->cce_mode; 38395584Sanholt 38495584Sanholt /* GH: Simple idle check. 38595584Sanholt */ 386145132Sanholt atomic_set(&dev_priv->idle_count, 0); 38795584Sanholt 38895584Sanholt /* We don't support anything other than bus-mastering ring mode, 38995584Sanholt * but the ring can be in either AGP or PCI space for the ring 39095584Sanholt * read pointer. 39195584Sanholt */ 392145132Sanholt if ((init->cce_mode != R128_PM4_192BM) && 393145132Sanholt (init->cce_mode != R128_PM4_128BM_64INDBM) && 394145132Sanholt (init->cce_mode != R128_PM4_64BM_128INDBM) && 395145132Sanholt (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) { 396145132Sanholt DRM_DEBUG("Bad cce_mode!\n"); 39795584Sanholt dev->dev_private = (void *)dev_priv; 398145132Sanholt r128_do_cleanup_cce(dev); 399182080Srnoland return -EINVAL; 40095584Sanholt } 40195584Sanholt 402145132Sanholt switch (init->cce_mode) { 40395584Sanholt case R128_PM4_NONPM4: 40495584Sanholt dev_priv->cce_fifo_size = 0; 40595584Sanholt break; 40695584Sanholt case R128_PM4_192PIO: 40795584Sanholt case R128_PM4_192BM: 40895584Sanholt dev_priv->cce_fifo_size = 192; 40995584Sanholt break; 41095584Sanholt case R128_PM4_128PIO_64INDBM: 41195584Sanholt case R128_PM4_128BM_64INDBM: 41295584Sanholt dev_priv->cce_fifo_size = 128; 41395584Sanholt break; 41495584Sanholt case R128_PM4_64PIO_128INDBM: 41595584Sanholt case R128_PM4_64BM_128INDBM: 41695584Sanholt case R128_PM4_64PIO_64VCBM_64INDBM: 41795584Sanholt case R128_PM4_64BM_64VCBM_64INDBM: 41895584Sanholt case R128_PM4_64PIO_64VCPIO_64INDPIO: 41995584Sanholt dev_priv->cce_fifo_size = 64; 42095584Sanholt break; 42195584Sanholt } 42295584Sanholt 423145132Sanholt switch (init->fb_bpp) { 42495584Sanholt case 16: 42595584Sanholt dev_priv->color_fmt = R128_DATATYPE_RGB565; 42695584Sanholt break; 42795584Sanholt case 32: 42895584Sanholt default: 42995584Sanholt dev_priv->color_fmt = R128_DATATYPE_ARGB8888; 43095584Sanholt break; 43195584Sanholt } 432145132Sanholt dev_priv->front_offset = init->front_offset; 433145132Sanholt dev_priv->front_pitch = init->front_pitch; 434145132Sanholt dev_priv->back_offset = init->back_offset; 435145132Sanholt dev_priv->back_pitch = init->back_pitch; 43695584Sanholt 437145132Sanholt switch (init->depth_bpp) { 43895584Sanholt case 16: 43995584Sanholt dev_priv->depth_fmt = R128_DATATYPE_RGB565; 44095584Sanholt break; 44195584Sanholt case 24: 44295584Sanholt case 32: 44395584Sanholt default: 44495584Sanholt dev_priv->depth_fmt = R128_DATATYPE_ARGB8888; 44595584Sanholt break; 44695584Sanholt } 447145132Sanholt dev_priv->depth_offset = init->depth_offset; 448145132Sanholt dev_priv->depth_pitch = init->depth_pitch; 449145132Sanholt dev_priv->span_offset = init->span_offset; 45095584Sanholt 451145132Sanholt dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) | 45295584Sanholt (dev_priv->front_offset >> 5)); 453145132Sanholt dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) | 45495584Sanholt (dev_priv->back_offset >> 5)); 455145132Sanholt dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | 45695584Sanholt (dev_priv->depth_offset >> 5) | 45795584Sanholt R128_DST_TILE); 458145132Sanholt dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | 45995584Sanholt (dev_priv->span_offset >> 5)); 46095584Sanholt 461182080Srnoland dev_priv->sarea = drm_getsarea(dev); 462145132Sanholt if (!dev_priv->sarea) { 46395584Sanholt DRM_ERROR("could not find sarea!\n"); 46495584Sanholt dev->dev_private = (void *)dev_priv; 465145132Sanholt r128_do_cleanup_cce(dev); 466182080Srnoland return -EINVAL; 46795584Sanholt } 46895584Sanholt 469145132Sanholt dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); 470145132Sanholt if (!dev_priv->mmio) { 47195584Sanholt DRM_ERROR("could not find mmio region!\n"); 47295584Sanholt dev->dev_private = (void *)dev_priv; 473145132Sanholt r128_do_cleanup_cce(dev); 474182080Srnoland return -EINVAL; 47595584Sanholt } 476145132Sanholt dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); 477145132Sanholt if (!dev_priv->cce_ring) { 47895584Sanholt DRM_ERROR("could not find cce ring region!\n"); 47995584Sanholt dev->dev_private = (void *)dev_priv; 480145132Sanholt r128_do_cleanup_cce(dev); 481182080Srnoland return -EINVAL; 48295584Sanholt } 483145132Sanholt dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); 484145132Sanholt if (!dev_priv->ring_rptr) { 48595584Sanholt DRM_ERROR("could not find ring read pointer!\n"); 48695584Sanholt dev->dev_private = (void *)dev_priv; 487145132Sanholt r128_do_cleanup_cce(dev); 488182080Srnoland return -EINVAL; 48995584Sanholt } 490152909Sanholt dev->agp_buffer_token = init->buffers_offset; 491145132Sanholt dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); 492145132Sanholt if (!dev->agp_buffer_map) { 49395584Sanholt DRM_ERROR("could not find dma buffer region!\n"); 49495584Sanholt dev->dev_private = (void *)dev_priv; 495145132Sanholt r128_do_cleanup_cce(dev); 496182080Srnoland return -EINVAL; 49795584Sanholt } 49895584Sanholt 499145132Sanholt if (!dev_priv->is_pci) { 500145132Sanholt dev_priv->agp_textures = 501145132Sanholt drm_core_findmap(dev, init->agp_textures_offset); 502145132Sanholt if (!dev_priv->agp_textures) { 50395584Sanholt DRM_ERROR("could not find agp texture region!\n"); 50495584Sanholt dev->dev_private = (void *)dev_priv; 505145132Sanholt r128_do_cleanup_cce(dev); 506182080Srnoland return -EINVAL; 50795584Sanholt } 50895584Sanholt } 50995584Sanholt 51095584Sanholt dev_priv->sarea_priv = 511207066Srnoland (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->virtual + 512145132Sanholt init->sarea_priv_offset); 51395584Sanholt 514145132Sanholt#if __OS_HAS_AGP 515145132Sanholt if (!dev_priv->is_pci) { 516145132Sanholt drm_core_ioremap(dev_priv->cce_ring, dev); 517145132Sanholt drm_core_ioremap(dev_priv->ring_rptr, dev); 518145132Sanholt drm_core_ioremap(dev->agp_buffer_map, dev); 519207066Srnoland if (!dev_priv->cce_ring->virtual || 520207066Srnoland !dev_priv->ring_rptr->virtual || 521207066Srnoland !dev->agp_buffer_map->virtual) { 52295584Sanholt DRM_ERROR("Could not ioremap agp regions!\n"); 52395584Sanholt dev->dev_private = (void *)dev_priv; 524145132Sanholt r128_do_cleanup_cce(dev); 525182080Srnoland return -ENOMEM; 52695584Sanholt } 527119098Sanholt } else 528119098Sanholt#endif 529119098Sanholt { 530207066Srnoland dev_priv->cce_ring->virtual = 531207066Srnoland (void *)dev_priv->cce_ring->offset; 532207066Srnoland dev_priv->ring_rptr->virtual = 533145132Sanholt (void *)dev_priv->ring_rptr->offset; 534207066Srnoland dev->agp_buffer_map->virtual = 535145132Sanholt (void *)dev->agp_buffer_map->offset; 53695584Sanholt } 53795584Sanholt 538145132Sanholt#if __OS_HAS_AGP 539145132Sanholt if (!dev_priv->is_pci) 54095584Sanholt dev_priv->cce_buffers_offset = dev->agp->base; 54195584Sanholt else 54295584Sanholt#endif 543207067Srnoland dev_priv->cce_buffers_offset = dev->sg->vaddr; 54495584Sanholt 545207066Srnoland dev_priv->ring.start = (u32 *) dev_priv->cce_ring->virtual; 546207066Srnoland dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->virtual 54795584Sanholt + init->ring_size / sizeof(u32)); 54895584Sanholt dev_priv->ring.size = init->ring_size; 549145132Sanholt dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); 55095584Sanholt 551145132Sanholt dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; 55295584Sanholt 55395584Sanholt dev_priv->ring.high_mark = 128; 55495584Sanholt 55595584Sanholt dev_priv->sarea_priv->last_frame = 0; 556145132Sanholt R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); 55795584Sanholt 55895584Sanholt dev_priv->sarea_priv->last_dispatch = 0; 559145132Sanholt R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch); 56095584Sanholt 561145132Sanholt#if __OS_HAS_AGP 562145132Sanholt if (dev_priv->is_pci) { 563121447Sanholt#endif 564182080Srnoland dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); 565152909Sanholt dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; 566182080Srnoland dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; 567152909Sanholt dev_priv->gart_info.addr = NULL; 568152909Sanholt dev_priv->gart_info.bus_addr = 0; 569182080Srnoland dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; 570152909Sanholt if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 571145132Sanholt DRM_ERROR("failed to init PCI GART!\n"); 57295584Sanholt dev->dev_private = (void *)dev_priv; 573145132Sanholt r128_do_cleanup_cce(dev); 574182080Srnoland return -ENOMEM; 57595584Sanholt } 576152909Sanholt R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); 577145132Sanholt#if __OS_HAS_AGP 57895584Sanholt } 57995584Sanholt#endif 58095584Sanholt 581145132Sanholt r128_cce_init_ring_buffer(dev, dev_priv); 582145132Sanholt r128_cce_load_microcode(dev_priv); 58395584Sanholt 58495584Sanholt dev->dev_private = (void *)dev_priv; 58595584Sanholt 586145132Sanholt r128_do_engine_reset(dev); 58795584Sanholt 58895584Sanholt return 0; 58995584Sanholt} 59095584Sanholt 591182080Srnolandint r128_do_cleanup_cce(struct drm_device * dev) 59295584Sanholt{ 593119098Sanholt 594119098Sanholt /* Make sure interrupts are disabled here because the uninstall ioctl 595119098Sanholt * may not have been called from userspace and after dev_private 596119098Sanholt * is freed, it's too late. 597119098Sanholt */ 598145132Sanholt if (dev->irq_enabled) 599145132Sanholt drm_irq_uninstall(dev); 600119098Sanholt 601145132Sanholt if (dev->dev_private) { 60295584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 60395584Sanholt 604145132Sanholt#if __OS_HAS_AGP 605145132Sanholt if (!dev_priv->is_pci) { 606145132Sanholt if (dev_priv->cce_ring != NULL) 607145132Sanholt drm_core_ioremapfree(dev_priv->cce_ring, dev); 608145132Sanholt if (dev_priv->ring_rptr != NULL) 609145132Sanholt drm_core_ioremapfree(dev_priv->ring_rptr, dev); 610145132Sanholt if (dev->agp_buffer_map != NULL) { 611145132Sanholt drm_core_ioremapfree(dev->agp_buffer_map, dev); 612145132Sanholt dev->agp_buffer_map = NULL; 613145132Sanholt } 614119098Sanholt } else 615119098Sanholt#endif 616119098Sanholt { 617152909Sanholt if (dev_priv->gart_info.bus_addr) 618152909Sanholt if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) 619152909Sanholt DRM_ERROR("failed to cleanup PCI GART!\n"); 62095584Sanholt } 62195584Sanholt 622145132Sanholt drm_free(dev->dev_private, sizeof(drm_r128_private_t), 623145132Sanholt DRM_MEM_DRIVER); 62495584Sanholt dev->dev_private = NULL; 62595584Sanholt } 62695584Sanholt 62795584Sanholt return 0; 62895584Sanholt} 62995584Sanholt 630182080Srnolandint r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 63195584Sanholt{ 632182080Srnoland drm_r128_init_t *init = data; 63395584Sanholt 634145132Sanholt DRM_DEBUG("\n"); 63595584Sanholt 636182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 637119098Sanholt 638182080Srnoland switch (init->func) { 63995584Sanholt case R128_INIT_CCE: 640182080Srnoland return r128_do_init_cce(dev, init); 64195584Sanholt case R128_CLEANUP_CCE: 642145132Sanholt return r128_do_cleanup_cce(dev); 64395584Sanholt } 64495584Sanholt 645182080Srnoland return -EINVAL; 64695584Sanholt} 64795584Sanholt 648182080Srnolandint r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) 64995584Sanholt{ 65095584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 651145132Sanholt DRM_DEBUG("\n"); 65295584Sanholt 653182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 65495584Sanholt 655145132Sanholt if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { 656182080Srnoland DRM_DEBUG("while CCE running\n"); 65795584Sanholt return 0; 65895584Sanholt } 65995584Sanholt 660145132Sanholt r128_do_cce_start(dev_priv); 66195584Sanholt 66295584Sanholt return 0; 66395584Sanholt} 66495584Sanholt 66595584Sanholt/* Stop the CCE. The engine must have been idled before calling this 66695584Sanholt * routine. 66795584Sanholt */ 668182080Srnolandint r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) 66995584Sanholt{ 67095584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 671182080Srnoland drm_r128_cce_stop_t *stop = data; 67295584Sanholt int ret; 673145132Sanholt DRM_DEBUG("\n"); 67495584Sanholt 675182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 67695584Sanholt 67795584Sanholt /* Flush any pending CCE commands. This ensures any outstanding 67895584Sanholt * commands are exectuted by the engine before we turn it off. 67995584Sanholt */ 680182080Srnoland if (stop->flush) { 681145132Sanholt r128_do_cce_flush(dev_priv); 68295584Sanholt } 68395584Sanholt 68495584Sanholt /* If we fail to make the engine go idle, we return an error 68595584Sanholt * code so that the DRM ioctl wrapper can try again. 68695584Sanholt */ 687182080Srnoland if (stop->idle) { 688145132Sanholt ret = r128_do_cce_idle(dev_priv); 689145132Sanholt if (ret) 690145132Sanholt return ret; 69195584Sanholt } 69295584Sanholt 69395584Sanholt /* Finally, we can turn off the CCE. If the engine isn't idle, 69495584Sanholt * we will get some dropped triangles as they won't be fully 69595584Sanholt * rendered before the CCE is shut down. 69695584Sanholt */ 697145132Sanholt r128_do_cce_stop(dev_priv); 69895584Sanholt 69995584Sanholt /* Reset the engine */ 700145132Sanholt r128_do_engine_reset(dev); 70195584Sanholt 70295584Sanholt return 0; 70395584Sanholt} 70495584Sanholt 70595584Sanholt/* Just reset the CCE ring. Called as part of an X Server engine reset. 70695584Sanholt */ 707182080Srnolandint r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 70895584Sanholt{ 70995584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 710145132Sanholt DRM_DEBUG("\n"); 71195584Sanholt 712182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 71395584Sanholt 714145132Sanholt if (!dev_priv) { 715182080Srnoland DRM_DEBUG("called before init done\n"); 716182080Srnoland return -EINVAL; 71795584Sanholt } 71895584Sanholt 719145132Sanholt r128_do_cce_reset(dev_priv); 72095584Sanholt 72195584Sanholt /* The CCE is no longer running after an engine reset */ 72295584Sanholt dev_priv->cce_running = 0; 72395584Sanholt 72495584Sanholt return 0; 72595584Sanholt} 72695584Sanholt 727182080Srnolandint r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) 72895584Sanholt{ 72995584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 730145132Sanholt DRM_DEBUG("\n"); 73195584Sanholt 732182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 73395584Sanholt 734145132Sanholt if (dev_priv->cce_running) { 735145132Sanholt r128_do_cce_flush(dev_priv); 73695584Sanholt } 73795584Sanholt 738145132Sanholt return r128_do_cce_idle(dev_priv); 73995584Sanholt} 74095584Sanholt 741182080Srnolandint r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 74295584Sanholt{ 743145132Sanholt DRM_DEBUG("\n"); 74495584Sanholt 745182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 74695584Sanholt 747145132Sanholt return r128_do_engine_reset(dev); 74895584Sanholt} 74995584Sanholt 750182080Srnolandint r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) 75195584Sanholt{ 752182080Srnoland return -EINVAL; 75395584Sanholt} 75495584Sanholt 75595584Sanholt/* ================================================================ 75695584Sanholt * Freelist management 75795584Sanholt */ 75895584Sanholt#define R128_BUFFER_USED 0xffffffff 75995584Sanholt#define R128_BUFFER_FREE 0 76095584Sanholt 76195584Sanholt#if 0 762182080Srnolandstatic int r128_freelist_init(struct drm_device * dev) 76395584Sanholt{ 764182080Srnoland struct drm_device_dma *dma = dev->dma; 76595584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 766182080Srnoland struct drm_buf *buf; 76795584Sanholt drm_r128_buf_priv_t *buf_priv; 76895584Sanholt drm_r128_freelist_t *entry; 76995584Sanholt int i; 77095584Sanholt 771145132Sanholt dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); 772145132Sanholt if (dev_priv->head == NULL) 773182080Srnoland return -ENOMEM; 77495584Sanholt 775145132Sanholt memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); 77695584Sanholt dev_priv->head->age = R128_BUFFER_USED; 77795584Sanholt 778145132Sanholt for (i = 0; i < dma->buf_count; i++) { 77995584Sanholt buf = dma->buflist[i]; 78095584Sanholt buf_priv = buf->dev_private; 78195584Sanholt 782145132Sanholt entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); 783145132Sanholt if (!entry) 784182080Srnoland return -ENOMEM; 78595584Sanholt 78695584Sanholt entry->age = R128_BUFFER_FREE; 78795584Sanholt entry->buf = buf; 78895584Sanholt entry->prev = dev_priv->head; 78995584Sanholt entry->next = dev_priv->head->next; 790145132Sanholt if (!entry->next) 79195584Sanholt dev_priv->tail = entry; 79295584Sanholt 79395584Sanholt buf_priv->discard = 0; 79495584Sanholt buf_priv->dispatched = 0; 79595584Sanholt buf_priv->list_entry = entry; 79695584Sanholt 79795584Sanholt dev_priv->head->next = entry; 79895584Sanholt 799145132Sanholt if (dev_priv->head->next) 80095584Sanholt dev_priv->head->next->prev = entry; 80195584Sanholt } 80295584Sanholt 80395584Sanholt return 0; 80495584Sanholt 80595584Sanholt} 80695584Sanholt#endif 80795584Sanholt 808182080Srnolandstatic struct drm_buf *r128_freelist_get(struct drm_device * dev) 80995584Sanholt{ 810182080Srnoland struct drm_device_dma *dma = dev->dma; 81195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 81295584Sanholt drm_r128_buf_priv_t *buf_priv; 813182080Srnoland struct drm_buf *buf; 81495584Sanholt int i, t; 81595584Sanholt 81695584Sanholt /* FIXME: Optimize -- use freelist code */ 81795584Sanholt 818145132Sanholt for (i = 0; i < dma->buf_count; i++) { 81995584Sanholt buf = dma->buflist[i]; 82095584Sanholt buf_priv = buf->dev_private; 821182080Srnoland if (buf->file_priv == 0) 82295584Sanholt return buf; 82395584Sanholt } 82495584Sanholt 825145132Sanholt for (t = 0; t < dev_priv->usec_timeout; t++) { 826145132Sanholt u32 done_age = R128_READ(R128_LAST_DISPATCH_REG); 82795584Sanholt 828145132Sanholt for (i = 0; i < dma->buf_count; i++) { 82995584Sanholt buf = dma->buflist[i]; 83095584Sanholt buf_priv = buf->dev_private; 831145132Sanholt if (buf->pending && buf_priv->age <= done_age) { 83295584Sanholt /* The buffer has been processed, so it 83395584Sanholt * can now be used. 83495584Sanholt */ 83595584Sanholt buf->pending = 0; 83695584Sanholt return buf; 83795584Sanholt } 83895584Sanholt } 839145132Sanholt DRM_UDELAY(1); 84095584Sanholt } 84195584Sanholt 842145132Sanholt DRM_DEBUG("returning NULL!\n"); 84395584Sanholt return NULL; 84495584Sanholt} 84595584Sanholt 846182080Srnolandvoid r128_freelist_reset(struct drm_device * dev) 84795584Sanholt{ 848182080Srnoland struct drm_device_dma *dma = dev->dma; 84995584Sanholt int i; 85095584Sanholt 851145132Sanholt for (i = 0; i < dma->buf_count; i++) { 852182080Srnoland struct drm_buf *buf = dma->buflist[i]; 85395584Sanholt drm_r128_buf_priv_t *buf_priv = buf->dev_private; 85495584Sanholt buf_priv->age = 0; 85595584Sanholt } 85695584Sanholt} 85795584Sanholt 85895584Sanholt/* ================================================================ 85995584Sanholt * CCE command submission 86095584Sanholt */ 86195584Sanholt 862145132Sanholtint r128_wait_ring(drm_r128_private_t * dev_priv, int n) 86395584Sanholt{ 86495584Sanholt drm_r128_ring_buffer_t *ring = &dev_priv->ring; 86595584Sanholt int i; 86695584Sanholt 867145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 868145132Sanholt r128_update_ring_snapshot(dev_priv); 869145132Sanholt if (ring->space >= n) 87095584Sanholt return 0; 871145132Sanholt DRM_UDELAY(1); 87295584Sanholt } 87395584Sanholt 87495584Sanholt /* FIXME: This is being ignored... */ 875145132Sanholt DRM_ERROR("failed!\n"); 876182080Srnoland return -EBUSY; 87795584Sanholt} 87895584Sanholt 879182080Srnolandstatic int r128_cce_get_buffers(struct drm_device * dev, 880182080Srnoland struct drm_file *file_priv, 881182080Srnoland struct drm_dma * d) 88295584Sanholt{ 88395584Sanholt int i; 884182080Srnoland struct drm_buf *buf; 88595584Sanholt 886145132Sanholt for (i = d->granted_count; i < d->request_count; i++) { 887145132Sanholt buf = r128_freelist_get(dev); 888145132Sanholt if (!buf) 889182080Srnoland return -EAGAIN; 89095584Sanholt 891182080Srnoland buf->file_priv = file_priv; 89295584Sanholt 893145132Sanholt if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, 894145132Sanholt sizeof(buf->idx))) 895182080Srnoland return -EFAULT; 896145132Sanholt if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, 897145132Sanholt sizeof(buf->total))) 898182080Srnoland return -EFAULT; 899112015Sanholt 90095584Sanholt d->granted_count++; 90195584Sanholt } 90295584Sanholt return 0; 90395584Sanholt} 90495584Sanholt 905182080Srnolandint r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) 90695584Sanholt{ 907182080Srnoland struct drm_device_dma *dma = dev->dma; 90895584Sanholt int ret = 0; 909182080Srnoland struct drm_dma *d = data; 91095584Sanholt 911182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 91295584Sanholt 91395584Sanholt /* Please don't send us buffers. 91495584Sanholt */ 915182080Srnoland if (d->send_count != 0) { 916145132Sanholt DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", 917182080Srnoland DRM_CURRENTPID, d->send_count); 918182080Srnoland return -EINVAL; 91995584Sanholt } 92095584Sanholt 92195584Sanholt /* We'll send you buffers. 92295584Sanholt */ 923182080Srnoland if (d->request_count < 0 || d->request_count > dma->buf_count) { 924145132Sanholt DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", 925182080Srnoland DRM_CURRENTPID, d->request_count, dma->buf_count); 926182080Srnoland return -EINVAL; 92795584Sanholt } 92895584Sanholt 929182080Srnoland d->granted_count = 0; 93095584Sanholt 931182080Srnoland if (d->request_count) { 932182080Srnoland ret = r128_cce_get_buffers(dev, file_priv, d); 93395584Sanholt } 93495584Sanholt 93595584Sanholt return ret; 93695584Sanholt} 937