1145132Sanholt/* mach64_dma.c -- DMA support for mach64 (Rage Pro) driver -*- linux-c -*- */ 2145132Sanholt/** 3145132Sanholt * \file mach64_dma.c 4145132Sanholt * DMA support for mach64 (Rage Pro) driver 5145132Sanholt * 6145132Sanholt * \author Gareth Hughes <gareth@valinux.com> 7145132Sanholt * \author Frank C. Earl <fearl@airmail.net> 8145132Sanholt * \author Leif Delgass <ldelgass@retinalburn.net> 9182080Srnoland * \author Jos�� Fonseca <j_r_fonseca@yahoo.co.uk> 10145132Sanholt */ 11145132Sanholt 12152909Sanholt/*- 13145132Sanholt * Copyright 2000 Gareth Hughes 14145132Sanholt * Copyright 2002 Frank C. Earl 15145132Sanholt * Copyright 2002-2003 Leif Delgass 16145132Sanholt * All Rights Reserved. 17145132Sanholt * 18145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 19145132Sanholt * copy of this software and associated documentation files (the "Software"), 20145132Sanholt * to deal in the Software without restriction, including without limitation 21145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 22145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 23145132Sanholt * Software is furnished to do so, subject to the following conditions: 24145132Sanholt * 25145132Sanholt * The above copyright notice and this permission notice (including the next 26145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 27145132Sanholt * Software. 28145132Sanholt * 29145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 32145132Sanholt * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 33145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 34145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35145132Sanholt */ 36145132Sanholt 37152909Sanholt#include <sys/cdefs.h> 38152909Sanholt__FBSDID("$FreeBSD$"); 39152909Sanholt 40145132Sanholt#include "dev/drm/drmP.h" 41145132Sanholt#include "dev/drm/drm.h" 42145132Sanholt#include "dev/drm/mach64_drm.h" 43145132Sanholt#include "dev/drm/mach64_drv.h" 44145132Sanholt 45145132Sanholt/*******************************************************************/ 46145132Sanholt/** \name Engine, FIFO control */ 47145132Sanholt/*@{*/ 48145132Sanholt 49145132Sanholt/** 50145132Sanholt * Waits for free entries in the FIFO. 51145132Sanholt * 52145132Sanholt * \note Most writes to Mach64 registers are automatically routed through 53145132Sanholt * command FIFO which is 16 entry deep. Prior to writing to any draw engine 54145132Sanholt * register one has to ensure that enough FIFO entries are available by calling 55145132Sanholt * this function. Failure to do so may cause the engine to lock. 56145132Sanholt * 57145132Sanholt * \param dev_priv pointer to device private data structure. 58145132Sanholt * \param entries number of free entries in the FIFO to wait for. 59182080Srnoland * 60145132Sanholt * \returns zero on success, or -EBUSY if the timeout (specificed by 61145132Sanholt * drm_mach64_private::usec_timeout) occurs. 62145132Sanholt */ 63182080Srnolandint mach64_do_wait_for_fifo(drm_mach64_private_t *dev_priv, int entries) 64145132Sanholt{ 65145132Sanholt int slots = 0, i; 66145132Sanholt 67145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 68145132Sanholt slots = (MACH64_READ(MACH64_FIFO_STAT) & MACH64_FIFO_SLOT_MASK); 69145132Sanholt if (slots <= (0x8000 >> entries)) 70145132Sanholt return 0; 71145132Sanholt DRM_UDELAY(1); 72145132Sanholt } 73145132Sanholt 74182080Srnoland DRM_INFO("failed! slots=%d entries=%d\n", slots, entries); 75182080Srnoland return -EBUSY; 76145132Sanholt} 77145132Sanholt 78145132Sanholt/** 79145132Sanholt * Wait for the draw engine to be idle. 80145132Sanholt */ 81182080Srnolandint mach64_do_wait_for_idle(drm_mach64_private_t *dev_priv) 82145132Sanholt{ 83145132Sanholt int i, ret; 84145132Sanholt 85145132Sanholt ret = mach64_do_wait_for_fifo(dev_priv, 16); 86145132Sanholt if (ret < 0) 87145132Sanholt return ret; 88145132Sanholt 89145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 90182080Srnoland if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) 91145132Sanholt return 0; 92145132Sanholt DRM_UDELAY(1); 93145132Sanholt } 94145132Sanholt 95182080Srnoland DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); 96145132Sanholt mach64_dump_ring_info(dev_priv); 97182080Srnoland return -EBUSY; 98145132Sanholt} 99145132Sanholt 100145132Sanholt/** 101145132Sanholt * Wait for free entries in the ring buffer. 102145132Sanholt * 103145132Sanholt * The Mach64 bus master can be configured to act as a virtual FIFO, using a 104145132Sanholt * circular buffer (commonly referred as "ring buffer" in other drivers) with 105145132Sanholt * pointers to engine commands. This allows the CPU to do other things while 106145132Sanholt * the graphics engine is busy, i.e., DMA mode. 107145132Sanholt * 108145132Sanholt * This function should be called before writing new entries to the ring 109145132Sanholt * buffer. 110182080Srnoland * 111145132Sanholt * \param dev_priv pointer to device private data structure. 112145132Sanholt * \param n number of free entries in the ring buffer to wait for. 113182080Srnoland * 114145132Sanholt * \returns zero on success, or -EBUSY if the timeout (specificed by 115145132Sanholt * drm_mach64_private_t::usec_timeout) occurs. 116145132Sanholt * 117145132Sanholt * \sa mach64_dump_ring_info() 118145132Sanholt */ 119182080Srnolandint mach64_wait_ring(drm_mach64_private_t *dev_priv, int n) 120145132Sanholt{ 121145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 122145132Sanholt int i; 123145132Sanholt 124145132Sanholt for (i = 0; i < dev_priv->usec_timeout; i++) { 125145132Sanholt mach64_update_ring_snapshot(dev_priv); 126145132Sanholt if (ring->space >= n) { 127182080Srnoland if (i > 0) 128182080Srnoland DRM_DEBUG("%d usecs\n", i); 129145132Sanholt return 0; 130145132Sanholt } 131145132Sanholt DRM_UDELAY(1); 132145132Sanholt } 133145132Sanholt 134145132Sanholt /* FIXME: This is being ignored... */ 135145132Sanholt DRM_ERROR("failed!\n"); 136145132Sanholt mach64_dump_ring_info(dev_priv); 137182080Srnoland return -EBUSY; 138145132Sanholt} 139145132Sanholt 140145132Sanholt/** 141182080Srnoland * Wait until all DMA requests have been processed... 142145132Sanholt * 143145132Sanholt * \sa mach64_wait_ring() 144145132Sanholt */ 145182080Srnolandstatic int mach64_ring_idle(drm_mach64_private_t *dev_priv) 146145132Sanholt{ 147145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 148145132Sanholt u32 head; 149145132Sanholt int i; 150145132Sanholt 151145132Sanholt head = ring->head; 152145132Sanholt i = 0; 153145132Sanholt while (i < dev_priv->usec_timeout) { 154145132Sanholt mach64_update_ring_snapshot(dev_priv); 155145132Sanholt if (ring->head == ring->tail && 156145132Sanholt !(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) { 157182080Srnoland if (i > 0) 158182080Srnoland DRM_DEBUG("%d usecs\n", i); 159145132Sanholt return 0; 160145132Sanholt } 161145132Sanholt if (ring->head == head) { 162145132Sanholt ++i; 163145132Sanholt } else { 164145132Sanholt head = ring->head; 165145132Sanholt i = 0; 166145132Sanholt } 167145132Sanholt DRM_UDELAY(1); 168145132Sanholt } 169145132Sanholt 170182080Srnoland DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); 171145132Sanholt mach64_dump_ring_info(dev_priv); 172182080Srnoland return -EBUSY; 173145132Sanholt} 174145132Sanholt 175145132Sanholt/** 176218909Sbrucec * Reset the ring buffer descriptors. 177145132Sanholt * 178145132Sanholt * \sa mach64_do_engine_reset() 179145132Sanholt */ 180182080Srnolandstatic void mach64_ring_reset(drm_mach64_private_t *dev_priv) 181145132Sanholt{ 182145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 183145132Sanholt 184145132Sanholt mach64_do_release_used_buffers(dev_priv); 185145132Sanholt ring->head_addr = ring->start_addr; 186145132Sanholt ring->head = ring->tail = 0; 187145132Sanholt ring->space = ring->size; 188145132Sanholt 189145132Sanholt MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 190145132Sanholt ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 191145132Sanholt 192145132Sanholt dev_priv->ring_running = 0; 193145132Sanholt} 194145132Sanholt 195145132Sanholt/** 196145132Sanholt * Ensure the all the queued commands will be processed. 197145132Sanholt */ 198182080Srnolandint mach64_do_dma_flush(drm_mach64_private_t *dev_priv) 199145132Sanholt{ 200145132Sanholt /* FIXME: It's not necessary to wait for idle when flushing 201145132Sanholt * we just need to ensure the ring will be completely processed 202145132Sanholt * in finite time without another ioctl 203145132Sanholt */ 204145132Sanholt return mach64_ring_idle(dev_priv); 205145132Sanholt} 206145132Sanholt 207145132Sanholt/** 208145132Sanholt * Stop all DMA activity. 209145132Sanholt */ 210182080Srnolandint mach64_do_dma_idle(drm_mach64_private_t *dev_priv) 211145132Sanholt{ 212145132Sanholt int ret; 213145132Sanholt 214145132Sanholt /* wait for completion */ 215145132Sanholt if ((ret = mach64_ring_idle(dev_priv)) < 0) { 216182080Srnoland DRM_ERROR("failed BM_GUI_TABLE=0x%08x tail: %u\n", 217182080Srnoland MACH64_READ(MACH64_BM_GUI_TABLE), 218145132Sanholt dev_priv->ring.tail); 219145132Sanholt return ret; 220145132Sanholt } 221145132Sanholt 222145132Sanholt mach64_ring_stop(dev_priv); 223145132Sanholt 224145132Sanholt /* clean up after pass */ 225145132Sanholt mach64_do_release_used_buffers(dev_priv); 226145132Sanholt return 0; 227145132Sanholt} 228145132Sanholt 229145132Sanholt/** 230145132Sanholt * Reset the engine. This will stop the DMA if it is running. 231145132Sanholt */ 232182080Srnolandint mach64_do_engine_reset(drm_mach64_private_t *dev_priv) 233145132Sanholt{ 234145132Sanholt u32 tmp; 235145132Sanholt 236182080Srnoland DRM_DEBUG("\n"); 237145132Sanholt 238145132Sanholt /* Kill off any outstanding DMA transfers. 239145132Sanholt */ 240145132Sanholt tmp = MACH64_READ(MACH64_BUS_CNTL); 241145132Sanholt MACH64_WRITE(MACH64_BUS_CNTL, tmp | MACH64_BUS_MASTER_DIS); 242145132Sanholt 243145132Sanholt /* Reset the GUI engine (high to low transition). 244145132Sanholt */ 245145132Sanholt tmp = MACH64_READ(MACH64_GEN_TEST_CNTL); 246145132Sanholt MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp & ~MACH64_GUI_ENGINE_ENABLE); 247145132Sanholt /* Enable the GUI engine 248145132Sanholt */ 249145132Sanholt tmp = MACH64_READ(MACH64_GEN_TEST_CNTL); 250145132Sanholt MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp | MACH64_GUI_ENGINE_ENABLE); 251145132Sanholt 252145132Sanholt /* ensure engine is not locked up by clearing any FIFO or HOST errors 253145132Sanholt */ 254145132Sanholt tmp = MACH64_READ(MACH64_BUS_CNTL); 255145132Sanholt MACH64_WRITE(MACH64_BUS_CNTL, tmp | 0x00a00000); 256145132Sanholt 257145132Sanholt /* Once GUI engine is restored, disable bus mastering */ 258145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, 0); 259145132Sanholt 260145132Sanholt /* Reset descriptor ring */ 261145132Sanholt mach64_ring_reset(dev_priv); 262145132Sanholt 263145132Sanholt return 0; 264145132Sanholt} 265145132Sanholt 266145132Sanholt/*@}*/ 267145132Sanholt 268145132Sanholt 269145132Sanholt/*******************************************************************/ 270145132Sanholt/** \name Debugging output */ 271145132Sanholt/*@{*/ 272145132Sanholt 273145132Sanholt/** 274145132Sanholt * Dump engine registers values. 275145132Sanholt */ 276182080Srnolandvoid mach64_dump_engine_info(drm_mach64_private_t *dev_priv) 277145132Sanholt{ 278145132Sanholt DRM_INFO("\n"); 279145132Sanholt if (!dev_priv->is_pci) { 280145132Sanholt DRM_INFO(" AGP_BASE = 0x%08x\n", 281145132Sanholt MACH64_READ(MACH64_AGP_BASE)); 282145132Sanholt DRM_INFO(" AGP_CNTL = 0x%08x\n", 283145132Sanholt MACH64_READ(MACH64_AGP_CNTL)); 284145132Sanholt } 285145132Sanholt DRM_INFO(" ALPHA_TST_CNTL = 0x%08x\n", 286145132Sanholt MACH64_READ(MACH64_ALPHA_TST_CNTL)); 287145132Sanholt DRM_INFO("\n"); 288145132Sanholt DRM_INFO(" BM_COMMAND = 0x%08x\n", 289145132Sanholt MACH64_READ(MACH64_BM_COMMAND)); 290145132Sanholt DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n", 291145132Sanholt MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET)); 292145132Sanholt DRM_INFO(" BM_GUI_TABLE = 0x%08x\n", 293145132Sanholt MACH64_READ(MACH64_BM_GUI_TABLE)); 294145132Sanholt DRM_INFO(" BM_STATUS = 0x%08x\n", 295145132Sanholt MACH64_READ(MACH64_BM_STATUS)); 296145132Sanholt DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n", 297145132Sanholt MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR)); 298145132Sanholt DRM_INFO(" BM_SYSTEM_TABLE = 0x%08x\n", 299145132Sanholt MACH64_READ(MACH64_BM_SYSTEM_TABLE)); 300145132Sanholt DRM_INFO(" BUS_CNTL = 0x%08x\n", 301145132Sanholt MACH64_READ(MACH64_BUS_CNTL)); 302145132Sanholt DRM_INFO("\n"); 303145132Sanholt /* DRM_INFO( " CLOCK_CNTL = 0x%08x\n", MACH64_READ( MACH64_CLOCK_CNTL ) ); */ 304145132Sanholt DRM_INFO(" CLR_CMP_CLR = 0x%08x\n", 305145132Sanholt MACH64_READ(MACH64_CLR_CMP_CLR)); 306145132Sanholt DRM_INFO(" CLR_CMP_CNTL = 0x%08x\n", 307145132Sanholt MACH64_READ(MACH64_CLR_CMP_CNTL)); 308145132Sanholt /* DRM_INFO( " CLR_CMP_MSK = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_MSK ) ); */ 309145132Sanholt DRM_INFO(" CONFIG_CHIP_ID = 0x%08x\n", 310145132Sanholt MACH64_READ(MACH64_CONFIG_CHIP_ID)); 311145132Sanholt DRM_INFO(" CONFIG_CNTL = 0x%08x\n", 312145132Sanholt MACH64_READ(MACH64_CONFIG_CNTL)); 313145132Sanholt DRM_INFO(" CONFIG_STAT0 = 0x%08x\n", 314145132Sanholt MACH64_READ(MACH64_CONFIG_STAT0)); 315145132Sanholt DRM_INFO(" CONFIG_STAT1 = 0x%08x\n", 316145132Sanholt MACH64_READ(MACH64_CONFIG_STAT1)); 317145132Sanholt DRM_INFO(" CONFIG_STAT2 = 0x%08x\n", 318145132Sanholt MACH64_READ(MACH64_CONFIG_STAT2)); 319145132Sanholt DRM_INFO(" CRC_SIG = 0x%08x\n", MACH64_READ(MACH64_CRC_SIG)); 320145132Sanholt DRM_INFO(" CUSTOM_MACRO_CNTL = 0x%08x\n", 321145132Sanholt MACH64_READ(MACH64_CUSTOM_MACRO_CNTL)); 322145132Sanholt DRM_INFO("\n"); 323145132Sanholt /* DRM_INFO( " DAC_CNTL = 0x%08x\n", MACH64_READ( MACH64_DAC_CNTL ) ); */ 324145132Sanholt /* DRM_INFO( " DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_DAC_REGS ) ); */ 325145132Sanholt DRM_INFO(" DP_BKGD_CLR = 0x%08x\n", 326145132Sanholt MACH64_READ(MACH64_DP_BKGD_CLR)); 327145132Sanholt DRM_INFO(" DP_FRGD_CLR = 0x%08x\n", 328145132Sanholt MACH64_READ(MACH64_DP_FRGD_CLR)); 329145132Sanholt DRM_INFO(" DP_MIX = 0x%08x\n", MACH64_READ(MACH64_DP_MIX)); 330145132Sanholt DRM_INFO(" DP_PIX_WIDTH = 0x%08x\n", 331145132Sanholt MACH64_READ(MACH64_DP_PIX_WIDTH)); 332145132Sanholt DRM_INFO(" DP_SRC = 0x%08x\n", MACH64_READ(MACH64_DP_SRC)); 333145132Sanholt DRM_INFO(" DP_WRITE_MASK = 0x%08x\n", 334145132Sanholt MACH64_READ(MACH64_DP_WRITE_MASK)); 335145132Sanholt DRM_INFO(" DSP_CONFIG = 0x%08x\n", 336145132Sanholt MACH64_READ(MACH64_DSP_CONFIG)); 337145132Sanholt DRM_INFO(" DSP_ON_OFF = 0x%08x\n", 338145132Sanholt MACH64_READ(MACH64_DSP_ON_OFF)); 339145132Sanholt DRM_INFO(" DST_CNTL = 0x%08x\n", 340145132Sanholt MACH64_READ(MACH64_DST_CNTL)); 341145132Sanholt DRM_INFO(" DST_OFF_PITCH = 0x%08x\n", 342145132Sanholt MACH64_READ(MACH64_DST_OFF_PITCH)); 343145132Sanholt DRM_INFO("\n"); 344145132Sanholt /* DRM_INFO( " EXT_DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_EXT_DAC_REGS ) ); */ 345145132Sanholt DRM_INFO(" EXT_MEM_CNTL = 0x%08x\n", 346145132Sanholt MACH64_READ(MACH64_EXT_MEM_CNTL)); 347145132Sanholt DRM_INFO("\n"); 348145132Sanholt DRM_INFO(" FIFO_STAT = 0x%08x\n", 349145132Sanholt MACH64_READ(MACH64_FIFO_STAT)); 350145132Sanholt DRM_INFO("\n"); 351145132Sanholt DRM_INFO(" GEN_TEST_CNTL = 0x%08x\n", 352145132Sanholt MACH64_READ(MACH64_GEN_TEST_CNTL)); 353145132Sanholt /* DRM_INFO( " GP_IO = 0x%08x\n", MACH64_READ( MACH64_GP_IO ) ); */ 354145132Sanholt DRM_INFO(" GUI_CMDFIFO_DATA = 0x%08x\n", 355145132Sanholt MACH64_READ(MACH64_GUI_CMDFIFO_DATA)); 356145132Sanholt DRM_INFO(" GUI_CMDFIFO_DEBUG = 0x%08x\n", 357145132Sanholt MACH64_READ(MACH64_GUI_CMDFIFO_DEBUG)); 358145132Sanholt DRM_INFO(" GUI_CNTL = 0x%08x\n", 359145132Sanholt MACH64_READ(MACH64_GUI_CNTL)); 360145132Sanholt DRM_INFO(" GUI_STAT = 0x%08x\n", 361145132Sanholt MACH64_READ(MACH64_GUI_STAT)); 362145132Sanholt DRM_INFO(" GUI_TRAJ_CNTL = 0x%08x\n", 363145132Sanholt MACH64_READ(MACH64_GUI_TRAJ_CNTL)); 364145132Sanholt DRM_INFO("\n"); 365145132Sanholt DRM_INFO(" HOST_CNTL = 0x%08x\n", 366145132Sanholt MACH64_READ(MACH64_HOST_CNTL)); 367145132Sanholt DRM_INFO(" HW_DEBUG = 0x%08x\n", 368145132Sanholt MACH64_READ(MACH64_HW_DEBUG)); 369145132Sanholt DRM_INFO("\n"); 370145132Sanholt DRM_INFO(" MEM_ADDR_CONFIG = 0x%08x\n", 371145132Sanholt MACH64_READ(MACH64_MEM_ADDR_CONFIG)); 372145132Sanholt DRM_INFO(" MEM_BUF_CNTL = 0x%08x\n", 373145132Sanholt MACH64_READ(MACH64_MEM_BUF_CNTL)); 374145132Sanholt DRM_INFO("\n"); 375145132Sanholt DRM_INFO(" PAT_REG0 = 0x%08x\n", 376145132Sanholt MACH64_READ(MACH64_PAT_REG0)); 377145132Sanholt DRM_INFO(" PAT_REG1 = 0x%08x\n", 378145132Sanholt MACH64_READ(MACH64_PAT_REG1)); 379145132Sanholt DRM_INFO("\n"); 380145132Sanholt DRM_INFO(" SC_LEFT = 0x%08x\n", MACH64_READ(MACH64_SC_LEFT)); 381145132Sanholt DRM_INFO(" SC_RIGHT = 0x%08x\n", 382145132Sanholt MACH64_READ(MACH64_SC_RIGHT)); 383145132Sanholt DRM_INFO(" SC_TOP = 0x%08x\n", MACH64_READ(MACH64_SC_TOP)); 384145132Sanholt DRM_INFO(" SC_BOTTOM = 0x%08x\n", 385145132Sanholt MACH64_READ(MACH64_SC_BOTTOM)); 386145132Sanholt DRM_INFO("\n"); 387145132Sanholt DRM_INFO(" SCALE_3D_CNTL = 0x%08x\n", 388145132Sanholt MACH64_READ(MACH64_SCALE_3D_CNTL)); 389145132Sanholt DRM_INFO(" SCRATCH_REG0 = 0x%08x\n", 390145132Sanholt MACH64_READ(MACH64_SCRATCH_REG0)); 391145132Sanholt DRM_INFO(" SCRATCH_REG1 = 0x%08x\n", 392145132Sanholt MACH64_READ(MACH64_SCRATCH_REG1)); 393145132Sanholt DRM_INFO(" SETUP_CNTL = 0x%08x\n", 394145132Sanholt MACH64_READ(MACH64_SETUP_CNTL)); 395145132Sanholt DRM_INFO(" SRC_CNTL = 0x%08x\n", 396145132Sanholt MACH64_READ(MACH64_SRC_CNTL)); 397145132Sanholt DRM_INFO("\n"); 398145132Sanholt DRM_INFO(" TEX_CNTL = 0x%08x\n", 399145132Sanholt MACH64_READ(MACH64_TEX_CNTL)); 400145132Sanholt DRM_INFO(" TEX_SIZE_PITCH = 0x%08x\n", 401145132Sanholt MACH64_READ(MACH64_TEX_SIZE_PITCH)); 402145132Sanholt DRM_INFO(" TIMER_CONFIG = 0x%08x\n", 403145132Sanholt MACH64_READ(MACH64_TIMER_CONFIG)); 404145132Sanholt DRM_INFO("\n"); 405145132Sanholt DRM_INFO(" Z_CNTL = 0x%08x\n", MACH64_READ(MACH64_Z_CNTL)); 406145132Sanholt DRM_INFO(" Z_OFF_PITCH = 0x%08x\n", 407145132Sanholt MACH64_READ(MACH64_Z_OFF_PITCH)); 408145132Sanholt DRM_INFO("\n"); 409145132Sanholt} 410145132Sanholt 411145132Sanholt#define MACH64_DUMP_CONTEXT 3 412145132Sanholt 413145132Sanholt/** 414145132Sanholt * Used by mach64_dump_ring_info() to dump the contents of the current buffer 415145132Sanholt * pointed by the ring head. 416145132Sanholt */ 417182080Srnolandstatic void mach64_dump_buf_info(drm_mach64_private_t *dev_priv, 418182080Srnoland struct drm_buf *buf) 419145132Sanholt{ 420145132Sanholt u32 addr = GETBUFADDR(buf); 421145132Sanholt u32 used = buf->used >> 2; 422145132Sanholt u32 sys_addr = MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR); 423145132Sanholt u32 *p = GETBUFPTR(buf); 424145132Sanholt int skipped = 0; 425145132Sanholt 426145132Sanholt DRM_INFO("buffer contents:\n"); 427145132Sanholt 428145132Sanholt while (used) { 429145132Sanholt u32 reg, count; 430145132Sanholt 431145132Sanholt reg = le32_to_cpu(*p++); 432145132Sanholt if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 || 433145132Sanholt (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 && 434145132Sanholt addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) || 435145132Sanholt addr >= 436145132Sanholt GETBUFADDR(buf) + buf->used - MACH64_DUMP_CONTEXT * 4) { 437145132Sanholt DRM_INFO("%08x: 0x%08x\n", addr, reg); 438145132Sanholt } 439145132Sanholt addr += 4; 440145132Sanholt used--; 441145132Sanholt 442145132Sanholt count = (reg >> 16) + 1; 443145132Sanholt reg = reg & 0xffff; 444145132Sanholt reg = MMSELECT(reg); 445145132Sanholt while (count && used) { 446145132Sanholt if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 || 447145132Sanholt (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 && 448145132Sanholt addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) || 449145132Sanholt addr >= 450145132Sanholt GETBUFADDR(buf) + buf->used - 451145132Sanholt MACH64_DUMP_CONTEXT * 4) { 452145132Sanholt DRM_INFO("%08x: 0x%04x = 0x%08x\n", addr, 453145132Sanholt reg, le32_to_cpu(*p)); 454145132Sanholt skipped = 0; 455145132Sanholt } else { 456145132Sanholt if (!skipped) { 457145132Sanholt DRM_INFO(" ...\n"); 458145132Sanholt skipped = 1; 459145132Sanholt } 460145132Sanholt } 461145132Sanholt p++; 462145132Sanholt addr += 4; 463145132Sanholt used--; 464145132Sanholt 465145132Sanholt reg += 4; 466145132Sanholt count--; 467145132Sanholt } 468145132Sanholt } 469145132Sanholt 470145132Sanholt DRM_INFO("\n"); 471145132Sanholt} 472145132Sanholt 473145132Sanholt/** 474145132Sanholt * Dump the ring state and contents, including the contents of the buffer being 475145132Sanholt * processed by the graphics engine. 476145132Sanholt */ 477182080Srnolandvoid mach64_dump_ring_info(drm_mach64_private_t *dev_priv) 478145132Sanholt{ 479145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 480145132Sanholt int i, skipped; 481145132Sanholt 482145132Sanholt DRM_INFO("\n"); 483145132Sanholt 484145132Sanholt DRM_INFO("ring contents:\n"); 485145132Sanholt DRM_INFO(" head_addr: 0x%08x head: %u tail: %u\n\n", 486145132Sanholt ring->head_addr, ring->head, ring->tail); 487145132Sanholt 488145132Sanholt skipped = 0; 489145132Sanholt for (i = 0; i < ring->size / sizeof(u32); i += 4) { 490145132Sanholt if (i <= MACH64_DUMP_CONTEXT * 4 || 491145132Sanholt i >= ring->size / sizeof(u32) - MACH64_DUMP_CONTEXT * 4 || 492145132Sanholt (i >= ring->tail - MACH64_DUMP_CONTEXT * 4 && 493145132Sanholt i <= ring->tail + MACH64_DUMP_CONTEXT * 4) || 494145132Sanholt (i >= ring->head - MACH64_DUMP_CONTEXT * 4 && 495145132Sanholt i <= ring->head + MACH64_DUMP_CONTEXT * 4)) { 496145132Sanholt DRM_INFO(" 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x%s%s\n", 497145132Sanholt (u32)(ring->start_addr + i * sizeof(u32)), 498145132Sanholt le32_to_cpu(((u32 *) ring->start)[i + 0]), 499145132Sanholt le32_to_cpu(((u32 *) ring->start)[i + 1]), 500145132Sanholt le32_to_cpu(((u32 *) ring->start)[i + 2]), 501145132Sanholt le32_to_cpu(((u32 *) ring->start)[i + 3]), 502145132Sanholt i == ring->head ? " (head)" : "", 503145132Sanholt i == ring->tail ? " (tail)" : ""); 504145132Sanholt skipped = 0; 505145132Sanholt } else { 506145132Sanholt if (!skipped) { 507145132Sanholt DRM_INFO(" ...\n"); 508145132Sanholt skipped = 1; 509145132Sanholt } 510145132Sanholt } 511145132Sanholt } 512145132Sanholt 513145132Sanholt DRM_INFO("\n"); 514145132Sanholt 515249816Sjkim if (ring->head < ring->size / sizeof(u32)) { 516145132Sanholt struct list_head *ptr; 517145132Sanholt u32 addr = le32_to_cpu(((u32 *) ring->start)[ring->head + 1]); 518145132Sanholt 519145132Sanholt list_for_each(ptr, &dev_priv->pending) { 520145132Sanholt drm_mach64_freelist_t *entry = 521145132Sanholt list_entry(ptr, drm_mach64_freelist_t, list); 522182080Srnoland struct drm_buf *buf = entry->buf; 523145132Sanholt 524145132Sanholt u32 buf_addr = GETBUFADDR(buf); 525145132Sanholt 526182080Srnoland if (buf_addr <= addr && addr < buf_addr + buf->used) 527145132Sanholt mach64_dump_buf_info(dev_priv, buf); 528145132Sanholt } 529145132Sanholt } 530145132Sanholt 531145132Sanholt DRM_INFO("\n"); 532145132Sanholt DRM_INFO(" BM_GUI_TABLE = 0x%08x\n", 533145132Sanholt MACH64_READ(MACH64_BM_GUI_TABLE)); 534145132Sanholt DRM_INFO("\n"); 535145132Sanholt DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n", 536145132Sanholt MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET)); 537145132Sanholt DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n", 538145132Sanholt MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR)); 539145132Sanholt DRM_INFO(" BM_COMMAND = 0x%08x\n", 540145132Sanholt MACH64_READ(MACH64_BM_COMMAND)); 541145132Sanholt DRM_INFO("\n"); 542145132Sanholt DRM_INFO(" BM_STATUS = 0x%08x\n", 543145132Sanholt MACH64_READ(MACH64_BM_STATUS)); 544145132Sanholt DRM_INFO(" BUS_CNTL = 0x%08x\n", 545145132Sanholt MACH64_READ(MACH64_BUS_CNTL)); 546145132Sanholt DRM_INFO(" FIFO_STAT = 0x%08x\n", 547145132Sanholt MACH64_READ(MACH64_FIFO_STAT)); 548145132Sanholt DRM_INFO(" GUI_STAT = 0x%08x\n", 549145132Sanholt MACH64_READ(MACH64_GUI_STAT)); 550145132Sanholt DRM_INFO(" SRC_CNTL = 0x%08x\n", 551145132Sanholt MACH64_READ(MACH64_SRC_CNTL)); 552145132Sanholt} 553145132Sanholt 554145132Sanholt/*@}*/ 555145132Sanholt 556145132Sanholt 557145132Sanholt/*******************************************************************/ 558182080Srnoland/** \name DMA descriptor ring macros */ 559182080Srnoland/*@{*/ 560182080Srnoland 561182080Srnoland/** 562182080Srnoland * Remove the end mark from the ring's old tail position. 563182080Srnoland * 564182080Srnoland * It should be called after calling mach64_set_dma_eol to mark the ring's new 565182080Srnoland * tail position. 566182080Srnoland * 567182080Srnoland * We update the end marks while the bus master engine is in operation. Since 568182080Srnoland * the bus master engine may potentially be reading from the same position 569182080Srnoland * that we write, we must change atomically to avoid having intermediary bad 570182080Srnoland * data. 571182080Srnoland */ 572182080Srnolandstatic __inline__ void mach64_clear_dma_eol(volatile u32 *addr) 573182080Srnoland{ 574182080Srnoland#if defined(__i386__) 575182080Srnoland int nr = 31; 576182080Srnoland 577182080Srnoland /* Taken from include/asm-i386/bitops.h linux header */ 578182080Srnoland __asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr) 579182080Srnoland :"Ir"(nr)); 580182080Srnoland#elif defined(__powerpc__) 581182080Srnoland u32 old; 582182080Srnoland u32 mask = cpu_to_le32(MACH64_DMA_EOL); 583182080Srnoland 584182080Srnoland /* Taken from the include/asm-ppc/bitops.h linux header */ 585182080Srnoland __asm__ __volatile__("\n\ 586182080Srnoland1: lwarx %0,0,%3 \n\ 587182080Srnoland andc %0,%0,%2 \n\ 588182080Srnoland stwcx. %0,0,%3 \n\ 589182080Srnoland bne- 1b":"=&r"(old), "=m"(*addr) 590182080Srnoland :"r"(mask), "r"(addr), "m"(*addr) 591182080Srnoland :"cc"); 592182080Srnoland#elif defined(__alpha__) 593182080Srnoland u32 temp; 594182080Srnoland u32 mask = ~MACH64_DMA_EOL; 595182080Srnoland 596182080Srnoland /* Taken from the include/asm-alpha/bitops.h linux header */ 597182080Srnoland __asm__ __volatile__("1: ldl_l %0,%3\n" 598182080Srnoland " and %0,%2,%0\n" 599182080Srnoland " stl_c %0,%1\n" 600182080Srnoland " beq %0,2f\n" 601182080Srnoland ".subsection 2\n" 602182080Srnoland "2: br 1b\n" 603182080Srnoland ".previous":"=&r"(temp), "=m"(*addr) 604182080Srnoland :"Ir"(mask), "m"(*addr)); 605182080Srnoland#else 606182080Srnoland u32 mask = cpu_to_le32(~MACH64_DMA_EOL); 607182080Srnoland 608182080Srnoland *addr &= mask; 609182080Srnoland#endif 610182080Srnoland} 611182080Srnoland 612182080Srnoland#define RING_LOCALS \ 613182080Srnoland int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring 614182080Srnoland 615182080Srnoland#define RING_WRITE_OFS _ring_write 616182080Srnoland 617182080Srnoland#define BEGIN_RING(n) \ 618182080Srnoland do { \ 619182080Srnoland if (MACH64_VERBOSE) { \ 620182080Srnoland DRM_INFO( "BEGIN_RING( %d ) \n", \ 621182080Srnoland (n) ); \ 622182080Srnoland } \ 623182080Srnoland if (dev_priv->ring.space <= (n) * sizeof(u32)) { \ 624182080Srnoland int ret; \ 625182080Srnoland if ((ret = mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ 626182080Srnoland DRM_ERROR( "wait_ring failed, resetting engine\n"); \ 627182080Srnoland mach64_dump_engine_info( dev_priv ); \ 628182080Srnoland mach64_do_engine_reset( dev_priv ); \ 629182080Srnoland return ret; \ 630182080Srnoland } \ 631182080Srnoland } \ 632182080Srnoland dev_priv->ring.space -= (n) * sizeof(u32); \ 633182080Srnoland _ring = (u32 *) dev_priv->ring.start; \ 634182080Srnoland _ring_tail = _ring_write = dev_priv->ring.tail; \ 635182080Srnoland _ring_mask = dev_priv->ring.tail_mask; \ 636182080Srnoland } while (0) 637182080Srnoland 638182080Srnoland#define OUT_RING( x ) \ 639182080Srnolanddo { \ 640182080Srnoland if (MACH64_VERBOSE) { \ 641182080Srnoland DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ 642182080Srnoland (unsigned int)(x), _ring_write ); \ 643182080Srnoland } \ 644182080Srnoland _ring[_ring_write++] = cpu_to_le32( x ); \ 645182080Srnoland _ring_write &= _ring_mask; \ 646182080Srnoland} while (0) 647182080Srnoland 648182080Srnoland#define ADVANCE_RING() \ 649182080Srnolanddo { \ 650182080Srnoland if (MACH64_VERBOSE) { \ 651182080Srnoland DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ 652182080Srnoland _ring_write, _ring_tail ); \ 653182080Srnoland } \ 654182080Srnoland DRM_MEMORYBARRIER(); \ 655182080Srnoland mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] ); \ 656182080Srnoland DRM_MEMORYBARRIER(); \ 657182080Srnoland dev_priv->ring.tail = _ring_write; \ 658182080Srnoland mach64_ring_tick( dev_priv, &(dev_priv)->ring ); \ 659182080Srnoland} while (0) 660182080Srnoland 661182080Srnoland/** 662182080Srnoland * Queue a DMA buffer of registers writes into the ring buffer. 663182080Srnoland */ 664182080Srnolandint mach64_add_buf_to_ring(drm_mach64_private_t *dev_priv, 665182080Srnoland drm_mach64_freelist_t *entry) 666182080Srnoland{ 667182080Srnoland int bytes, pages, remainder; 668182080Srnoland u32 address, page; 669182080Srnoland int i; 670182080Srnoland struct drm_buf *buf = entry->buf; 671182080Srnoland RING_LOCALS; 672182080Srnoland 673182080Srnoland bytes = buf->used; 674182080Srnoland address = GETBUFADDR( buf ); 675182080Srnoland pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; 676182080Srnoland 677182080Srnoland BEGIN_RING( pages * 4 ); 678182080Srnoland 679182080Srnoland for ( i = 0 ; i < pages-1 ; i++ ) { 680182080Srnoland page = address + i * MACH64_DMA_CHUNKSIZE; 681182080Srnoland OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); 682182080Srnoland OUT_RING( page ); 683182080Srnoland OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); 684182080Srnoland OUT_RING( 0 ); 685182080Srnoland } 686182080Srnoland 687182080Srnoland /* generate the final descriptor for any remaining commands in this buffer */ 688182080Srnoland page = address + i * MACH64_DMA_CHUNKSIZE; 689182080Srnoland remainder = bytes - i * MACH64_DMA_CHUNKSIZE; 690182080Srnoland 691182080Srnoland /* Save dword offset of last descriptor for this buffer. 692182080Srnoland * This is needed to check for completion of the buffer in freelist_get 693182080Srnoland */ 694182080Srnoland entry->ring_ofs = RING_WRITE_OFS; 695182080Srnoland 696182080Srnoland OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); 697182080Srnoland OUT_RING( page ); 698182080Srnoland OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); 699182080Srnoland OUT_RING( 0 ); 700182080Srnoland 701182080Srnoland ADVANCE_RING(); 702182080Srnoland 703182080Srnoland return 0; 704182080Srnoland} 705182080Srnoland 706182080Srnoland/** 707182080Srnoland * Queue DMA buffer controlling host data tranfers (e.g., blit). 708182080Srnoland * 709182080Srnoland * Almost identical to mach64_add_buf_to_ring. 710182080Srnoland */ 711182080Srnolandint mach64_add_hostdata_buf_to_ring(drm_mach64_private_t *dev_priv, 712182080Srnoland drm_mach64_freelist_t *entry) 713182080Srnoland{ 714182080Srnoland int bytes, pages, remainder; 715182080Srnoland u32 address, page; 716182080Srnoland int i; 717182080Srnoland struct drm_buf *buf = entry->buf; 718182080Srnoland RING_LOCALS; 719182080Srnoland 720182080Srnoland bytes = buf->used - MACH64_HOSTDATA_BLIT_OFFSET; 721182080Srnoland pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE; 722182080Srnoland address = GETBUFADDR( buf ); 723182080Srnoland 724182080Srnoland BEGIN_RING( 4 + pages * 4 ); 725182080Srnoland 726182080Srnoland OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR ); 727182080Srnoland OUT_RING( address ); 728182080Srnoland OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET ); 729182080Srnoland OUT_RING( 0 ); 730182080Srnoland address += MACH64_HOSTDATA_BLIT_OFFSET; 731182080Srnoland 732182080Srnoland for ( i = 0 ; i < pages-1 ; i++ ) { 733182080Srnoland page = address + i * MACH64_DMA_CHUNKSIZE; 734182080Srnoland OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); 735182080Srnoland OUT_RING( page ); 736182080Srnoland OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET ); 737182080Srnoland OUT_RING( 0 ); 738182080Srnoland } 739182080Srnoland 740182080Srnoland /* generate the final descriptor for any remaining commands in this buffer */ 741182080Srnoland page = address + i * MACH64_DMA_CHUNKSIZE; 742182080Srnoland remainder = bytes - i * MACH64_DMA_CHUNKSIZE; 743182080Srnoland 744182080Srnoland /* Save dword offset of last descriptor for this buffer. 745182080Srnoland * This is needed to check for completion of the buffer in freelist_get 746182080Srnoland */ 747182080Srnoland entry->ring_ofs = RING_WRITE_OFS; 748182080Srnoland 749182080Srnoland OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA ); 750182080Srnoland OUT_RING( page ); 751182080Srnoland OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL ); 752182080Srnoland OUT_RING( 0 ); 753182080Srnoland 754182080Srnoland ADVANCE_RING(); 755182080Srnoland 756182080Srnoland return 0; 757182080Srnoland} 758182080Srnoland 759182080Srnoland/*@}*/ 760182080Srnoland 761182080Srnoland 762182080Srnoland/*******************************************************************/ 763145132Sanholt/** \name DMA test and initialization */ 764145132Sanholt/*@{*/ 765145132Sanholt 766145132Sanholt/** 767145132Sanholt * Perform a simple DMA operation using the pattern registers to test whether 768145132Sanholt * DMA works. 769145132Sanholt * 770145132Sanholt * \return zero if successful. 771145132Sanholt * 772145132Sanholt * \note This function was the testbed for many experiences regarding Mach64 773145132Sanholt * DMA operation. It is left here since it so tricky to get DMA operating 774145132Sanholt * properly in some architectures and hardware. 775145132Sanholt */ 776182080Srnolandstatic int mach64_bm_dma_test(struct drm_device * dev) 777145132Sanholt{ 778145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 779152909Sanholt drm_dma_handle_t *cpu_addr_dmah; 780145132Sanholt u32 data_addr; 781145132Sanholt u32 *table, *data; 782145132Sanholt u32 expected[2]; 783145132Sanholt u32 src_cntl, pat_reg0, pat_reg1; 784145132Sanholt int i, count, failed; 785145132Sanholt 786182080Srnoland DRM_DEBUG("\n"); 787145132Sanholt 788145132Sanholt table = (u32 *) dev_priv->ring.start; 789145132Sanholt 790145132Sanholt /* FIXME: get a dma buffer from the freelist here */ 791145132Sanholt DRM_DEBUG("Allocating data memory ...\n"); 792182883Srnoland#ifdef __FreeBSD__ 793182883Srnoland DRM_UNLOCK(); 794182883Srnoland#endif 795152909Sanholt cpu_addr_dmah = 796152909Sanholt drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful); 797182883Srnoland#ifdef __FreeBSD__ 798182883Srnoland DRM_LOCK(); 799182883Srnoland#endif 800152909Sanholt if (!cpu_addr_dmah) { 801145132Sanholt DRM_INFO("data-memory allocation failed!\n"); 802182080Srnoland return -ENOMEM; 803145132Sanholt } else { 804152909Sanholt data = (u32 *) cpu_addr_dmah->vaddr; 805152909Sanholt data_addr = (u32) cpu_addr_dmah->busaddr; 806145132Sanholt } 807145132Sanholt 808145132Sanholt /* Save the X server's value for SRC_CNTL and restore it 809145132Sanholt * in case our test fails. This prevents the X server 810145132Sanholt * from disabling it's cache for this register 811145132Sanholt */ 812145132Sanholt src_cntl = MACH64_READ(MACH64_SRC_CNTL); 813145132Sanholt pat_reg0 = MACH64_READ(MACH64_PAT_REG0); 814145132Sanholt pat_reg1 = MACH64_READ(MACH64_PAT_REG1); 815145132Sanholt 816145132Sanholt mach64_do_wait_for_fifo(dev_priv, 3); 817145132Sanholt 818145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, 0); 819145132Sanholt MACH64_WRITE(MACH64_PAT_REG0, 0x11111111); 820145132Sanholt MACH64_WRITE(MACH64_PAT_REG1, 0x11111111); 821145132Sanholt 822145132Sanholt mach64_do_wait_for_idle(dev_priv); 823145132Sanholt 824145132Sanholt for (i = 0; i < 2; i++) { 825145132Sanholt u32 reg; 826145132Sanholt reg = MACH64_READ((MACH64_PAT_REG0 + i * 4)); 827145132Sanholt DRM_DEBUG("(Before DMA Transfer) reg %d = 0x%08x\n", i, reg); 828145132Sanholt if (reg != 0x11111111) { 829145132Sanholt DRM_INFO("Error initializing test registers\n"); 830145132Sanholt DRM_INFO("resetting engine ...\n"); 831145132Sanholt mach64_do_engine_reset(dev_priv); 832145132Sanholt DRM_INFO("freeing data buffer memory.\n"); 833152909Sanholt drm_pci_free(dev, cpu_addr_dmah); 834182080Srnoland return -EIO; 835145132Sanholt } 836145132Sanholt } 837145132Sanholt 838145132Sanholt /* fill up a buffer with sets of 2 consecutive writes starting with PAT_REG0 */ 839145132Sanholt count = 0; 840145132Sanholt 841145132Sanholt data[count++] = cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16)); 842145132Sanholt data[count++] = expected[0] = 0x22222222; 843145132Sanholt data[count++] = expected[1] = 0xaaaaaaaa; 844145132Sanholt 845145132Sanholt while (count < 1020) { 846145132Sanholt data[count++] = 847145132Sanholt cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16)); 848145132Sanholt data[count++] = 0x22222222; 849145132Sanholt data[count++] = 0xaaaaaaaa; 850145132Sanholt } 851145132Sanholt data[count++] = cpu_to_le32(DMAREG(MACH64_SRC_CNTL) | (0 << 16)); 852145132Sanholt data[count++] = 0; 853145132Sanholt 854145132Sanholt DRM_DEBUG("Preparing table ...\n"); 855145132Sanholt table[MACH64_DMA_FRAME_BUF_OFFSET] = cpu_to_le32(MACH64_BM_ADDR + 856145132Sanholt MACH64_APERTURE_OFFSET); 857145132Sanholt table[MACH64_DMA_SYS_MEM_ADDR] = cpu_to_le32(data_addr); 858145132Sanholt table[MACH64_DMA_COMMAND] = cpu_to_le32(count * sizeof(u32) 859145132Sanholt | MACH64_DMA_HOLD_OFFSET 860145132Sanholt | MACH64_DMA_EOL); 861145132Sanholt table[MACH64_DMA_RESERVED] = 0; 862145132Sanholt 863145132Sanholt DRM_DEBUG("table[0] = 0x%08x\n", table[0]); 864145132Sanholt DRM_DEBUG("table[1] = 0x%08x\n", table[1]); 865145132Sanholt DRM_DEBUG("table[2] = 0x%08x\n", table[2]); 866145132Sanholt DRM_DEBUG("table[3] = 0x%08x\n", table[3]); 867145132Sanholt 868145132Sanholt for (i = 0; i < 6; i++) { 869145132Sanholt DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]); 870145132Sanholt } 871145132Sanholt DRM_DEBUG(" ...\n"); 872145132Sanholt for (i = count - 5; i < count; i++) { 873145132Sanholt DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]); 874145132Sanholt } 875145132Sanholt 876145132Sanholt DRM_MEMORYBARRIER(); 877145132Sanholt 878145132Sanholt DRM_DEBUG("waiting for idle...\n"); 879145132Sanholt if ((i = mach64_do_wait_for_idle(dev_priv))) { 880145132Sanholt DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i); 881145132Sanholt DRM_INFO("resetting engine ...\n"); 882145132Sanholt mach64_do_engine_reset(dev_priv); 883145132Sanholt mach64_do_wait_for_fifo(dev_priv, 3); 884145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); 885145132Sanholt MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); 886145132Sanholt MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); 887145132Sanholt DRM_INFO("freeing data buffer memory.\n"); 888152909Sanholt drm_pci_free(dev, cpu_addr_dmah); 889145132Sanholt return i; 890145132Sanholt } 891145132Sanholt DRM_DEBUG("waiting for idle...done\n"); 892145132Sanholt 893145132Sanholt DRM_DEBUG("BUS_CNTL = 0x%08x\n", MACH64_READ(MACH64_BUS_CNTL)); 894145132Sanholt DRM_DEBUG("SRC_CNTL = 0x%08x\n", MACH64_READ(MACH64_SRC_CNTL)); 895145132Sanholt DRM_DEBUG("\n"); 896145132Sanholt DRM_DEBUG("data bus addr = 0x%08x\n", data_addr); 897145132Sanholt DRM_DEBUG("table bus addr = 0x%08x\n", dev_priv->ring.start_addr); 898145132Sanholt 899145132Sanholt DRM_DEBUG("starting DMA transfer...\n"); 900145132Sanholt MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 901145132Sanholt dev_priv->ring.start_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 902145132Sanholt 903145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, 904145132Sanholt MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | 905145132Sanholt MACH64_SRC_BM_OP_SYSTEM_TO_REG); 906145132Sanholt 907145132Sanholt /* Kick off the transfer */ 908145132Sanholt DRM_DEBUG("starting DMA transfer... done.\n"); 909145132Sanholt MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); 910145132Sanholt 911145132Sanholt DRM_DEBUG("waiting for idle...\n"); 912145132Sanholt 913145132Sanholt if ((i = mach64_do_wait_for_idle(dev_priv))) { 914145132Sanholt /* engine locked up, dump register state and reset */ 915145132Sanholt DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i); 916145132Sanholt mach64_dump_engine_info(dev_priv); 917145132Sanholt DRM_INFO("resetting engine ...\n"); 918145132Sanholt mach64_do_engine_reset(dev_priv); 919145132Sanholt mach64_do_wait_for_fifo(dev_priv, 3); 920145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); 921145132Sanholt MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); 922145132Sanholt MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); 923145132Sanholt DRM_INFO("freeing data buffer memory.\n"); 924152909Sanholt drm_pci_free(dev, cpu_addr_dmah); 925145132Sanholt return i; 926145132Sanholt } 927145132Sanholt 928145132Sanholt DRM_DEBUG("waiting for idle...done\n"); 929145132Sanholt 930145132Sanholt /* restore SRC_CNTL */ 931145132Sanholt mach64_do_wait_for_fifo(dev_priv, 1); 932145132Sanholt MACH64_WRITE(MACH64_SRC_CNTL, src_cntl); 933145132Sanholt 934145132Sanholt failed = 0; 935145132Sanholt 936145132Sanholt /* Check register values to see if the GUI master operation succeeded */ 937145132Sanholt for (i = 0; i < 2; i++) { 938145132Sanholt u32 reg; 939145132Sanholt reg = MACH64_READ((MACH64_PAT_REG0 + i * 4)); 940145132Sanholt DRM_DEBUG("(After DMA Transfer) reg %d = 0x%08x\n", i, reg); 941145132Sanholt if (reg != expected[i]) { 942145132Sanholt failed = -1; 943145132Sanholt } 944145132Sanholt } 945145132Sanholt 946145132Sanholt /* restore pattern registers */ 947145132Sanholt mach64_do_wait_for_fifo(dev_priv, 2); 948145132Sanholt MACH64_WRITE(MACH64_PAT_REG0, pat_reg0); 949145132Sanholt MACH64_WRITE(MACH64_PAT_REG1, pat_reg1); 950145132Sanholt 951145132Sanholt DRM_DEBUG("freeing data buffer memory.\n"); 952152909Sanholt drm_pci_free(dev, cpu_addr_dmah); 953145132Sanholt DRM_DEBUG("returning ...\n"); 954145132Sanholt 955145132Sanholt return failed; 956145132Sanholt} 957145132Sanholt 958145132Sanholt/** 959145132Sanholt * Called during the DMA initialization ioctl to initialize all the necessary 960145132Sanholt * software and hardware state for DMA operation. 961145132Sanholt */ 962182080Srnolandstatic int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init) 963145132Sanholt{ 964145132Sanholt drm_mach64_private_t *dev_priv; 965145132Sanholt u32 tmp; 966145132Sanholt int i, ret; 967145132Sanholt 968182080Srnoland DRM_DEBUG("\n"); 969145132Sanholt 970145132Sanholt dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER); 971145132Sanholt if (dev_priv == NULL) 972182080Srnoland return -ENOMEM; 973145132Sanholt 974145132Sanholt memset(dev_priv, 0, sizeof(drm_mach64_private_t)); 975145132Sanholt 976145132Sanholt dev_priv->is_pci = init->is_pci; 977145132Sanholt 978145132Sanholt dev_priv->fb_bpp = init->fb_bpp; 979145132Sanholt dev_priv->front_offset = init->front_offset; 980145132Sanholt dev_priv->front_pitch = init->front_pitch; 981145132Sanholt dev_priv->back_offset = init->back_offset; 982145132Sanholt dev_priv->back_pitch = init->back_pitch; 983145132Sanholt 984145132Sanholt dev_priv->depth_bpp = init->depth_bpp; 985145132Sanholt dev_priv->depth_offset = init->depth_offset; 986145132Sanholt dev_priv->depth_pitch = init->depth_pitch; 987145132Sanholt 988145132Sanholt dev_priv->front_offset_pitch = (((dev_priv->front_pitch / 8) << 22) | 989145132Sanholt (dev_priv->front_offset >> 3)); 990145132Sanholt dev_priv->back_offset_pitch = (((dev_priv->back_pitch / 8) << 22) | 991145132Sanholt (dev_priv->back_offset >> 3)); 992145132Sanholt dev_priv->depth_offset_pitch = (((dev_priv->depth_pitch / 8) << 22) | 993145132Sanholt (dev_priv->depth_offset >> 3)); 994145132Sanholt 995145132Sanholt dev_priv->usec_timeout = 1000000; 996145132Sanholt 997145132Sanholt /* Set up the freelist, placeholder list and pending list */ 998145132Sanholt INIT_LIST_HEAD(&dev_priv->free_list); 999145132Sanholt INIT_LIST_HEAD(&dev_priv->placeholders); 1000145132Sanholt INIT_LIST_HEAD(&dev_priv->pending); 1001145132Sanholt 1002182080Srnoland dev_priv->sarea = drm_getsarea(dev); 1003145132Sanholt if (!dev_priv->sarea) { 1004145132Sanholt DRM_ERROR("can not find sarea!\n"); 1005145132Sanholt dev->dev_private = (void *)dev_priv; 1006145132Sanholt mach64_do_cleanup_dma(dev); 1007182080Srnoland return -EINVAL; 1008145132Sanholt } 1009145132Sanholt dev_priv->fb = drm_core_findmap(dev, init->fb_offset); 1010145132Sanholt if (!dev_priv->fb) { 1011145132Sanholt DRM_ERROR("can not find frame buffer map!\n"); 1012145132Sanholt dev->dev_private = (void *)dev_priv; 1013145132Sanholt mach64_do_cleanup_dma(dev); 1014182080Srnoland return -EINVAL; 1015145132Sanholt } 1016145132Sanholt dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); 1017145132Sanholt if (!dev_priv->mmio) { 1018145132Sanholt DRM_ERROR("can not find mmio map!\n"); 1019145132Sanholt dev->dev_private = (void *)dev_priv; 1020145132Sanholt mach64_do_cleanup_dma(dev); 1021182080Srnoland return -EINVAL; 1022145132Sanholt } 1023145132Sanholt 1024182080Srnoland dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); 1025182080Srnoland if (!dev_priv->ring_map) { 1026182080Srnoland DRM_ERROR("can not find ring map!\n"); 1027182080Srnoland dev->dev_private = (void *)dev_priv; 1028182080Srnoland mach64_do_cleanup_dma(dev); 1029182080Srnoland return -EINVAL; 1030182080Srnoland } 1031182080Srnoland 1032145132Sanholt dev_priv->sarea_priv = (drm_mach64_sarea_t *) 1033207066Srnoland ((u8 *) dev_priv->sarea->virtual + init->sarea_priv_offset); 1034145132Sanholt 1035145132Sanholt if (!dev_priv->is_pci) { 1036145132Sanholt drm_core_ioremap(dev_priv->ring_map, dev); 1037207066Srnoland if (!dev_priv->ring_map->virtual) { 1038145132Sanholt DRM_ERROR("can not ioremap virtual address for" 1039145132Sanholt " descriptor ring\n"); 1040145132Sanholt dev->dev_private = (void *)dev_priv; 1041145132Sanholt mach64_do_cleanup_dma(dev); 1042182080Srnoland return -ENOMEM; 1043145132Sanholt } 1044182080Srnoland dev->agp_buffer_token = init->buffers_offset; 1045145132Sanholt dev->agp_buffer_map = 1046145132Sanholt drm_core_findmap(dev, init->buffers_offset); 1047145132Sanholt if (!dev->agp_buffer_map) { 1048145132Sanholt DRM_ERROR("can not find dma buffer map!\n"); 1049145132Sanholt dev->dev_private = (void *)dev_priv; 1050145132Sanholt mach64_do_cleanup_dma(dev); 1051182080Srnoland return -EINVAL; 1052145132Sanholt } 1053145132Sanholt /* there might be a nicer way to do this - 1054145132Sanholt dev isn't passed all the way though the mach64 - DA */ 1055145132Sanholt dev_priv->dev_buffers = dev->agp_buffer_map; 1056145132Sanholt 1057145132Sanholt drm_core_ioremap(dev->agp_buffer_map, dev); 1058207066Srnoland if (!dev->agp_buffer_map->virtual) { 1059145132Sanholt DRM_ERROR("can not ioremap virtual address for" 1060145132Sanholt " dma buffer\n"); 1061145132Sanholt dev->dev_private = (void *)dev_priv; 1062145132Sanholt mach64_do_cleanup_dma(dev); 1063182080Srnoland return -ENOMEM; 1064145132Sanholt } 1065145132Sanholt dev_priv->agp_textures = 1066145132Sanholt drm_core_findmap(dev, init->agp_textures_offset); 1067145132Sanholt if (!dev_priv->agp_textures) { 1068145132Sanholt DRM_ERROR("can not find agp texture region!\n"); 1069145132Sanholt dev->dev_private = (void *)dev_priv; 1070145132Sanholt mach64_do_cleanup_dma(dev); 1071182080Srnoland return -EINVAL; 1072145132Sanholt } 1073145132Sanholt } 1074145132Sanholt 1075145132Sanholt dev->dev_private = (void *)dev_priv; 1076145132Sanholt 1077145132Sanholt dev_priv->driver_mode = init->dma_mode; 1078145132Sanholt 1079145132Sanholt /* changing the FIFO size from the default causes problems with DMA */ 1080145132Sanholt tmp = MACH64_READ(MACH64_GUI_CNTL); 1081145132Sanholt if ((tmp & MACH64_CMDFIFO_SIZE_MASK) != MACH64_CMDFIFO_SIZE_128) { 1082145132Sanholt DRM_INFO("Setting FIFO size to 128 entries\n"); 1083145132Sanholt /* FIFO must be empty to change the FIFO depth */ 1084145132Sanholt if ((ret = mach64_do_wait_for_idle(dev_priv))) { 1085145132Sanholt DRM_ERROR 1086145132Sanholt ("wait for idle failed before changing FIFO depth!\n"); 1087145132Sanholt mach64_do_cleanup_dma(dev); 1088145132Sanholt return ret; 1089145132Sanholt } 1090145132Sanholt MACH64_WRITE(MACH64_GUI_CNTL, ((tmp & ~MACH64_CMDFIFO_SIZE_MASK) 1091145132Sanholt | MACH64_CMDFIFO_SIZE_128)); 1092145132Sanholt /* need to read GUI_STAT for proper sync according to docs */ 1093145132Sanholt if ((ret = mach64_do_wait_for_idle(dev_priv))) { 1094145132Sanholt DRM_ERROR 1095145132Sanholt ("wait for idle failed when changing FIFO depth!\n"); 1096145132Sanholt mach64_do_cleanup_dma(dev); 1097145132Sanholt return ret; 1098145132Sanholt } 1099145132Sanholt } 1100145132Sanholt 1101145132Sanholt dev_priv->ring.size = 0x4000; /* 16KB */ 1102207066Srnoland dev_priv->ring.start = dev_priv->ring_map->virtual; 1103182080Srnoland dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; 1104145132Sanholt 1105145132Sanholt memset(dev_priv->ring.start, 0, dev_priv->ring.size); 1106145132Sanholt DRM_INFO("descriptor ring: cpu addr %p, bus addr: 0x%08x\n", 1107145132Sanholt dev_priv->ring.start, dev_priv->ring.start_addr); 1108145132Sanholt 1109145132Sanholt ret = 0; 1110145132Sanholt if (dev_priv->driver_mode != MACH64_MODE_MMIO) { 1111145132Sanholt 1112145132Sanholt /* enable block 1 registers and bus mastering */ 1113145132Sanholt MACH64_WRITE(MACH64_BUS_CNTL, ((MACH64_READ(MACH64_BUS_CNTL) 1114145132Sanholt | MACH64_BUS_EXT_REG_EN) 1115145132Sanholt & ~MACH64_BUS_MASTER_DIS)); 1116145132Sanholt 1117145132Sanholt /* try a DMA GUI-mastering pass and fall back to MMIO if it fails */ 1118145132Sanholt DRM_DEBUG("Starting DMA test...\n"); 1119145132Sanholt if ((ret = mach64_bm_dma_test(dev))) { 1120145132Sanholt dev_priv->driver_mode = MACH64_MODE_MMIO; 1121145132Sanholt } 1122145132Sanholt } 1123145132Sanholt 1124145132Sanholt switch (dev_priv->driver_mode) { 1125145132Sanholt case MACH64_MODE_MMIO: 1126145132Sanholt MACH64_WRITE(MACH64_BUS_CNTL, (MACH64_READ(MACH64_BUS_CNTL) 1127145132Sanholt | MACH64_BUS_EXT_REG_EN 1128145132Sanholt | MACH64_BUS_MASTER_DIS)); 1129145132Sanholt if (init->dma_mode == MACH64_MODE_MMIO) 1130145132Sanholt DRM_INFO("Forcing pseudo-DMA mode\n"); 1131145132Sanholt else 1132145132Sanholt DRM_INFO 1133145132Sanholt ("DMA test failed (ret=%d), using pseudo-DMA mode\n", 1134145132Sanholt ret); 1135145132Sanholt break; 1136145132Sanholt case MACH64_MODE_DMA_SYNC: 1137145132Sanholt DRM_INFO("DMA test succeeded, using synchronous DMA mode\n"); 1138145132Sanholt break; 1139145132Sanholt case MACH64_MODE_DMA_ASYNC: 1140145132Sanholt default: 1141145132Sanholt DRM_INFO("DMA test succeeded, using asynchronous DMA mode\n"); 1142145132Sanholt } 1143145132Sanholt 1144145132Sanholt dev_priv->ring_running = 0; 1145145132Sanholt 1146145132Sanholt /* setup offsets for physical address of table start and end */ 1147145132Sanholt dev_priv->ring.head_addr = dev_priv->ring.start_addr; 1148145132Sanholt dev_priv->ring.head = dev_priv->ring.tail = 0; 1149145132Sanholt dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; 1150145132Sanholt dev_priv->ring.space = dev_priv->ring.size; 1151145132Sanholt 1152145132Sanholt /* setup physical address and size of descriptor table */ 1153145132Sanholt mach64_do_wait_for_fifo(dev_priv, 1); 1154145132Sanholt MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 1155145132Sanholt (dev_priv->ring. 1156145132Sanholt head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB)); 1157145132Sanholt 1158145132Sanholt /* init frame counter */ 1159145132Sanholt dev_priv->sarea_priv->frames_queued = 0; 1160145132Sanholt for (i = 0; i < MACH64_MAX_QUEUED_FRAMES; i++) { 1161145132Sanholt dev_priv->frame_ofs[i] = ~0; /* All ones indicates placeholder */ 1162145132Sanholt } 1163145132Sanholt 1164145132Sanholt /* Allocate the DMA buffer freelist */ 1165145132Sanholt if ((ret = mach64_init_freelist(dev))) { 1166145132Sanholt DRM_ERROR("Freelist allocation failed\n"); 1167145132Sanholt mach64_do_cleanup_dma(dev); 1168145132Sanholt return ret; 1169145132Sanholt } 1170145132Sanholt 1171145132Sanholt return 0; 1172145132Sanholt} 1173145132Sanholt 1174145132Sanholt/*******************************************************************/ 1175145132Sanholt/** MMIO Pseudo-DMA (intended primarily for debugging, not performance) 1176145132Sanholt */ 1177145132Sanholt 1178182080Srnolandint mach64_do_dispatch_pseudo_dma(drm_mach64_private_t *dev_priv) 1179145132Sanholt{ 1180145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 1181145132Sanholt volatile u32 *ring_read; 1182145132Sanholt struct list_head *ptr; 1183145132Sanholt drm_mach64_freelist_t *entry; 1184182080Srnoland struct drm_buf *buf = NULL; 1185145132Sanholt u32 *buf_ptr; 1186145132Sanholt u32 used, reg, target; 1187145132Sanholt int fifo, count, found, ret, no_idle_wait; 1188145132Sanholt 1189145132Sanholt fifo = count = reg = no_idle_wait = 0; 1190145132Sanholt target = MACH64_BM_ADDR; 1191145132Sanholt 1192145132Sanholt if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) { 1193182080Srnoland DRM_INFO("idle failed before pseudo-dma dispatch, resetting engine\n"); 1194145132Sanholt mach64_dump_engine_info(dev_priv); 1195145132Sanholt mach64_do_engine_reset(dev_priv); 1196145132Sanholt return ret; 1197145132Sanholt } 1198145132Sanholt 1199145132Sanholt ring_read = (u32 *) ring->start; 1200145132Sanholt 1201145132Sanholt while (ring->tail != ring->head) { 1202145132Sanholt u32 buf_addr, new_target, offset; 1203145132Sanholt u32 bytes, remaining, head, eol; 1204145132Sanholt 1205145132Sanholt head = ring->head; 1206145132Sanholt 1207145132Sanholt new_target = 1208145132Sanholt le32_to_cpu(ring_read[head++]) - MACH64_APERTURE_OFFSET; 1209145132Sanholt buf_addr = le32_to_cpu(ring_read[head++]); 1210145132Sanholt eol = le32_to_cpu(ring_read[head]) & MACH64_DMA_EOL; 1211145132Sanholt bytes = le32_to_cpu(ring_read[head++]) 1212145132Sanholt & ~(MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL); 1213145132Sanholt head++; 1214145132Sanholt head &= ring->tail_mask; 1215145132Sanholt 1216145132Sanholt /* can't wait for idle between a blit setup descriptor 1217145132Sanholt * and a HOSTDATA descriptor or the engine will lock 1218145132Sanholt */ 1219145132Sanholt if (new_target == MACH64_BM_HOSTDATA 1220145132Sanholt && target == MACH64_BM_ADDR) 1221145132Sanholt no_idle_wait = 1; 1222145132Sanholt 1223145132Sanholt target = new_target; 1224145132Sanholt 1225145132Sanholt found = 0; 1226145132Sanholt offset = 0; 1227145132Sanholt list_for_each(ptr, &dev_priv->pending) { 1228145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1229145132Sanholt buf = entry->buf; 1230145132Sanholt offset = buf_addr - GETBUFADDR(buf); 1231249816Sjkim if (offset < MACH64_BUFFER_SIZE) { 1232145132Sanholt found = 1; 1233145132Sanholt break; 1234145132Sanholt } 1235145132Sanholt } 1236145132Sanholt 1237145132Sanholt if (!found || buf == NULL) { 1238145132Sanholt DRM_ERROR 1239145132Sanholt ("Couldn't find pending buffer: head: %u tail: %u buf_addr: 0x%08x %s\n", 1240145132Sanholt head, ring->tail, buf_addr, (eol ? "eol" : "")); 1241145132Sanholt mach64_dump_ring_info(dev_priv); 1242145132Sanholt mach64_do_engine_reset(dev_priv); 1243182080Srnoland return -EINVAL; 1244145132Sanholt } 1245145132Sanholt 1246145132Sanholt /* Hand feed the buffer to the card via MMIO, waiting for the fifo 1247145132Sanholt * every 16 writes 1248145132Sanholt */ 1249145132Sanholt DRM_DEBUG("target: (0x%08x) %s\n", target, 1250145132Sanholt (target == 1251145132Sanholt MACH64_BM_HOSTDATA ? "BM_HOSTDATA" : "BM_ADDR")); 1252145132Sanholt DRM_DEBUG("offset: %u bytes: %u used: %u\n", offset, bytes, 1253145132Sanholt buf->used); 1254145132Sanholt 1255145132Sanholt remaining = (buf->used - offset) >> 2; /* dwords remaining in buffer */ 1256145132Sanholt used = bytes >> 2; /* dwords in buffer for this descriptor */ 1257145132Sanholt buf_ptr = (u32 *) ((char *)GETBUFPTR(buf) + offset); 1258145132Sanholt 1259145132Sanholt while (used) { 1260145132Sanholt 1261145132Sanholt if (count == 0) { 1262145132Sanholt if (target == MACH64_BM_HOSTDATA) { 1263145132Sanholt reg = DMAREG(MACH64_HOST_DATA0); 1264145132Sanholt count = 1265145132Sanholt (remaining > 16) ? 16 : remaining; 1266145132Sanholt fifo = 0; 1267145132Sanholt } else { 1268145132Sanholt reg = le32_to_cpu(*buf_ptr++); 1269145132Sanholt used--; 1270145132Sanholt count = (reg >> 16) + 1; 1271145132Sanholt } 1272145132Sanholt 1273145132Sanholt reg = reg & 0xffff; 1274145132Sanholt reg = MMSELECT(reg); 1275145132Sanholt } 1276145132Sanholt while (count && used) { 1277145132Sanholt if (!fifo) { 1278145132Sanholt if (no_idle_wait) { 1279145132Sanholt if ((ret = 1280145132Sanholt mach64_do_wait_for_fifo 1281145132Sanholt (dev_priv, 16)) < 0) { 1282145132Sanholt no_idle_wait = 0; 1283145132Sanholt return ret; 1284145132Sanholt } 1285145132Sanholt } else { 1286145132Sanholt if ((ret = 1287145132Sanholt mach64_do_wait_for_idle 1288145132Sanholt (dev_priv)) < 0) { 1289145132Sanholt return ret; 1290145132Sanholt } 1291145132Sanholt } 1292145132Sanholt fifo = 16; 1293145132Sanholt } 1294145132Sanholt --fifo; 1295145132Sanholt MACH64_WRITE(reg, le32_to_cpu(*buf_ptr++)); 1296145132Sanholt used--; 1297145132Sanholt remaining--; 1298145132Sanholt 1299145132Sanholt reg += 4; 1300145132Sanholt count--; 1301145132Sanholt } 1302145132Sanholt } 1303145132Sanholt ring->head = head; 1304145132Sanholt ring->head_addr = ring->start_addr + (ring->head * sizeof(u32)); 1305145132Sanholt ring->space += (4 * sizeof(u32)); 1306145132Sanholt } 1307145132Sanholt 1308145132Sanholt if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) { 1309145132Sanholt return ret; 1310145132Sanholt } 1311145132Sanholt MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 1312145132Sanholt ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 1313145132Sanholt 1314182080Srnoland DRM_DEBUG("completed\n"); 1315145132Sanholt return 0; 1316145132Sanholt} 1317145132Sanholt 1318145132Sanholt/*@}*/ 1319145132Sanholt 1320145132Sanholt 1321145132Sanholt/*******************************************************************/ 1322145132Sanholt/** \name DMA cleanup */ 1323145132Sanholt/*@{*/ 1324145132Sanholt 1325182080Srnolandint mach64_do_cleanup_dma(struct drm_device * dev) 1326145132Sanholt{ 1327182080Srnoland DRM_DEBUG("\n"); 1328145132Sanholt 1329145132Sanholt /* Make sure interrupts are disabled here because the uninstall ioctl 1330145132Sanholt * may not have been called from userspace and after dev_private 1331145132Sanholt * is freed, it's too late. 1332145132Sanholt */ 1333145132Sanholt if (dev->irq) 1334145132Sanholt drm_irq_uninstall(dev); 1335145132Sanholt 1336145132Sanholt if (dev->dev_private) { 1337145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1338145132Sanholt 1339182080Srnoland if (!dev_priv->is_pci) { 1340145132Sanholt if (dev_priv->ring_map) 1341145132Sanholt drm_core_ioremapfree(dev_priv->ring_map, dev); 1342145132Sanholt 1343182080Srnoland if (dev->agp_buffer_map) { 1344182080Srnoland drm_core_ioremapfree(dev->agp_buffer_map, dev); 1345182080Srnoland dev->agp_buffer_map = NULL; 1346182080Srnoland } 1347145132Sanholt } 1348145132Sanholt 1349145132Sanholt mach64_destroy_freelist(dev); 1350145132Sanholt 1351145132Sanholt drm_free(dev_priv, sizeof(drm_mach64_private_t), 1352145132Sanholt DRM_MEM_DRIVER); 1353145132Sanholt dev->dev_private = NULL; 1354145132Sanholt } 1355145132Sanholt 1356145132Sanholt return 0; 1357145132Sanholt} 1358145132Sanholt 1359145132Sanholt/*@}*/ 1360145132Sanholt 1361145132Sanholt 1362145132Sanholt/*******************************************************************/ 1363145132Sanholt/** \name IOCTL handlers */ 1364145132Sanholt/*@{*/ 1365145132Sanholt 1366182080Srnolandint mach64_dma_init(struct drm_device *dev, void *data, 1367182080Srnoland struct drm_file *file_priv) 1368145132Sanholt{ 1369182080Srnoland drm_mach64_init_t *init = data; 1370145132Sanholt 1371182080Srnoland DRM_DEBUG("\n"); 1372145132Sanholt 1373182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1374145132Sanholt 1375182080Srnoland switch (init->func) { 1376145132Sanholt case DRM_MACH64_INIT_DMA: 1377182080Srnoland return mach64_do_dma_init(dev, init); 1378145132Sanholt case DRM_MACH64_CLEANUP_DMA: 1379145132Sanholt return mach64_do_cleanup_dma(dev); 1380145132Sanholt } 1381145132Sanholt 1382182080Srnoland return -EINVAL; 1383145132Sanholt} 1384145132Sanholt 1385182080Srnolandint mach64_dma_idle(struct drm_device *dev, void *data, 1386182080Srnoland struct drm_file *file_priv) 1387145132Sanholt{ 1388145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1389145132Sanholt 1390182080Srnoland DRM_DEBUG("\n"); 1391145132Sanholt 1392182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1393145132Sanholt 1394145132Sanholt return mach64_do_dma_idle(dev_priv); 1395145132Sanholt} 1396145132Sanholt 1397182080Srnolandint mach64_dma_flush(struct drm_device *dev, void *data, 1398182080Srnoland struct drm_file *file_priv) 1399145132Sanholt{ 1400145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1401145132Sanholt 1402182080Srnoland DRM_DEBUG("\n"); 1403145132Sanholt 1404182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1405145132Sanholt 1406145132Sanholt return mach64_do_dma_flush(dev_priv); 1407145132Sanholt} 1408145132Sanholt 1409182080Srnolandint mach64_engine_reset(struct drm_device *dev, void *data, 1410182080Srnoland struct drm_file *file_priv) 1411145132Sanholt{ 1412145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1413145132Sanholt 1414182080Srnoland DRM_DEBUG("\n"); 1415145132Sanholt 1416182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1417145132Sanholt 1418145132Sanholt return mach64_do_engine_reset(dev_priv); 1419145132Sanholt} 1420145132Sanholt 1421145132Sanholt/*@}*/ 1422145132Sanholt 1423145132Sanholt 1424145132Sanholt/*******************************************************************/ 1425145132Sanholt/** \name Freelist management */ 1426145132Sanholt/*@{*/ 1427145132Sanholt 1428182080Srnolandint mach64_init_freelist(struct drm_device * dev) 1429145132Sanholt{ 1430182080Srnoland struct drm_device_dma *dma = dev->dma; 1431145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1432145132Sanholt drm_mach64_freelist_t *entry; 1433145132Sanholt struct list_head *ptr; 1434145132Sanholt int i; 1435145132Sanholt 1436182080Srnoland DRM_DEBUG("adding %d buffers to freelist\n", dma->buf_count); 1437145132Sanholt 1438145132Sanholt for (i = 0; i < dma->buf_count; i++) { 1439145132Sanholt if ((entry = 1440145132Sanholt (drm_mach64_freelist_t *) 1441145132Sanholt drm_alloc(sizeof(drm_mach64_freelist_t), 1442145132Sanholt DRM_MEM_BUFLISTS)) == NULL) 1443182080Srnoland return -ENOMEM; 1444145132Sanholt memset(entry, 0, sizeof(drm_mach64_freelist_t)); 1445145132Sanholt entry->buf = dma->buflist[i]; 1446145132Sanholt ptr = &entry->list; 1447145132Sanholt list_add_tail(ptr, &dev_priv->free_list); 1448145132Sanholt } 1449145132Sanholt 1450145132Sanholt return 0; 1451145132Sanholt} 1452145132Sanholt 1453182080Srnolandvoid mach64_destroy_freelist(struct drm_device * dev) 1454145132Sanholt{ 1455145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1456145132Sanholt drm_mach64_freelist_t *entry; 1457145132Sanholt struct list_head *ptr; 1458145132Sanholt struct list_head *tmp; 1459145132Sanholt 1460182080Srnoland DRM_DEBUG("\n"); 1461145132Sanholt 1462145132Sanholt list_for_each_safe(ptr, tmp, &dev_priv->pending) { 1463145132Sanholt list_del(ptr); 1464145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1465145132Sanholt drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); 1466145132Sanholt } 1467145132Sanholt list_for_each_safe(ptr, tmp, &dev_priv->placeholders) { 1468145132Sanholt list_del(ptr); 1469145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1470145132Sanholt drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); 1471145132Sanholt } 1472145132Sanholt 1473145132Sanholt list_for_each_safe(ptr, tmp, &dev_priv->free_list) { 1474145132Sanholt list_del(ptr); 1475145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1476145132Sanholt drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS); 1477145132Sanholt } 1478145132Sanholt} 1479145132Sanholt 1480145132Sanholt/* IMPORTANT: This function should only be called when the engine is idle or locked up, 1481145132Sanholt * as it assumes all buffers in the pending list have been completed by the hardware. 1482145132Sanholt */ 1483182080Srnolandint mach64_do_release_used_buffers(drm_mach64_private_t *dev_priv) 1484145132Sanholt{ 1485145132Sanholt struct list_head *ptr; 1486145132Sanholt struct list_head *tmp; 1487145132Sanholt drm_mach64_freelist_t *entry; 1488145132Sanholt int i; 1489145132Sanholt 1490145132Sanholt if (list_empty(&dev_priv->pending)) 1491145132Sanholt return 0; 1492145132Sanholt 1493145132Sanholt /* Iterate the pending list and move all buffers into the freelist... */ 1494145132Sanholt i = 0; 1495145132Sanholt list_for_each_safe(ptr, tmp, &dev_priv->pending) { 1496145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1497145132Sanholt if (entry->discard) { 1498145132Sanholt entry->buf->pending = 0; 1499145132Sanholt list_del(ptr); 1500145132Sanholt list_add_tail(ptr, &dev_priv->free_list); 1501145132Sanholt i++; 1502145132Sanholt } 1503145132Sanholt } 1504145132Sanholt 1505182080Srnoland DRM_DEBUG("released %d buffers from pending list\n", i); 1506145132Sanholt 1507145132Sanholt return 0; 1508145132Sanholt} 1509145132Sanholt 1510182080Srnolandstatic int mach64_do_reclaim_completed(drm_mach64_private_t *dev_priv) 1511145132Sanholt{ 1512145132Sanholt drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 1513182080Srnoland struct list_head *ptr; 1514182080Srnoland struct list_head *tmp; 1515145132Sanholt drm_mach64_freelist_t *entry; 1516182080Srnoland u32 head, tail, ofs; 1517182080Srnoland 1518182080Srnoland mach64_ring_tick(dev_priv, ring); 1519182080Srnoland head = ring->head; 1520182080Srnoland tail = ring->tail; 1521182080Srnoland 1522182080Srnoland if (head == tail) { 1523182080Srnoland#if MACH64_EXTRA_CHECKING 1524182080Srnoland if (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) { 1525182080Srnoland DRM_ERROR("Empty ring with non-idle engine!\n"); 1526182080Srnoland mach64_dump_ring_info(dev_priv); 1527182080Srnoland return -1; 1528182080Srnoland } 1529182080Srnoland#endif 1530182080Srnoland /* last pass is complete, so release everything */ 1531182080Srnoland mach64_do_release_used_buffers(dev_priv); 1532182080Srnoland DRM_DEBUG("idle engine, freed all buffers.\n"); 1533182080Srnoland if (list_empty(&dev_priv->free_list)) { 1534182080Srnoland DRM_ERROR("Freelist empty with idle engine\n"); 1535182080Srnoland return -1; 1536182080Srnoland } 1537182080Srnoland return 0; 1538182080Srnoland } 1539182080Srnoland /* Look for a completed buffer and bail out of the loop 1540182080Srnoland * as soon as we find one -- don't waste time trying 1541182080Srnoland * to free extra bufs here, leave that to do_release_used_buffers 1542182080Srnoland */ 1543182080Srnoland list_for_each_safe(ptr, tmp, &dev_priv->pending) { 1544182080Srnoland entry = list_entry(ptr, drm_mach64_freelist_t, list); 1545182080Srnoland ofs = entry->ring_ofs; 1546182080Srnoland if (entry->discard && 1547182080Srnoland ((head < tail && (ofs < head || ofs >= tail)) || 1548182080Srnoland (head > tail && (ofs < head && ofs >= tail)))) { 1549182080Srnoland#if MACH64_EXTRA_CHECKING 1550182080Srnoland int i; 1551182080Srnoland 1552182080Srnoland for (i = head; i != tail; i = (i + 4) & ring->tail_mask) 1553182080Srnoland { 1554182080Srnoland u32 o1 = le32_to_cpu(((u32 *) ring-> 1555182080Srnoland start)[i + 1]); 1556182080Srnoland u32 o2 = GETBUFADDR(entry->buf); 1557182080Srnoland 1558182080Srnoland if (o1 == o2) { 1559182080Srnoland DRM_ERROR 1560182080Srnoland ("Attempting to free used buffer: " 1561182080Srnoland "i=%d buf=0x%08x\n", 1562182080Srnoland i, o1); 1563182080Srnoland mach64_dump_ring_info(dev_priv); 1564182080Srnoland return -1; 1565182080Srnoland } 1566182080Srnoland } 1567182080Srnoland#endif 1568182080Srnoland /* found a processed buffer */ 1569182080Srnoland entry->buf->pending = 0; 1570182080Srnoland list_del(ptr); 1571182080Srnoland list_add_tail(ptr, &dev_priv->free_list); 1572182080Srnoland DRM_DEBUG 1573182080Srnoland ("freed processed buffer (head=%d tail=%d " 1574182080Srnoland "buf ring ofs=%d).\n", 1575182080Srnoland head, tail, ofs); 1576182080Srnoland return 0; 1577182080Srnoland } 1578182080Srnoland } 1579182080Srnoland 1580182080Srnoland return 1; 1581182080Srnoland} 1582182080Srnoland 1583182080Srnolandstruct drm_buf *mach64_freelist_get(drm_mach64_private_t *dev_priv) 1584182080Srnoland{ 1585182080Srnoland drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 1586182080Srnoland drm_mach64_freelist_t *entry; 1587145132Sanholt struct list_head *ptr; 1588145132Sanholt int t; 1589145132Sanholt 1590145132Sanholt if (list_empty(&dev_priv->free_list)) { 1591145132Sanholt if (list_empty(&dev_priv->pending)) { 1592145132Sanholt DRM_ERROR 1593145132Sanholt ("Couldn't get buffer - pending and free lists empty\n"); 1594145132Sanholt t = 0; 1595145132Sanholt list_for_each(ptr, &dev_priv->placeholders) { 1596145132Sanholt t++; 1597145132Sanholt } 1598145132Sanholt DRM_INFO("Placeholders: %d\n", t); 1599145132Sanholt return NULL; 1600145132Sanholt } 1601145132Sanholt 1602145132Sanholt for (t = 0; t < dev_priv->usec_timeout; t++) { 1603182080Srnoland int ret; 1604145132Sanholt 1605182080Srnoland ret = mach64_do_reclaim_completed(dev_priv); 1606182080Srnoland if (ret == 0) 1607145132Sanholt goto _freelist_entry_found; 1608182080Srnoland if (ret < 0) 1609182080Srnoland return NULL; 1610145132Sanholt 1611145132Sanholt DRM_UDELAY(1); 1612145132Sanholt } 1613145132Sanholt mach64_dump_ring_info(dev_priv); 1614145132Sanholt DRM_ERROR 1615145132Sanholt ("timeout waiting for buffers: ring head_addr: 0x%08x head: %d tail: %d\n", 1616145132Sanholt ring->head_addr, ring->head, ring->tail); 1617145132Sanholt return NULL; 1618145132Sanholt } 1619145132Sanholt 1620145132Sanholt _freelist_entry_found: 1621145132Sanholt ptr = dev_priv->free_list.next; 1622145132Sanholt list_del(ptr); 1623145132Sanholt entry = list_entry(ptr, drm_mach64_freelist_t, list); 1624145132Sanholt entry->buf->used = 0; 1625145132Sanholt list_add_tail(ptr, &dev_priv->placeholders); 1626145132Sanholt return entry->buf; 1627145132Sanholt} 1628145132Sanholt 1629182080Srnolandint mach64_freelist_put(drm_mach64_private_t *dev_priv, struct drm_buf *copy_buf) 1630182080Srnoland{ 1631182080Srnoland struct list_head *ptr; 1632182080Srnoland drm_mach64_freelist_t *entry; 1633182080Srnoland 1634182080Srnoland#if MACH64_EXTRA_CHECKING 1635182080Srnoland list_for_each(ptr, &dev_priv->pending) { 1636182080Srnoland entry = list_entry(ptr, drm_mach64_freelist_t, list); 1637182080Srnoland if (copy_buf == entry->buf) { 1638182080Srnoland DRM_ERROR("Trying to release a pending buf\n"); 1639182080Srnoland return -EFAULT; 1640182080Srnoland } 1641182080Srnoland } 1642182080Srnoland#endif 1643182080Srnoland ptr = dev_priv->placeholders.next; 1644182080Srnoland entry = list_entry(ptr, drm_mach64_freelist_t, list); 1645182080Srnoland copy_buf->pending = 0; 1646182080Srnoland copy_buf->used = 0; 1647182080Srnoland entry->buf = copy_buf; 1648182080Srnoland entry->discard = 1; 1649182080Srnoland list_del(ptr); 1650182080Srnoland list_add_tail(ptr, &dev_priv->free_list); 1651182080Srnoland 1652182080Srnoland return 0; 1653182080Srnoland} 1654182080Srnoland 1655145132Sanholt/*@}*/ 1656145132Sanholt 1657145132Sanholt 1658145132Sanholt/*******************************************************************/ 1659145132Sanholt/** \name DMA buffer request and submission IOCTL handler */ 1660145132Sanholt/*@{*/ 1661145132Sanholt 1662182080Srnolandstatic int mach64_dma_get_buffers(struct drm_device *dev, 1663182080Srnoland struct drm_file *file_priv, 1664182080Srnoland struct drm_dma * d) 1665145132Sanholt{ 1666145132Sanholt int i; 1667182080Srnoland struct drm_buf *buf; 1668145132Sanholt drm_mach64_private_t *dev_priv = dev->dev_private; 1669145132Sanholt 1670145132Sanholt for (i = d->granted_count; i < d->request_count; i++) { 1671145132Sanholt buf = mach64_freelist_get(dev_priv); 1672145132Sanholt#if MACH64_EXTRA_CHECKING 1673145132Sanholt if (!buf) 1674182080Srnoland return -EFAULT; 1675145132Sanholt#else 1676145132Sanholt if (!buf) 1677182080Srnoland return -EAGAIN; 1678145132Sanholt#endif 1679145132Sanholt 1680182080Srnoland buf->file_priv = file_priv; 1681145132Sanholt 1682145132Sanholt if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, 1683145132Sanholt sizeof(buf->idx))) 1684182080Srnoland return -EFAULT; 1685145132Sanholt if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, 1686145132Sanholt sizeof(buf->total))) 1687182080Srnoland return -EFAULT; 1688145132Sanholt 1689145132Sanholt d->granted_count++; 1690145132Sanholt } 1691145132Sanholt return 0; 1692145132Sanholt} 1693145132Sanholt 1694182080Srnolandint mach64_dma_buffers(struct drm_device *dev, void *data, 1695182080Srnoland struct drm_file *file_priv) 1696145132Sanholt{ 1697182080Srnoland struct drm_device_dma *dma = dev->dma; 1698182080Srnoland struct drm_dma *d = data; 1699145132Sanholt int ret = 0; 1700145132Sanholt 1701182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1702145132Sanholt 1703145132Sanholt /* Please don't send us buffers. 1704145132Sanholt */ 1705182080Srnoland if (d->send_count != 0) { 1706145132Sanholt DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", 1707182080Srnoland DRM_CURRENTPID, d->send_count); 1708182080Srnoland return -EINVAL; 1709145132Sanholt } 1710145132Sanholt 1711145132Sanholt /* We'll send you buffers. 1712145132Sanholt */ 1713182080Srnoland if (d->request_count < 0 || d->request_count > dma->buf_count) { 1714145132Sanholt DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", 1715182080Srnoland DRM_CURRENTPID, d->request_count, dma->buf_count); 1716182080Srnoland ret = -EINVAL; 1717145132Sanholt } 1718145132Sanholt 1719182080Srnoland d->granted_count = 0; 1720145132Sanholt 1721182080Srnoland if (d->request_count) { 1722182080Srnoland ret = mach64_dma_get_buffers(dev, file_priv, d); 1723145132Sanholt } 1724145132Sanholt 1725145132Sanholt return ret; 1726145132Sanholt} 1727145132Sanholt 1728182080Srnolandvoid mach64_driver_lastclose(struct drm_device * dev) 1729145132Sanholt{ 1730145132Sanholt mach64_do_cleanup_dma(dev); 1731145132Sanholt} 1732145132Sanholt 1733145132Sanholt/*@}*/ 1734