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