radeon_cp.c revision 95746
195584Sanholt/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- 295584Sanholt * 395584Sanholt * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. 495584Sanholt * Copyright 2000 VA Linux Systems, Inc., Fremont, California. 595584Sanholt * All Rights Reserved. 695584Sanholt * 795584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 895584Sanholt * copy of this software and associated documentation files (the "Software"), 995584Sanholt * to deal in the Software without restriction, including without limitation 1095584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1195584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1295584Sanholt * Software is furnished to do so, subject to the following conditions: 1395584Sanholt * 1495584Sanholt * The above copyright notice and this permission notice (including the next 1595584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1695584Sanholt * Software. 1795584Sanholt * 1895584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1995584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2095584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2195584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2295584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2395584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2495584Sanholt * DEALINGS IN THE SOFTWARE. 2595584Sanholt * 2695584Sanholt * Authors: 2795584Sanholt * Kevin E. Martin <martin@valinux.com> 2895584Sanholt * Gareth Hughes <gareth@valinux.com> 2995584Sanholt * 3095584Sanholt * $FreeBSD: head/sys/dev/drm/radeon_cp.c 95746 2002-04-29 18:18:42Z anholt $ 3195584Sanholt */ 3295584Sanholt 3395584Sanholt#include "dev/drm/radeon.h" 3495584Sanholt#include "dev/drm/drmP.h" 3595746Sanholt#include "dev/drm/radeon_drm.h" 3695584Sanholt#include "dev/drm/radeon_drv.h" 3795584Sanholt 3895584Sanholt#ifdef __linux__ 3995584Sanholt#define __NO_VERSION__ 4095584Sanholt#include <linux/interrupt.h> /* For task queue support */ 4195584Sanholt#include <linux/delay.h> 4295584Sanholt#endif /* __linux__ */ 4395584Sanholt#ifdef __FreeBSD__ 4495584Sanholt#include <vm/vm.h> 4595584Sanholt#include <vm/pmap.h> 4695584Sanholt#endif /* __FreeBSD__ */ 4795584Sanholt 4895584Sanholt#define RADEON_FIFO_DEBUG 0 4995584Sanholt 5095584Sanholt#if defined(__alpha__) 5195584Sanholt# define PCIGART_ENABLED 5295584Sanholt#else 5395584Sanholt# undef PCIGART_ENABLED 5495584Sanholt#endif 5595584Sanholt 5695584Sanholt 5795584Sanholt/* CP microcode (from ATI) */ 5895584Sanholtstatic u32 radeon_cp_microcode[][2] = { 5995584Sanholt { 0x21007000, 0000000000 }, 6095584Sanholt { 0x20007000, 0000000000 }, 6195584Sanholt { 0x000000b4, 0x00000004 }, 6295584Sanholt { 0x000000b8, 0x00000004 }, 6395584Sanholt { 0x6f5b4d4c, 0000000000 }, 6495584Sanholt { 0x4c4c427f, 0000000000 }, 6595584Sanholt { 0x5b568a92, 0000000000 }, 6695584Sanholt { 0x4ca09c6d, 0000000000 }, 6795584Sanholt { 0xad4c4c4c, 0000000000 }, 6895584Sanholt { 0x4ce1af3d, 0000000000 }, 6995584Sanholt { 0xd8afafaf, 0000000000 }, 7095584Sanholt { 0xd64c4cdc, 0000000000 }, 7195584Sanholt { 0x4cd10d10, 0000000000 }, 7295584Sanholt { 0x000f0000, 0x00000016 }, 7395584Sanholt { 0x362f242d, 0000000000 }, 7495584Sanholt { 0x00000012, 0x00000004 }, 7595584Sanholt { 0x000f0000, 0x00000016 }, 7695584Sanholt { 0x362f282d, 0000000000 }, 7795584Sanholt { 0x000380e7, 0x00000002 }, 7895584Sanholt { 0x04002c97, 0x00000002 }, 7995584Sanholt { 0x000f0001, 0x00000016 }, 8095584Sanholt { 0x333a3730, 0000000000 }, 8195584Sanholt { 0x000077ef, 0x00000002 }, 8295584Sanholt { 0x00061000, 0x00000002 }, 8395584Sanholt { 0x00000021, 0x0000001a }, 8495584Sanholt { 0x00004000, 0x0000001e }, 8595584Sanholt { 0x00061000, 0x00000002 }, 8695584Sanholt { 0x00000021, 0x0000001a }, 8795584Sanholt { 0x00004000, 0x0000001e }, 8895584Sanholt { 0x00061000, 0x00000002 }, 8995584Sanholt { 0x00000021, 0x0000001a }, 9095584Sanholt { 0x00004000, 0x0000001e }, 9195584Sanholt { 0x00000017, 0x00000004 }, 9295584Sanholt { 0x0003802b, 0x00000002 }, 9395584Sanholt { 0x040067e0, 0x00000002 }, 9495584Sanholt { 0x00000017, 0x00000004 }, 9595584Sanholt { 0x000077e0, 0x00000002 }, 9695584Sanholt { 0x00065000, 0x00000002 }, 9795584Sanholt { 0x000037e1, 0x00000002 }, 9895584Sanholt { 0x040067e1, 0x00000006 }, 9995584Sanholt { 0x000077e0, 0x00000002 }, 10095584Sanholt { 0x000077e1, 0x00000002 }, 10195584Sanholt { 0x000077e1, 0x00000006 }, 10295584Sanholt { 0xffffffff, 0000000000 }, 10395584Sanholt { 0x10000000, 0000000000 }, 10495584Sanholt { 0x0003802b, 0x00000002 }, 10595584Sanholt { 0x040067e0, 0x00000006 }, 10695584Sanholt { 0x00007675, 0x00000002 }, 10795584Sanholt { 0x00007676, 0x00000002 }, 10895584Sanholt { 0x00007677, 0x00000002 }, 10995584Sanholt { 0x00007678, 0x00000006 }, 11095584Sanholt { 0x0003802c, 0x00000002 }, 11195584Sanholt { 0x04002676, 0x00000002 }, 11295584Sanholt { 0x00007677, 0x00000002 }, 11395584Sanholt { 0x00007678, 0x00000006 }, 11495584Sanholt { 0x0000002f, 0x00000018 }, 11595584Sanholt { 0x0000002f, 0x00000018 }, 11695584Sanholt { 0000000000, 0x00000006 }, 11795584Sanholt { 0x00000030, 0x00000018 }, 11895584Sanholt { 0x00000030, 0x00000018 }, 11995584Sanholt { 0000000000, 0x00000006 }, 12095584Sanholt { 0x01605000, 0x00000002 }, 12195584Sanholt { 0x00065000, 0x00000002 }, 12295584Sanholt { 0x00098000, 0x00000002 }, 12395584Sanholt { 0x00061000, 0x00000002 }, 12495584Sanholt { 0x64c0603e, 0x00000004 }, 12595584Sanholt { 0x000380e6, 0x00000002 }, 12695584Sanholt { 0x040025c5, 0x00000002 }, 12795584Sanholt { 0x00080000, 0x00000016 }, 12895584Sanholt { 0000000000, 0000000000 }, 12995584Sanholt { 0x0400251d, 0x00000002 }, 13095584Sanholt { 0x00007580, 0x00000002 }, 13195584Sanholt { 0x00067581, 0x00000002 }, 13295584Sanholt { 0x04002580, 0x00000002 }, 13395584Sanholt { 0x00067581, 0x00000002 }, 13495584Sanholt { 0x00000049, 0x00000004 }, 13595584Sanholt { 0x00005000, 0000000000 }, 13695584Sanholt { 0x000380e6, 0x00000002 }, 13795584Sanholt { 0x040025c5, 0x00000002 }, 13895584Sanholt { 0x00061000, 0x00000002 }, 13995584Sanholt { 0x0000750e, 0x00000002 }, 14095584Sanholt { 0x00019000, 0x00000002 }, 14195584Sanholt { 0x00011055, 0x00000014 }, 14295584Sanholt { 0x00000055, 0x00000012 }, 14395584Sanholt { 0x0400250f, 0x00000002 }, 14495584Sanholt { 0x0000504f, 0x00000004 }, 14595584Sanholt { 0x000380e6, 0x00000002 }, 14695584Sanholt { 0x040025c5, 0x00000002 }, 14795584Sanholt { 0x00007565, 0x00000002 }, 14895584Sanholt { 0x00007566, 0x00000002 }, 14995584Sanholt { 0x00000058, 0x00000004 }, 15095584Sanholt { 0x000380e6, 0x00000002 }, 15195584Sanholt { 0x040025c5, 0x00000002 }, 15295584Sanholt { 0x01e655b4, 0x00000002 }, 15395584Sanholt { 0x4401b0e4, 0x00000002 }, 15495584Sanholt { 0x01c110e4, 0x00000002 }, 15595584Sanholt { 0x26667066, 0x00000018 }, 15695584Sanholt { 0x040c2565, 0x00000002 }, 15795584Sanholt { 0x00000066, 0x00000018 }, 15895584Sanholt { 0x04002564, 0x00000002 }, 15995584Sanholt { 0x00007566, 0x00000002 }, 16095584Sanholt { 0x0000005d, 0x00000004 }, 16195584Sanholt { 0x00401069, 0x00000008 }, 16295584Sanholt { 0x00101000, 0x00000002 }, 16395584Sanholt { 0x000d80ff, 0x00000002 }, 16495584Sanholt { 0x0080006c, 0x00000008 }, 16595584Sanholt { 0x000f9000, 0x00000002 }, 16695584Sanholt { 0x000e00ff, 0x00000002 }, 16795584Sanholt { 0000000000, 0x00000006 }, 16895584Sanholt { 0x0000008f, 0x00000018 }, 16995584Sanholt { 0x0000005b, 0x00000004 }, 17095584Sanholt { 0x000380e6, 0x00000002 }, 17195584Sanholt { 0x040025c5, 0x00000002 }, 17295584Sanholt { 0x00007576, 0x00000002 }, 17395584Sanholt { 0x00065000, 0x00000002 }, 17495584Sanholt { 0x00009000, 0x00000002 }, 17595584Sanholt { 0x00041000, 0x00000002 }, 17695584Sanholt { 0x0c00350e, 0x00000002 }, 17795584Sanholt { 0x00049000, 0x00000002 }, 17895584Sanholt { 0x00051000, 0x00000002 }, 17995584Sanholt { 0x01e785f8, 0x00000002 }, 18095584Sanholt { 0x00200000, 0x00000002 }, 18195584Sanholt { 0x0060007e, 0x0000000c }, 18295584Sanholt { 0x00007563, 0x00000002 }, 18395584Sanholt { 0x006075f0, 0x00000021 }, 18495584Sanholt { 0x20007073, 0x00000004 }, 18595584Sanholt { 0x00005073, 0x00000004 }, 18695584Sanholt { 0x000380e6, 0x00000002 }, 18795584Sanholt { 0x040025c5, 0x00000002 }, 18895584Sanholt { 0x00007576, 0x00000002 }, 18995584Sanholt { 0x00007577, 0x00000002 }, 19095584Sanholt { 0x0000750e, 0x00000002 }, 19195584Sanholt { 0x0000750f, 0x00000002 }, 19295584Sanholt { 0x00a05000, 0x00000002 }, 19395584Sanholt { 0x00600083, 0x0000000c }, 19495584Sanholt { 0x006075f0, 0x00000021 }, 19595584Sanholt { 0x000075f8, 0x00000002 }, 19695584Sanholt { 0x00000083, 0x00000004 }, 19795584Sanholt { 0x000a750e, 0x00000002 }, 19895584Sanholt { 0x000380e6, 0x00000002 }, 19995584Sanholt { 0x040025c5, 0x00000002 }, 20095584Sanholt { 0x0020750f, 0x00000002 }, 20195584Sanholt { 0x00600086, 0x00000004 }, 20295584Sanholt { 0x00007570, 0x00000002 }, 20395584Sanholt { 0x00007571, 0x00000002 }, 20495584Sanholt { 0x00007572, 0x00000006 }, 20595584Sanholt { 0x000380e6, 0x00000002 }, 20695584Sanholt { 0x040025c5, 0x00000002 }, 20795584Sanholt { 0x00005000, 0x00000002 }, 20895584Sanholt { 0x00a05000, 0x00000002 }, 20995584Sanholt { 0x00007568, 0x00000002 }, 21095584Sanholt { 0x00061000, 0x00000002 }, 21195584Sanholt { 0x00000095, 0x0000000c }, 21295584Sanholt { 0x00058000, 0x00000002 }, 21395584Sanholt { 0x0c607562, 0x00000002 }, 21495584Sanholt { 0x00000097, 0x00000004 }, 21595584Sanholt { 0x000380e6, 0x00000002 }, 21695584Sanholt { 0x040025c5, 0x00000002 }, 21795584Sanholt { 0x00600096, 0x00000004 }, 21895584Sanholt { 0x400070e5, 0000000000 }, 21995584Sanholt { 0x000380e6, 0x00000002 }, 22095584Sanholt { 0x040025c5, 0x00000002 }, 22195584Sanholt { 0x000380e5, 0x00000002 }, 22295584Sanholt { 0x000000a8, 0x0000001c }, 22395584Sanholt { 0x000650aa, 0x00000018 }, 22495584Sanholt { 0x040025bb, 0x00000002 }, 22595584Sanholt { 0x000610ab, 0x00000018 }, 22695584Sanholt { 0x040075bc, 0000000000 }, 22795584Sanholt { 0x000075bb, 0x00000002 }, 22895584Sanholt { 0x000075bc, 0000000000 }, 22995584Sanholt { 0x00090000, 0x00000006 }, 23095584Sanholt { 0x00090000, 0x00000002 }, 23195584Sanholt { 0x000d8002, 0x00000006 }, 23295584Sanholt { 0x00007832, 0x00000002 }, 23395584Sanholt { 0x00005000, 0x00000002 }, 23495584Sanholt { 0x000380e7, 0x00000002 }, 23595584Sanholt { 0x04002c97, 0x00000002 }, 23695584Sanholt { 0x00007820, 0x00000002 }, 23795584Sanholt { 0x00007821, 0x00000002 }, 23895584Sanholt { 0x00007800, 0000000000 }, 23995584Sanholt { 0x01200000, 0x00000002 }, 24095584Sanholt { 0x20077000, 0x00000002 }, 24195584Sanholt { 0x01200000, 0x00000002 }, 24295584Sanholt { 0x20007000, 0x00000002 }, 24395584Sanholt { 0x00061000, 0x00000002 }, 24495584Sanholt { 0x0120751b, 0x00000002 }, 24595584Sanholt { 0x8040750a, 0x00000002 }, 24695584Sanholt { 0x8040750b, 0x00000002 }, 24795584Sanholt { 0x00110000, 0x00000002 }, 24895584Sanholt { 0x000380e5, 0x00000002 }, 24995584Sanholt { 0x000000c6, 0x0000001c }, 25095584Sanholt { 0x000610ab, 0x00000018 }, 25195584Sanholt { 0x844075bd, 0x00000002 }, 25295584Sanholt { 0x000610aa, 0x00000018 }, 25395584Sanholt { 0x840075bb, 0x00000002 }, 25495584Sanholt { 0x000610ab, 0x00000018 }, 25595584Sanholt { 0x844075bc, 0x00000002 }, 25695584Sanholt { 0x000000c9, 0x00000004 }, 25795584Sanholt { 0x804075bd, 0x00000002 }, 25895584Sanholt { 0x800075bb, 0x00000002 }, 25995584Sanholt { 0x804075bc, 0x00000002 }, 26095584Sanholt { 0x00108000, 0x00000002 }, 26195584Sanholt { 0x01400000, 0x00000002 }, 26295584Sanholt { 0x006000cd, 0x0000000c }, 26395584Sanholt { 0x20c07000, 0x00000020 }, 26495584Sanholt { 0x000000cf, 0x00000012 }, 26595584Sanholt { 0x00800000, 0x00000006 }, 26695584Sanholt { 0x0080751d, 0x00000006 }, 26795584Sanholt { 0000000000, 0000000000 }, 26895584Sanholt { 0x0000775c, 0x00000002 }, 26995584Sanholt { 0x00a05000, 0x00000002 }, 27095584Sanholt { 0x00661000, 0x00000002 }, 27195584Sanholt { 0x0460275d, 0x00000020 }, 27295584Sanholt { 0x00004000, 0000000000 }, 27395584Sanholt { 0x01e00830, 0x00000002 }, 27495584Sanholt { 0x21007000, 0000000000 }, 27595584Sanholt { 0x6464614d, 0000000000 }, 27695584Sanholt { 0x69687420, 0000000000 }, 27795584Sanholt { 0x00000073, 0000000000 }, 27895584Sanholt { 0000000000, 0000000000 }, 27995584Sanholt { 0x00005000, 0x00000002 }, 28095584Sanholt { 0x000380d0, 0x00000002 }, 28195584Sanholt { 0x040025e0, 0x00000002 }, 28295584Sanholt { 0x000075e1, 0000000000 }, 28395584Sanholt { 0x00000001, 0000000000 }, 28495584Sanholt { 0x000380e0, 0x00000002 }, 28595584Sanholt { 0x04002394, 0x00000002 }, 28695584Sanholt { 0x00005000, 0000000000 }, 28795584Sanholt { 0000000000, 0000000000 }, 28895584Sanholt { 0000000000, 0000000000 }, 28995584Sanholt { 0x00000008, 0000000000 }, 29095584Sanholt { 0x00000004, 0000000000 }, 29195584Sanholt { 0000000000, 0000000000 }, 29295584Sanholt { 0000000000, 0000000000 }, 29395584Sanholt { 0000000000, 0000000000 }, 29495584Sanholt { 0000000000, 0000000000 }, 29595584Sanholt { 0000000000, 0000000000 }, 29695584Sanholt { 0000000000, 0000000000 }, 29795584Sanholt { 0000000000, 0000000000 }, 29895584Sanholt { 0000000000, 0000000000 }, 29995584Sanholt { 0000000000, 0000000000 }, 30095584Sanholt { 0000000000, 0000000000 }, 30195584Sanholt { 0000000000, 0000000000 }, 30295584Sanholt { 0000000000, 0000000000 }, 30395584Sanholt { 0000000000, 0000000000 }, 30495584Sanholt { 0000000000, 0000000000 }, 30595584Sanholt { 0000000000, 0000000000 }, 30695584Sanholt { 0000000000, 0000000000 }, 30795584Sanholt { 0000000000, 0000000000 }, 30895584Sanholt { 0000000000, 0000000000 }, 30995584Sanholt { 0000000000, 0000000000 }, 31095584Sanholt { 0000000000, 0000000000 }, 31195584Sanholt { 0000000000, 0000000000 }, 31295584Sanholt { 0000000000, 0000000000 }, 31395584Sanholt { 0000000000, 0000000000 }, 31495584Sanholt { 0000000000, 0000000000 }, 31595584Sanholt}; 31695584Sanholt 31795584Sanholt 31895584Sanholtint RADEON_READ_PLL(drm_device_t *dev, int addr) 31995584Sanholt{ 32095584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 32195584Sanholt 32295584Sanholt RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); 32395584Sanholt return RADEON_READ(RADEON_CLOCK_CNTL_DATA); 32495584Sanholt} 32595584Sanholt 32695584Sanholt#if RADEON_FIFO_DEBUG 32795584Sanholtstatic void radeon_status( drm_radeon_private_t *dev_priv ) 32895584Sanholt{ 32995584Sanholt printk( "%s:\n", __FUNCTION__ ); 33095584Sanholt printk( "RBBM_STATUS = 0x%08x\n", 33195584Sanholt (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) ); 33295584Sanholt printk( "CP_RB_RTPR = 0x%08x\n", 33395584Sanholt (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) ); 33495584Sanholt printk( "CP_RB_WTPR = 0x%08x\n", 33595584Sanholt (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) ); 33695584Sanholt printk( "AIC_CNTL = 0x%08x\n", 33795584Sanholt (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) ); 33895584Sanholt printk( "AIC_STAT = 0x%08x\n", 33995584Sanholt (unsigned int)RADEON_READ( RADEON_AIC_STAT ) ); 34095584Sanholt printk( "AIC_PT_BASE = 0x%08x\n", 34195584Sanholt (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) ); 34295584Sanholt printk( "TLB_ADDR = 0x%08x\n", 34395584Sanholt (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) ); 34495584Sanholt printk( "TLB_DATA = 0x%08x\n", 34595584Sanholt (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) ); 34695584Sanholt} 34795584Sanholt#endif 34895584Sanholt 34995584Sanholt 35095584Sanholt/* ================================================================ 35195584Sanholt * Engine, FIFO control 35295584Sanholt */ 35395584Sanholt 35495584Sanholtstatic int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv ) 35595584Sanholt{ 35695584Sanholt u32 tmp; 35795584Sanholt int i; 35895584Sanholt 35995584Sanholt tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT ); 36095584Sanholt tmp |= RADEON_RB2D_DC_FLUSH_ALL; 36195584Sanholt RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp ); 36295584Sanholt 36395584Sanholt for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { 36495584Sanholt if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT ) 36595584Sanholt & RADEON_RB2D_DC_BUSY) ) { 36695584Sanholt return 0; 36795584Sanholt } 36895584Sanholt DRM_OS_DELAY( 1 ); 36995584Sanholt } 37095584Sanholt 37195584Sanholt#if RADEON_FIFO_DEBUG 37295584Sanholt DRM_ERROR( "failed!\n" ); 37395584Sanholt radeon_status( dev_priv ); 37495584Sanholt#endif 37595693Sanholt return DRM_OS_ERR(EBUSY); 37695584Sanholt} 37795584Sanholt 37895584Sanholtstatic int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv, 37995584Sanholt int entries ) 38095584Sanholt{ 38195584Sanholt int i; 38295584Sanholt 38395584Sanholt for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { 38495584Sanholt int slots = ( RADEON_READ( RADEON_RBBM_STATUS ) 38595584Sanholt & RADEON_RBBM_FIFOCNT_MASK ); 38695584Sanholt if ( slots >= entries ) return 0; 38795584Sanholt DRM_OS_DELAY( 1 ); 38895584Sanholt } 38995584Sanholt 39095584Sanholt#if RADEON_FIFO_DEBUG 39195584Sanholt DRM_ERROR( "failed!\n" ); 39295584Sanholt radeon_status( dev_priv ); 39395584Sanholt#endif 39495693Sanholt return DRM_OS_ERR(EBUSY); 39595584Sanholt} 39695584Sanholt 39795584Sanholtstatic int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv ) 39895584Sanholt{ 39995584Sanholt int i, ret; 40095584Sanholt 40195584Sanholt ret = radeon_do_wait_for_fifo( dev_priv, 64 ); 40295584Sanholt if ( ret ) return ret; 40395584Sanholt for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { 40495584Sanholt if ( !(RADEON_READ( RADEON_RBBM_STATUS ) 40595584Sanholt & RADEON_RBBM_ACTIVE) ) { 40695584Sanholt radeon_do_pixcache_flush( dev_priv ); 40795584Sanholt return 0; 40895584Sanholt } 40995584Sanholt DRM_OS_DELAY( 1 ); 41095584Sanholt } 41195584Sanholt 41295584Sanholt#if RADEON_FIFO_DEBUG 41395584Sanholt DRM_ERROR( "failed!\n" ); 41495584Sanholt radeon_status( dev_priv ); 41595584Sanholt#endif 41695693Sanholt return DRM_OS_ERR(EBUSY); 41795584Sanholt} 41895584Sanholt 41995584Sanholt 42095584Sanholt/* ================================================================ 42195584Sanholt * CP control, initialization 42295584Sanholt */ 42395584Sanholt 42495584Sanholt/* Load the microcode for the CP */ 42595584Sanholtstatic void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv ) 42695584Sanholt{ 42795584Sanholt int i; 42895584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 42995584Sanholt 43095584Sanholt radeon_do_wait_for_idle( dev_priv ); 43195584Sanholt 43295584Sanholt RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 ); 43395584Sanholt for ( i = 0 ; i < 256 ; i++ ) { 43495584Sanholt RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, 43595584Sanholt radeon_cp_microcode[i][1] ); 43695584Sanholt RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, 43795584Sanholt radeon_cp_microcode[i][0] ); 43895584Sanholt } 43995584Sanholt} 44095584Sanholt 44195584Sanholt/* Flush any pending commands to the CP. This should only be used just 44295584Sanholt * prior to a wait for idle, as it informs the engine that the command 44395584Sanholt * stream is ending. 44495584Sanholt */ 44595584Sanholtstatic void radeon_do_cp_flush( drm_radeon_private_t *dev_priv ) 44695584Sanholt{ 44795584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 44895584Sanholt#if 0 44995584Sanholt u32 tmp; 45095584Sanholt 45195584Sanholt tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31); 45295584Sanholt RADEON_WRITE( RADEON_CP_RB_WPTR, tmp ); 45395584Sanholt#endif 45495584Sanholt} 45595584Sanholt 45695584Sanholt/* Wait for the CP to go idle. 45795584Sanholt */ 45895584Sanholtint radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) 45995584Sanholt{ 46095584Sanholt RING_LOCALS; 46195584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 46295584Sanholt 46395584Sanholt BEGIN_RING( 6 ); 46495584Sanholt 46595584Sanholt RADEON_PURGE_CACHE(); 46695584Sanholt RADEON_PURGE_ZCACHE(); 46795584Sanholt RADEON_WAIT_UNTIL_IDLE(); 46895584Sanholt 46995584Sanholt ADVANCE_RING(); 47095584Sanholt 47195584Sanholt return radeon_do_wait_for_idle( dev_priv ); 47295584Sanholt} 47395584Sanholt 47495584Sanholt/* Start the Command Processor. 47595584Sanholt */ 47695584Sanholtstatic void radeon_do_cp_start( drm_radeon_private_t *dev_priv ) 47795584Sanholt{ 47895584Sanholt RING_LOCALS; 47995584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 48095584Sanholt 48195584Sanholt radeon_do_wait_for_idle( dev_priv ); 48295584Sanholt 48395584Sanholt RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode ); 48495584Sanholt 48595584Sanholt dev_priv->cp_running = 1; 48695584Sanholt 48795584Sanholt BEGIN_RING( 6 ); 48895584Sanholt 48995584Sanholt RADEON_PURGE_CACHE(); 49095584Sanholt RADEON_PURGE_ZCACHE(); 49195584Sanholt RADEON_WAIT_UNTIL_IDLE(); 49295584Sanholt 49395584Sanholt ADVANCE_RING(); 49495584Sanholt} 49595584Sanholt 49695584Sanholt/* Reset the Command Processor. This will not flush any pending 49795584Sanholt * commands, so you must wait for the CP command stream to complete 49895584Sanholt * before calling this routine. 49995584Sanholt */ 50095584Sanholtstatic void radeon_do_cp_reset( drm_radeon_private_t *dev_priv ) 50195584Sanholt{ 50295584Sanholt u32 cur_read_ptr; 50395584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 50495584Sanholt 50595584Sanholt cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR ); 50695584Sanholt RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr ); 50795584Sanholt *dev_priv->ring.head = cur_read_ptr; 50895584Sanholt dev_priv->ring.tail = cur_read_ptr; 50995584Sanholt} 51095584Sanholt 51195584Sanholt/* Stop the Command Processor. This will not flush any pending 51295584Sanholt * commands, so you must flush the command stream and wait for the CP 51395584Sanholt * to go idle before calling this routine. 51495584Sanholt */ 51595584Sanholtstatic void radeon_do_cp_stop( drm_radeon_private_t *dev_priv ) 51695584Sanholt{ 51795584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 51895584Sanholt 51995584Sanholt RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); 52095584Sanholt 52195584Sanholt dev_priv->cp_running = 0; 52295584Sanholt} 52395584Sanholt 52495584Sanholt/* Reset the engine. This will stop the CP if it is running. 52595584Sanholt */ 52695584Sanholtstatic int radeon_do_engine_reset( drm_device_t *dev ) 52795584Sanholt{ 52895584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 52995584Sanholt u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; 53095584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 53195584Sanholt 53295584Sanholt radeon_do_pixcache_flush( dev_priv ); 53395584Sanholt 53495584Sanholt clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX ); 53595584Sanholt mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL ); 53695584Sanholt 53795584Sanholt RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl | 53895584Sanholt RADEON_FORCEON_MCLKA | 53995584Sanholt RADEON_FORCEON_MCLKB | 54095584Sanholt RADEON_FORCEON_YCLKA | 54195584Sanholt RADEON_FORCEON_YCLKB | 54295584Sanholt RADEON_FORCEON_MC | 54395584Sanholt RADEON_FORCEON_AIC ) ); 54495584Sanholt 54595584Sanholt rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET ); 54695584Sanholt 54795584Sanholt RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset | 54895584Sanholt RADEON_SOFT_RESET_CP | 54995584Sanholt RADEON_SOFT_RESET_HI | 55095584Sanholt RADEON_SOFT_RESET_SE | 55195584Sanholt RADEON_SOFT_RESET_RE | 55295584Sanholt RADEON_SOFT_RESET_PP | 55395584Sanholt RADEON_SOFT_RESET_E2 | 55495584Sanholt RADEON_SOFT_RESET_RB ) ); 55595584Sanholt RADEON_READ( RADEON_RBBM_SOFT_RESET ); 55695584Sanholt RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset & 55795584Sanholt ~( RADEON_SOFT_RESET_CP | 55895584Sanholt RADEON_SOFT_RESET_HI | 55995584Sanholt RADEON_SOFT_RESET_SE | 56095584Sanholt RADEON_SOFT_RESET_RE | 56195584Sanholt RADEON_SOFT_RESET_PP | 56295584Sanholt RADEON_SOFT_RESET_E2 | 56395584Sanholt RADEON_SOFT_RESET_RB ) ) ); 56495584Sanholt RADEON_READ( RADEON_RBBM_SOFT_RESET ); 56595584Sanholt 56695584Sanholt 56795584Sanholt RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl ); 56895584Sanholt RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index ); 56995584Sanholt RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset ); 57095584Sanholt 57195584Sanholt /* Reset the CP ring */ 57295584Sanholt radeon_do_cp_reset( dev_priv ); 57395584Sanholt 57495584Sanholt /* The CP is no longer running after an engine reset */ 57595584Sanholt dev_priv->cp_running = 0; 57695584Sanholt 57795584Sanholt /* Reset any pending vertex, indirect buffers */ 57895584Sanholt radeon_freelist_reset( dev ); 57995584Sanholt 58095584Sanholt return 0; 58195584Sanholt} 58295584Sanholt 58395584Sanholtstatic void radeon_cp_init_ring_buffer( drm_device_t *dev, 58495584Sanholt drm_radeon_private_t *dev_priv ) 58595584Sanholt{ 58695584Sanholt u32 ring_start, cur_read_ptr; 58795584Sanholt u32 tmp; 58895584Sanholt 58995584Sanholt /* Initialize the memory controller */ 59095584Sanholt RADEON_WRITE( RADEON_MC_FB_LOCATION, 59195584Sanholt (dev_priv->agp_vm_start - 1) & 0xffff0000 ); 59295584Sanholt 59395584Sanholt if ( !dev_priv->is_pci ) { 59495584Sanholt RADEON_WRITE( RADEON_MC_AGP_LOCATION, 59595584Sanholt (((dev_priv->agp_vm_start - 1 + 59695584Sanholt dev_priv->agp_size) & 0xffff0000) | 59795584Sanholt (dev_priv->agp_vm_start >> 16)) ); 59895584Sanholt } 59995584Sanholt 60095584Sanholt#if __REALLY_HAVE_AGP 60195584Sanholt if ( !dev_priv->is_pci ) 60295584Sanholt ring_start = (dev_priv->cp_ring->offset 60395584Sanholt - dev->agp->base 60495584Sanholt + dev_priv->agp_vm_start); 60595584Sanholt else 60695584Sanholt#endif 60795584Sanholt ring_start = (dev_priv->cp_ring->offset 60895584Sanholt - dev->sg->handle 60995584Sanholt + dev_priv->agp_vm_start); 61095584Sanholt 61195584Sanholt RADEON_WRITE( RADEON_CP_RB_BASE, ring_start ); 61295584Sanholt 61395584Sanholt /* Set the write pointer delay */ 61495584Sanholt RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 ); 61595584Sanholt 61695584Sanholt /* Initialize the ring buffer's read and write pointers */ 61795584Sanholt cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR ); 61895584Sanholt RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr ); 61995584Sanholt *dev_priv->ring.head = cur_read_ptr; 62095584Sanholt dev_priv->ring.tail = cur_read_ptr; 62195584Sanholt 62295584Sanholt#if __REALLY_HAVE_SG 62395584Sanholt if ( !dev_priv->is_pci ) { 62495584Sanholt#endif 62595584Sanholt RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, 62695584Sanholt dev_priv->ring_rptr->offset ); 62795584Sanholt#if __REALLY_HAVE_SG 62895584Sanholt } else { 62995584Sanholt drm_sg_mem_t *entry = dev->sg; 63095584Sanholt unsigned long tmp_ofs, page_ofs; 63195584Sanholt 63295584Sanholt tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle; 63395584Sanholt page_ofs = tmp_ofs >> PAGE_SHIFT; 63495584Sanholt 63595584Sanholt RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, 63695584Sanholt entry->busaddr[page_ofs]); 63795584Sanholt DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", 63895584Sanholt entry->busaddr[page_ofs], 63995584Sanholt entry->handle + tmp_ofs ); 64095584Sanholt } 64195584Sanholt#endif 64295584Sanholt 64395584Sanholt /* Set ring buffer size */ 64495584Sanholt RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw ); 64595584Sanholt 64695584Sanholt radeon_do_wait_for_idle( dev_priv ); 64795584Sanholt 64895584Sanholt /* Turn on bus mastering */ 64995584Sanholt tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS; 65095584Sanholt RADEON_WRITE( RADEON_BUS_CNTL, tmp ); 65195584Sanholt 65295584Sanholt /* Sync everything up */ 65395584Sanholt RADEON_WRITE( RADEON_ISYNC_CNTL, 65495584Sanholt (RADEON_ISYNC_ANY2D_IDLE3D | 65595584Sanholt RADEON_ISYNC_ANY3D_IDLE2D | 65695584Sanholt RADEON_ISYNC_WAIT_IDLEGUI | 65795584Sanholt RADEON_ISYNC_CPSCRATCH_IDLEGUI) ); 65895584Sanholt} 65995584Sanholt 66095584Sanholtstatic int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) 66195584Sanholt{ 66295584Sanholt drm_radeon_private_t *dev_priv; 66395584Sanholt#ifdef __linux__ 66495584Sanholt struct list_head *list; 66595584Sanholt#endif /* __linux__ */ 66695584Sanholt#ifdef __FreeBSD__ 66795584Sanholt drm_map_list_entry_t *listentry; 66895584Sanholt#endif /* __FreeBSD__ */ 66995584Sanholt u32 tmp; 67095584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 67195584Sanholt 67295584Sanholt dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); 67395584Sanholt if ( dev_priv == NULL ) 67495693Sanholt return DRM_OS_ERR(ENOMEM); 67595584Sanholt 67695584Sanholt memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); 67795584Sanholt 67895584Sanholt dev_priv->is_pci = init->is_pci; 67995584Sanholt 68095584Sanholt#if !defined(PCIGART_ENABLED) 68195584Sanholt /* PCI support is not 100% working, so we disable it here. 68295584Sanholt */ 68395584Sanholt if ( dev_priv->is_pci ) { 68495584Sanholt DRM_ERROR( "PCI GART not yet supported for Radeon!\n" ); 68595584Sanholt dev->dev_private = (void *)dev_priv; 68695584Sanholt radeon_do_cleanup_cp(dev); 68795693Sanholt return DRM_OS_ERR(EINVAL); 68895584Sanholt } 68995584Sanholt#endif 69095584Sanholt 69195584Sanholt if ( dev_priv->is_pci && !dev->sg ) { 69295584Sanholt DRM_ERROR( "PCI GART memory not allocated!\n" ); 69395584Sanholt dev->dev_private = (void *)dev_priv; 69495584Sanholt radeon_do_cleanup_cp(dev); 69595693Sanholt return DRM_OS_ERR(EINVAL); 69695584Sanholt } 69795584Sanholt 69895584Sanholt dev_priv->usec_timeout = init->usec_timeout; 69995584Sanholt if ( dev_priv->usec_timeout < 1 || 70095584Sanholt dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) { 70195584Sanholt DRM_DEBUG( "TIMEOUT problem!\n" ); 70295584Sanholt dev->dev_private = (void *)dev_priv; 70395584Sanholt radeon_do_cleanup_cp(dev); 70495693Sanholt return DRM_OS_ERR(EINVAL); 70595584Sanholt } 70695584Sanholt 70795584Sanholt dev_priv->cp_mode = init->cp_mode; 70895584Sanholt 70995584Sanholt /* Simple idle check. 71095584Sanholt */ 71195584Sanholt atomic_set( &dev_priv->idle_count, 0 ); 71295584Sanholt 71395584Sanholt /* We don't support anything other than bus-mastering ring mode, 71495584Sanholt * but the ring can be in either AGP or PCI space for the ring 71595584Sanholt * read pointer. 71695584Sanholt */ 71795584Sanholt if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) && 71895584Sanholt ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) { 71995584Sanholt DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode ); 72095584Sanholt dev->dev_private = (void *)dev_priv; 72195584Sanholt radeon_do_cleanup_cp(dev); 72295693Sanholt return DRM_OS_ERR(EINVAL); 72395584Sanholt } 72495584Sanholt 72595584Sanholt switch ( init->fb_bpp ) { 72695584Sanholt case 16: 72795584Sanholt dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; 72895584Sanholt break; 72995584Sanholt case 32: 73095584Sanholt default: 73195584Sanholt dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; 73295584Sanholt break; 73395584Sanholt } 73495584Sanholt dev_priv->front_offset = init->front_offset; 73595584Sanholt dev_priv->front_pitch = init->front_pitch; 73695584Sanholt dev_priv->back_offset = init->back_offset; 73795584Sanholt dev_priv->back_pitch = init->back_pitch; 73895584Sanholt 73995584Sanholt switch ( init->depth_bpp ) { 74095584Sanholt case 16: 74195584Sanholt dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; 74295584Sanholt break; 74395584Sanholt case 32: 74495584Sanholt default: 74595584Sanholt dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; 74695584Sanholt break; 74795584Sanholt } 74895584Sanholt dev_priv->depth_offset = init->depth_offset; 74995584Sanholt dev_priv->depth_pitch = init->depth_pitch; 75095584Sanholt 75195584Sanholt dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) | 75295584Sanholt (dev_priv->front_offset >> 10)); 75395584Sanholt dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) | 75495584Sanholt (dev_priv->back_offset >> 10)); 75595584Sanholt dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) | 75695584Sanholt (dev_priv->depth_offset >> 10)); 75795584Sanholt 75895584Sanholt /* Hardware state for depth clears. Remove this if/when we no 75995584Sanholt * longer clear the depth buffer with a 3D rectangle. Hard-code 76095584Sanholt * all values to prevent unwanted 3D state from slipping through 76195584Sanholt * and screwing with the clear operation. 76295584Sanholt */ 76395584Sanholt dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | 76495584Sanholt RADEON_Z_ENABLE | 76595584Sanholt (dev_priv->color_fmt << 10) | 76695584Sanholt RADEON_ZBLOCK16); 76795584Sanholt 76895584Sanholt dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt | 76995584Sanholt RADEON_Z_TEST_ALWAYS | 77095584Sanholt RADEON_STENCIL_TEST_ALWAYS | 77195584Sanholt RADEON_STENCIL_S_FAIL_KEEP | 77295584Sanholt RADEON_STENCIL_ZPASS_KEEP | 77395584Sanholt RADEON_STENCIL_ZFAIL_KEEP | 77495584Sanholt RADEON_Z_WRITE_ENABLE); 77595584Sanholt 77695584Sanholt dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | 77795584Sanholt RADEON_BFACE_SOLID | 77895584Sanholt RADEON_FFACE_SOLID | 77995584Sanholt RADEON_FLAT_SHADE_VTX_LAST | 78095584Sanholt RADEON_DIFFUSE_SHADE_FLAT | 78195584Sanholt RADEON_ALPHA_SHADE_FLAT | 78295584Sanholt RADEON_SPECULAR_SHADE_FLAT | 78395584Sanholt RADEON_FOG_SHADE_FLAT | 78495584Sanholt RADEON_VTX_PIX_CENTER_OGL | 78595584Sanholt RADEON_ROUND_MODE_TRUNC | 78695584Sanholt RADEON_ROUND_PREC_8TH_PIX); 78795584Sanholt 78895584Sanholt#ifdef __linux__ 78995584Sanholt list_for_each(list, &dev->maplist->head) { 79095584Sanholt drm_map_list_t *r_list = (drm_map_list_t *)list; 79195584Sanholt if( r_list->map && 79295584Sanholt r_list->map->type == _DRM_SHM && 79395584Sanholt r_list->map->flags & _DRM_CONTAINS_LOCK ) { 79495584Sanholt dev_priv->sarea = r_list->map; 79595584Sanholt break; 79695584Sanholt } 79795584Sanholt } 79895584Sanholt#endif /* __linux__ */ 79995584Sanholt#ifdef __FreeBSD__ 80095584Sanholt TAILQ_FOREACH(listentry, dev->maplist, link) { 80195584Sanholt drm_map_t *map = listentry->map; 80295584Sanholt if (map->type == _DRM_SHM && 80395584Sanholt map->flags & _DRM_CONTAINS_LOCK) { 80495584Sanholt dev_priv->sarea = map; 80595584Sanholt break; 80695584Sanholt } 80795584Sanholt } 80895584Sanholt#endif /* __FreeBSD__ */ 80995584Sanholt 81095584Sanholt if(!dev_priv->sarea) { 81195584Sanholt DRM_ERROR("could not find sarea!\n"); 81295584Sanholt dev->dev_private = (void *)dev_priv; 81395584Sanholt radeon_do_cleanup_cp(dev); 81495693Sanholt return DRM_OS_ERR(EINVAL); 81595584Sanholt } 81695584Sanholt 81795584Sanholt DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); 81895584Sanholt if(!dev_priv->fb) { 81995584Sanholt DRM_ERROR("could not find framebuffer!\n"); 82095584Sanholt dev->dev_private = (void *)dev_priv; 82195584Sanholt radeon_do_cleanup_cp(dev); 82295693Sanholt return DRM_OS_ERR(EINVAL); 82395584Sanholt } 82495584Sanholt DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); 82595584Sanholt if(!dev_priv->mmio) { 82695584Sanholt DRM_ERROR("could not find mmio region!\n"); 82795584Sanholt dev->dev_private = (void *)dev_priv; 82895584Sanholt radeon_do_cleanup_cp(dev); 82995693Sanholt return DRM_OS_ERR(EINVAL); 83095584Sanholt } 83195584Sanholt DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset ); 83295584Sanholt if(!dev_priv->cp_ring) { 83395584Sanholt DRM_ERROR("could not find cp ring region!\n"); 83495584Sanholt dev->dev_private = (void *)dev_priv; 83595584Sanholt radeon_do_cleanup_cp(dev); 83695693Sanholt return DRM_OS_ERR(EINVAL); 83795584Sanholt } 83895584Sanholt DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); 83995584Sanholt if(!dev_priv->ring_rptr) { 84095584Sanholt DRM_ERROR("could not find ring read pointer!\n"); 84195584Sanholt dev->dev_private = (void *)dev_priv; 84295584Sanholt radeon_do_cleanup_cp(dev); 84395693Sanholt return DRM_OS_ERR(EINVAL); 84495584Sanholt } 84595584Sanholt DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); 84695584Sanholt if(!dev_priv->buffers) { 84795584Sanholt DRM_ERROR("could not find dma buffer region!\n"); 84895584Sanholt dev->dev_private = (void *)dev_priv; 84995584Sanholt radeon_do_cleanup_cp(dev); 85095693Sanholt return DRM_OS_ERR(EINVAL); 85195584Sanholt } 85295584Sanholt 85395584Sanholt if ( !dev_priv->is_pci ) { 85495584Sanholt DRM_FIND_MAP( dev_priv->agp_textures, 85595584Sanholt init->agp_textures_offset ); 85695584Sanholt if(!dev_priv->agp_textures) { 85795584Sanholt DRM_ERROR("could not find agp texture region!\n"); 85895584Sanholt dev->dev_private = (void *)dev_priv; 85995584Sanholt radeon_do_cleanup_cp(dev); 86095693Sanholt return DRM_OS_ERR(EINVAL); 86195584Sanholt } 86295584Sanholt } 86395584Sanholt 86495584Sanholt dev_priv->sarea_priv = 86595584Sanholt (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle + 86695584Sanholt init->sarea_priv_offset); 86795584Sanholt 86895584Sanholt if ( !dev_priv->is_pci ) { 86995584Sanholt DRM_IOREMAP( dev_priv->cp_ring ); 87095584Sanholt DRM_IOREMAP( dev_priv->ring_rptr ); 87195584Sanholt DRM_IOREMAP( dev_priv->buffers ); 87295584Sanholt if(!dev_priv->cp_ring->handle || 87395584Sanholt !dev_priv->ring_rptr->handle || 87495584Sanholt !dev_priv->buffers->handle) { 87595584Sanholt DRM_ERROR("could not find ioremap agp regions!\n"); 87695584Sanholt dev->dev_private = (void *)dev_priv; 87795584Sanholt radeon_do_cleanup_cp(dev); 87895693Sanholt return DRM_OS_ERR(EINVAL); 87995584Sanholt } 88095584Sanholt } else { 88195584Sanholt dev_priv->cp_ring->handle = 88295584Sanholt (void *)dev_priv->cp_ring->offset; 88395584Sanholt dev_priv->ring_rptr->handle = 88495584Sanholt (void *)dev_priv->ring_rptr->offset; 88595584Sanholt dev_priv->buffers->handle = (void *)dev_priv->buffers->offset; 88695584Sanholt 88795584Sanholt DRM_DEBUG( "dev_priv->cp_ring->handle %p\n", 88895584Sanholt dev_priv->cp_ring->handle ); 88995584Sanholt DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n", 89095584Sanholt dev_priv->ring_rptr->handle ); 89195584Sanholt DRM_DEBUG( "dev_priv->buffers->handle %p\n", 89295584Sanholt dev_priv->buffers->handle ); 89395584Sanholt } 89495584Sanholt 89595584Sanholt 89695584Sanholt dev_priv->agp_size = init->agp_size; 89795584Sanholt dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE ); 89895584Sanholt#if __REALLY_HAVE_AGP 89995584Sanholt if ( !dev_priv->is_pci ) 90095584Sanholt dev_priv->agp_buffers_offset = (dev_priv->buffers->offset 90195584Sanholt - dev->agp->base 90295584Sanholt + dev_priv->agp_vm_start); 90395584Sanholt else 90495584Sanholt#endif 90595584Sanholt dev_priv->agp_buffers_offset = (dev_priv->buffers->offset 90695584Sanholt - dev->sg->handle 90795584Sanholt + dev_priv->agp_vm_start); 90895584Sanholt 90995584Sanholt DRM_DEBUG( "dev_priv->agp_size %d\n", 91095584Sanholt dev_priv->agp_size ); 91195584Sanholt DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n", 91295584Sanholt dev_priv->agp_vm_start ); 91395584Sanholt DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n", 91495584Sanholt dev_priv->agp_buffers_offset ); 91595584Sanholt 91695584Sanholt dev_priv->ring.head = ((__volatile__ u32 *) 91795584Sanholt dev_priv->ring_rptr->handle); 91895584Sanholt 91995584Sanholt dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle; 92095584Sanholt dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle 92195584Sanholt + init->ring_size / sizeof(u32)); 92295584Sanholt dev_priv->ring.size = init->ring_size; 92395584Sanholt dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 ); 92495584Sanholt 92595584Sanholt dev_priv->ring.tail_mask = 92695584Sanholt (dev_priv->ring.size / sizeof(u32)) - 1; 92795584Sanholt 92895584Sanholt dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; 92995584Sanholt 93095584Sanholt#if 0 93195584Sanholt /* Initialize the scratch register pointer. This will cause 93295584Sanholt * the scratch register values to be written out to memory 93395584Sanholt * whenever they are updated. 93495584Sanholt * FIXME: This doesn't quite work yet, so we're disabling it 93595584Sanholt * for the release. 93695584Sanholt */ 93795584Sanholt RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset + 93895584Sanholt RADEON_SCRATCH_REG_OFFSET) ); 93995584Sanholt RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); 94095584Sanholt#endif 94195584Sanholt 94295584Sanholt dev_priv->scratch = ((__volatile__ u32 *) 94395584Sanholt dev_priv->ring_rptr->handle + 94495584Sanholt (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); 94595584Sanholt 94695584Sanholt dev_priv->sarea_priv->last_frame = 0; 94795584Sanholt RADEON_WRITE( RADEON_LAST_FRAME_REG, 94895584Sanholt dev_priv->sarea_priv->last_frame ); 94995584Sanholt 95095584Sanholt dev_priv->sarea_priv->last_dispatch = 0; 95195584Sanholt RADEON_WRITE( RADEON_LAST_DISPATCH_REG, 95295584Sanholt dev_priv->sarea_priv->last_dispatch ); 95395584Sanholt 95495584Sanholt dev_priv->sarea_priv->last_clear = 0; 95595584Sanholt RADEON_WRITE( RADEON_LAST_CLEAR_REG, 95695584Sanholt dev_priv->sarea_priv->last_clear ); 95795584Sanholt 95895584Sanholt#if __REALLY_HAVE_SG 95995584Sanholt if ( dev_priv->is_pci ) { 96095584Sanholt if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, 96195584Sanholt &dev_priv->bus_pci_gart)) { 96295584Sanholt DRM_ERROR( "failed to init PCI GART!\n" ); 96395584Sanholt dev->dev_private = (void *)dev_priv; 96495584Sanholt radeon_do_cleanup_cp(dev); 96595693Sanholt return DRM_OS_ERR(ENOMEM); 96695584Sanholt } 96795584Sanholt /* Turn on PCI GART 96895584Sanholt */ 96995584Sanholt tmp = RADEON_READ( RADEON_AIC_CNTL ) 97095584Sanholt | RADEON_PCIGART_TRANSLATE_EN; 97195584Sanholt RADEON_WRITE( RADEON_AIC_CNTL, tmp ); 97295584Sanholt 97395584Sanholt /* set PCI GART page-table base address 97495584Sanholt */ 97595584Sanholt RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart ); 97695584Sanholt 97795584Sanholt /* set address range for PCI address translate 97895584Sanholt */ 97995584Sanholt RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start ); 98095584Sanholt RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start 98195584Sanholt + dev_priv->agp_size - 1); 98295584Sanholt 98395584Sanholt /* Turn off AGP aperture -- is this required for PCIGART? 98495584Sanholt */ 98595584Sanholt RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ 98695584Sanholt RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ 98795584Sanholt } else { 98895584Sanholt#endif 98995584Sanholt /* Turn off PCI GART 99095584Sanholt */ 99195584Sanholt tmp = RADEON_READ( RADEON_AIC_CNTL ) 99295584Sanholt & ~RADEON_PCIGART_TRANSLATE_EN; 99395584Sanholt RADEON_WRITE( RADEON_AIC_CNTL, tmp ); 99495584Sanholt#if __REALLY_HAVE_SG 99595584Sanholt } 99695584Sanholt#endif 99795584Sanholt 99895584Sanholt radeon_cp_load_microcode( dev_priv ); 99995584Sanholt radeon_cp_init_ring_buffer( dev, dev_priv ); 100095584Sanholt 100195584Sanholt#if ROTATE_BUFS 100295584Sanholt dev_priv->last_buf = 0; 100395584Sanholt#endif 100495584Sanholt 100595584Sanholt dev->dev_private = (void *)dev_priv; 100695584Sanholt 100795584Sanholt radeon_do_engine_reset( dev ); 100895584Sanholt 100995584Sanholt return 0; 101095584Sanholt} 101195584Sanholt 101295584Sanholtint radeon_do_cleanup_cp( drm_device_t *dev ) 101395584Sanholt{ 101495584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 101595584Sanholt 101695584Sanholt if ( dev->dev_private ) { 101795584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 101895584Sanholt 101995584Sanholt#if __REALLY_HAVE_SG 102095584Sanholt if ( !dev_priv->is_pci ) { 102195584Sanholt#endif 102295584Sanholt DRM_IOREMAPFREE( dev_priv->cp_ring ); 102395584Sanholt DRM_IOREMAPFREE( dev_priv->ring_rptr ); 102495584Sanholt DRM_IOREMAPFREE( dev_priv->buffers ); 102595584Sanholt#if __REALLY_HAVE_SG 102695584Sanholt } else { 102795584Sanholt if (!DRM(ati_pcigart_cleanup)( dev, 102895584Sanholt dev_priv->phys_pci_gart, 102995584Sanholt dev_priv->bus_pci_gart )) 103095584Sanholt DRM_ERROR( "failed to cleanup PCI GART!\n" ); 103195584Sanholt } 103295584Sanholt#endif 103395584Sanholt 103495584Sanholt DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), 103595584Sanholt DRM_MEM_DRIVER ); 103695584Sanholt dev->dev_private = NULL; 103795584Sanholt } 103895584Sanholt 103995584Sanholt return 0; 104095584Sanholt} 104195584Sanholt 104295584Sanholtint radeon_cp_init( DRM_OS_IOCTL ) 104395584Sanholt{ 104495584Sanholt DRM_OS_DEVICE; 104595584Sanholt drm_radeon_init_t init; 104695584Sanholt 104795584Sanholt DRM_OS_KRNFROMUSR( init, (drm_radeon_init_t *) data, sizeof(init) ); 104895584Sanholt 104995584Sanholt switch ( init.func ) { 105095584Sanholt case RADEON_INIT_CP: 105195584Sanholt return radeon_do_init_cp( dev, &init ); 105295584Sanholt case RADEON_CLEANUP_CP: 105395584Sanholt return radeon_do_cleanup_cp( dev ); 105495584Sanholt } 105595584Sanholt 105695693Sanholt return DRM_OS_ERR(EINVAL); 105795584Sanholt} 105895584Sanholt 105995584Sanholtint radeon_cp_start( DRM_OS_IOCTL ) 106095584Sanholt{ 106195584Sanholt DRM_OS_DEVICE; 106295584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 106395584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 106495584Sanholt 106595584Sanholt LOCK_TEST_WITH_RETURN( dev ); 106695584Sanholt 106795584Sanholt if ( dev_priv->cp_running ) { 106895584Sanholt DRM_DEBUG( "%s while CP running\n", __FUNCTION__ ); 106995584Sanholt return 0; 107095584Sanholt } 107195584Sanholt if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) { 107295584Sanholt DRM_DEBUG( "%s called with bogus CP mode (%d)\n", 107395584Sanholt __FUNCTION__, dev_priv->cp_mode ); 107495584Sanholt return 0; 107595584Sanholt } 107695584Sanholt 107795584Sanholt radeon_do_cp_start( dev_priv ); 107895584Sanholt 107995584Sanholt return 0; 108095584Sanholt} 108195584Sanholt 108295584Sanholt/* Stop the CP. The engine must have been idled before calling this 108395584Sanholt * routine. 108495584Sanholt */ 108595584Sanholtint radeon_cp_stop( DRM_OS_IOCTL ) 108695584Sanholt{ 108795584Sanholt DRM_OS_DEVICE; 108895584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 108995584Sanholt drm_radeon_cp_stop_t stop; 109095584Sanholt int ret; 109195584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 109295584Sanholt 109395584Sanholt LOCK_TEST_WITH_RETURN( dev ); 109495584Sanholt 109595584Sanholt DRM_OS_KRNFROMUSR( stop, (drm_radeon_cp_stop_t *) data, sizeof(stop) ); 109695584Sanholt 109795584Sanholt /* Flush any pending CP commands. This ensures any outstanding 109895584Sanholt * commands are exectuted by the engine before we turn it off. 109995584Sanholt */ 110095584Sanholt if ( stop.flush ) { 110195584Sanholt radeon_do_cp_flush( dev_priv ); 110295584Sanholt } 110395584Sanholt 110495584Sanholt /* If we fail to make the engine go idle, we return an error 110595584Sanholt * code so that the DRM ioctl wrapper can try again. 110695584Sanholt */ 110795584Sanholt if ( stop.idle ) { 110895584Sanholt ret = radeon_do_cp_idle( dev_priv ); 110995584Sanholt if ( ret ) return ret; 111095584Sanholt } 111195584Sanholt 111295584Sanholt /* Finally, we can turn off the CP. If the engine isn't idle, 111395584Sanholt * we will get some dropped triangles as they won't be fully 111495584Sanholt * rendered before the CP is shut down. 111595584Sanholt */ 111695584Sanholt radeon_do_cp_stop( dev_priv ); 111795584Sanholt 111895584Sanholt /* Reset the engine */ 111995584Sanholt radeon_do_engine_reset( dev ); 112095584Sanholt 112195584Sanholt return 0; 112295584Sanholt} 112395584Sanholt 112495584Sanholt/* Just reset the CP ring. Called as part of an X Server engine reset. 112595584Sanholt */ 112695584Sanholtint radeon_cp_reset( DRM_OS_IOCTL ) 112795584Sanholt{ 112895584Sanholt DRM_OS_DEVICE; 112995584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 113095584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 113195584Sanholt 113295584Sanholt LOCK_TEST_WITH_RETURN( dev ); 113395584Sanholt 113495584Sanholt if ( !dev_priv ) { 113595584Sanholt DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); 113695693Sanholt return DRM_OS_ERR(EINVAL); 113795584Sanholt } 113895584Sanholt 113995584Sanholt radeon_do_cp_reset( dev_priv ); 114095584Sanholt 114195584Sanholt /* The CP is no longer running after an engine reset */ 114295584Sanholt dev_priv->cp_running = 0; 114395584Sanholt 114495584Sanholt return 0; 114595584Sanholt} 114695584Sanholt 114795584Sanholtint radeon_cp_idle( DRM_OS_IOCTL ) 114895584Sanholt{ 114995584Sanholt DRM_OS_DEVICE; 115095584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 115195584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 115295584Sanholt 115395584Sanholt LOCK_TEST_WITH_RETURN( dev ); 115495584Sanholt 115595584Sanholt return radeon_do_cp_idle( dev_priv ); 115695584Sanholt} 115795584Sanholt 115895584Sanholtint radeon_engine_reset( DRM_OS_IOCTL ) 115995584Sanholt{ 116095584Sanholt DRM_OS_DEVICE; 116195584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 116295584Sanholt 116395584Sanholt LOCK_TEST_WITH_RETURN( dev ); 116495584Sanholt 116595584Sanholt return radeon_do_engine_reset( dev ); 116695584Sanholt} 116795584Sanholt 116895584Sanholt 116995584Sanholt/* ================================================================ 117095584Sanholt * Fullscreen mode 117195584Sanholt */ 117295584Sanholt 117395584Sanholtstatic int radeon_do_init_pageflip( drm_device_t *dev ) 117495584Sanholt{ 117595584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 117695584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 117795584Sanholt 117895584Sanholt dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); 117995584Sanholt dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); 118095584Sanholt 118195584Sanholt RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); 118295584Sanholt RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, 118395584Sanholt dev_priv->crtc_offset_cntl | 118495584Sanholt RADEON_CRTC_OFFSET_FLIP_CNTL ); 118595584Sanholt 118695584Sanholt dev_priv->page_flipping = 1; 118795584Sanholt dev_priv->current_page = 0; 118895584Sanholt 118995584Sanholt return 0; 119095584Sanholt} 119195584Sanholt 119295584Sanholtint radeon_do_cleanup_pageflip( drm_device_t *dev ) 119395584Sanholt{ 119495584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 119595584Sanholt DRM_DEBUG( "%s\n", __FUNCTION__ ); 119695584Sanholt 119795584Sanholt RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); 119895584Sanholt RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); 119995584Sanholt 120095584Sanholt dev_priv->page_flipping = 0; 120195584Sanholt dev_priv->current_page = 0; 120295584Sanholt 120395584Sanholt return 0; 120495584Sanholt} 120595584Sanholt 120695584Sanholtint radeon_fullscreen( DRM_OS_IOCTL ) 120795584Sanholt{ 120895584Sanholt DRM_OS_DEVICE; 120995584Sanholt drm_radeon_fullscreen_t fs; 121095584Sanholt 121195584Sanholt LOCK_TEST_WITH_RETURN( dev ); 121295584Sanholt 121395584Sanholt DRM_OS_KRNFROMUSR( fs, (drm_radeon_fullscreen_t *) data, 121495584Sanholt sizeof(fs) ); 121595584Sanholt 121695584Sanholt switch ( fs.func ) { 121795584Sanholt case RADEON_INIT_FULLSCREEN: 121895584Sanholt return radeon_do_init_pageflip( dev ); 121995584Sanholt case RADEON_CLEANUP_FULLSCREEN: 122095584Sanholt return radeon_do_cleanup_pageflip( dev ); 122195584Sanholt } 122295584Sanholt 122395693Sanholt return DRM_OS_ERR(EINVAL); 122495584Sanholt} 122595584Sanholt 122695584Sanholt 122795584Sanholt/* ================================================================ 122895584Sanholt * Freelist management 122995584Sanholt */ 123095584Sanholt#define RADEON_BUFFER_USED 0xffffffff 123195584Sanholt#define RADEON_BUFFER_FREE 0 123295584Sanholt 123395584Sanholt#if 0 123495584Sanholtstatic int radeon_freelist_init( drm_device_t *dev ) 123595584Sanholt{ 123695584Sanholt drm_device_dma_t *dma = dev->dma; 123795584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 123895584Sanholt drm_buf_t *buf; 123995584Sanholt drm_radeon_buf_priv_t *buf_priv; 124095584Sanholt drm_radeon_freelist_t *entry; 124195584Sanholt int i; 124295584Sanholt 124395584Sanholt dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t), 124495584Sanholt DRM_MEM_DRIVER ); 124595584Sanholt if ( dev_priv->head == NULL ) 124695693Sanholt return DRM_OS_ERR(ENOMEM); 124795584Sanholt 124895584Sanholt memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) ); 124995584Sanholt dev_priv->head->age = RADEON_BUFFER_USED; 125095584Sanholt 125195584Sanholt for ( i = 0 ; i < dma->buf_count ; i++ ) { 125295584Sanholt buf = dma->buflist[i]; 125395584Sanholt buf_priv = buf->dev_private; 125495584Sanholt 125595584Sanholt entry = DRM(alloc)( sizeof(drm_radeon_freelist_t), 125695584Sanholt DRM_MEM_DRIVER ); 125795693Sanholt if ( !entry ) return DRM_OS_ERR(ENOMEM); 125895584Sanholt 125995584Sanholt entry->age = RADEON_BUFFER_FREE; 126095584Sanholt entry->buf = buf; 126195584Sanholt entry->prev = dev_priv->head; 126295584Sanholt entry->next = dev_priv->head->next; 126395584Sanholt if ( !entry->next ) 126495584Sanholt dev_priv->tail = entry; 126595584Sanholt 126695584Sanholt buf_priv->discard = 0; 126795584Sanholt buf_priv->dispatched = 0; 126895584Sanholt buf_priv->list_entry = entry; 126995584Sanholt 127095584Sanholt dev_priv->head->next = entry; 127195584Sanholt 127295584Sanholt if ( dev_priv->head->next ) 127395584Sanholt dev_priv->head->next->prev = entry; 127495584Sanholt } 127595584Sanholt 127695584Sanholt return 0; 127795584Sanholt 127895584Sanholt} 127995584Sanholt#endif 128095584Sanholt 128195584Sanholtdrm_buf_t *radeon_freelist_get( drm_device_t *dev ) 128295584Sanholt{ 128395584Sanholt drm_device_dma_t *dma = dev->dma; 128495584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 128595584Sanholt drm_radeon_buf_priv_t *buf_priv; 128695584Sanholt drm_buf_t *buf; 128795584Sanholt int i, t; 128895584Sanholt#if ROTATE_BUFS 128995584Sanholt int start; 129095584Sanholt#endif 129195584Sanholt 129295584Sanholt /* FIXME: Optimize -- use freelist code */ 129395584Sanholt 129495584Sanholt for ( i = 0 ; i < dma->buf_count ; i++ ) { 129595584Sanholt buf = dma->buflist[i]; 129695584Sanholt buf_priv = buf->dev_private; 129795584Sanholt if ( buf->pid == 0 ) { 129895584Sanholt DRM_DEBUG( " ret buf=%d last=%d pid=0\n", 129995584Sanholt buf->idx, dev_priv->last_buf ); 130095584Sanholt return buf; 130195584Sanholt } 130295584Sanholt DRM_DEBUG( " skipping buf=%d pid=%d\n", 130395584Sanholt buf->idx, buf->pid ); 130495584Sanholt } 130595584Sanholt 130695584Sanholt#if ROTATE_BUFS 130795584Sanholt if ( ++dev_priv->last_buf >= dma->buf_count ) 130895584Sanholt dev_priv->last_buf = 0; 130995584Sanholt start = dev_priv->last_buf; 131095584Sanholt#endif 131195584Sanholt for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { 131295584Sanholt#if 0 131395584Sanholt /* FIXME: Disable this for now */ 131495584Sanholt u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH]; 131595584Sanholt#else 131695584Sanholt u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG ); 131795584Sanholt#endif 131895584Sanholt#if ROTATE_BUFS 131995584Sanholt for ( i = start ; i < dma->buf_count ; i++ ) { 132095584Sanholt#else 132195584Sanholt for ( i = 0 ; i < dma->buf_count ; i++ ) { 132295584Sanholt#endif 132395584Sanholt buf = dma->buflist[i]; 132495584Sanholt buf_priv = buf->dev_private; 132595584Sanholt if ( buf->pending && buf_priv->age <= done_age ) { 132695584Sanholt /* The buffer has been processed, so it 132795584Sanholt * can now be used. 132895584Sanholt */ 132995584Sanholt buf->pending = 0; 133095584Sanholt DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age ); 133195584Sanholt return buf; 133295584Sanholt } 133395584Sanholt DRM_DEBUG( " skipping buf=%d age=%d done=%d\n", 133495584Sanholt buf->idx, buf_priv->age, 133595584Sanholt done_age ); 133695584Sanholt#if ROTATE_BUFS 133795584Sanholt start = 0; 133895584Sanholt#endif 133995584Sanholt } 134095584Sanholt DRM_OS_DELAY( 1 ); 134195584Sanholt } 134295584Sanholt 134395584Sanholt DRM_ERROR( "returning NULL!\n" ); 134495584Sanholt return NULL; 134595584Sanholt} 134695584Sanholt 134795584Sanholtvoid radeon_freelist_reset( drm_device_t *dev ) 134895584Sanholt{ 134995584Sanholt drm_device_dma_t *dma = dev->dma; 135095584Sanholt#if ROTATE_BUFS 135195584Sanholt drm_radeon_private_t *dev_priv = dev->dev_private; 135295584Sanholt#endif 135395584Sanholt int i; 135495584Sanholt 135595584Sanholt#if ROTATE_BUFS 135695584Sanholt dev_priv->last_buf = 0; 135795584Sanholt#endif 135895584Sanholt for ( i = 0 ; i < dma->buf_count ; i++ ) { 135995584Sanholt drm_buf_t *buf = dma->buflist[i]; 136095584Sanholt drm_radeon_buf_priv_t *buf_priv = buf->dev_private; 136195584Sanholt buf_priv->age = 0; 136295584Sanholt } 136395584Sanholt} 136495584Sanholt 136595584Sanholt 136695584Sanholt/* ================================================================ 136795584Sanholt * CP command submission 136895584Sanholt */ 136995584Sanholt 137095584Sanholtint radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ) 137195584Sanholt{ 137295584Sanholt drm_radeon_ring_buffer_t *ring = &dev_priv->ring; 137395584Sanholt int i; 137495584Sanholt 137595584Sanholt for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { 137695584Sanholt radeon_update_ring_snapshot( ring ); 137795584Sanholt if ( ring->space > n ) 137895584Sanholt return 0; 137995584Sanholt DRM_OS_DELAY( 1 ); 138095584Sanholt } 138195584Sanholt 138295584Sanholt /* FIXME: This return value is ignored in the BEGIN_RING macro! */ 138395584Sanholt#if RADEON_FIFO_DEBUG 138495584Sanholt radeon_status( dev_priv ); 138595584Sanholt DRM_ERROR( "failed!\n" ); 138695584Sanholt#endif 138795693Sanholt return DRM_OS_ERR(EBUSY); 138895584Sanholt} 138995584Sanholt 139095584Sanholtstatic int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ) 139195584Sanholt{ 139295584Sanholt int i; 139395584Sanholt drm_buf_t *buf; 139495584Sanholt 139595584Sanholt for ( i = d->granted_count ; i < d->request_count ; i++ ) { 139695584Sanholt buf = radeon_freelist_get( dev ); 139795693Sanholt if ( !buf ) return DRM_OS_ERR(EAGAIN); 139895584Sanholt 139995584Sanholt buf->pid = DRM_OS_CURRENTPID; 140095584Sanholt 140195584Sanholt if (DRM_OS_COPYTOUSR( &d->request_indices[i], &buf->idx, 140295584Sanholt sizeof(buf->idx) ) ) 140395693Sanholt return DRM_OS_ERR(EFAULT); 140495584Sanholt if (DRM_OS_COPYTOUSR( &d->request_sizes[i], &buf->total, 140595584Sanholt sizeof(buf->total) ) ) 140695693Sanholt return DRM_OS_ERR(EFAULT); 140795584Sanholt 140895584Sanholt d->granted_count++; 140995584Sanholt } 141095584Sanholt return 0; 141195584Sanholt} 141295584Sanholt 141395584Sanholtint radeon_cp_buffers( DRM_OS_IOCTL ) 141495584Sanholt{ 141595584Sanholt DRM_OS_DEVICE; 141695584Sanholt drm_device_dma_t *dma = dev->dma; 141795584Sanholt int ret = 0; 141895584Sanholt drm_dma_t d; 141995584Sanholt 142095584Sanholt LOCK_TEST_WITH_RETURN( dev ); 142195584Sanholt 142295584Sanholt DRM_OS_KRNFROMUSR( d, (drm_dma_t *) data, sizeof(d) ); 142395584Sanholt 142495584Sanholt /* Please don't send us buffers. 142595584Sanholt */ 142695584Sanholt if ( d.send_count != 0 ) { 142795584Sanholt DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n", 142895584Sanholt DRM_OS_CURRENTPID, d.send_count ); 142995693Sanholt return DRM_OS_ERR(EINVAL); 143095584Sanholt } 143195584Sanholt 143295584Sanholt /* We'll send you buffers. 143395584Sanholt */ 143495584Sanholt if ( d.request_count < 0 || d.request_count > dma->buf_count ) { 143595584Sanholt DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", 143695584Sanholt DRM_OS_CURRENTPID, d.request_count, dma->buf_count ); 143795693Sanholt return DRM_OS_ERR(EINVAL); 143895584Sanholt } 143995584Sanholt 144095584Sanholt d.granted_count = 0; 144195584Sanholt 144295584Sanholt if ( d.request_count ) { 144395584Sanholt ret = radeon_cp_get_buffers( dev, &d ); 144495584Sanholt } 144595584Sanholt 144695584Sanholt DRM_OS_KRNTOUSR( (drm_dma_t *) data, d, sizeof(d) ); 144795584Sanholt 144895584Sanholt return ret; 144995584Sanholt} 1450