📄 cp_setup.c
字号:
/* Copyright (c) 2002, Thomas Kurschel Part of Radeon accelerant CP initialization/sync/cleanup. It also handles command buffer synchronization. non-local memory is used as following: - 2048 dwords for ring buffer - 253 indirect buffers a 4k (1024 dwords) - 8 dwords for returned data (i.e. current read ptr) & 6 dwords for "scratch registers" usage of scratch registers: - reg 0 = reached engine.count with a granularity of 4 KByte, we need 2+253+1=256 blocks, which is exactly 1 MB*/#include "radeon_driver.h"#include "CPMicroCode.h"#include "../shared/mmio.h"#include "../regs/cp_regs.h"#include "../regs/pll_regs.h"#include "../regs/rbbm_regs.h"#include "../regs/buscntrl_regs.h"#include "../common/utils.h"#include "../shared/pll_access.h"#include "log_coll.h"#include "shared/log_enum.h"#include <string.h>#if 0// macros for user-space#define ALLOC_MEM( asize, mem_type, aglobal, handle, offset ) \ { \ radeon_alloc_mem am; \\ am.magic = RADEON_PRIVATE_DATA_MAGIC; \ am.size = (asize) * 4; \ am.memory_type = (mt_nonlocal); \ am.global = (aglobal); \\ res = ioctl( ai->fd, RADEON_ALLOC_MEM, &am ); \ if( res == B_OK ) \ *(handle) = am.handle; \ *(offset) = am.offset; \ }#define MEM2CPU( mem ) \ ((uint32 *)(ai->mapped_memory[(mem).memory_type].data + (mem).offset))#define MEM2GC( mem ) ((mem).offset + si->memory[(mem).memory_type].virtual_addr_start)#define FREE_MEM( mem_type, handle ) \ { \ radeon_free_mem fm; \\ fm.magic = RADEON_PRIVATE_DATA_MAGIC; \ fm.memory_type = mem_type; \ fm.handle = offset; \\ ioctl( ai->fd, RADEON_FREE_MEM, &fm ); \ } #else// macros for kernel-space// allocate memory// if memory_type is non-local, it is replaced with default non-local type#define ALLOC_MEM( asize, mem_type, aglobal, handle, offset ) \ if( mem_type == mt_nonlocal ) \ mem_type = di->si->nonlocal_type; \ res = mem_alloc( di->memmgr[mem_type], asize, NULL, handle, offset );// get address as seen by program to access allocated memory// (memory_type must _not_ be non-local, see ALLOC_MEM)#define MEM2CPU( memory_type, offset ) \ ((uint8 *)(memory_type == mt_local ? di->si->local_mem : \ (memory_type == mt_PCI ? di->pci_gart.buffer.ptr : di->agp_gart.buffer.ptr)) \ + (offset))// get graphics card's virtual address of allocated memory// (memory_type must _not_ be non-local, see ALLOC_MEM)#define MEM2GC( memory_type, offset ) \ (di->si->memory[(memory_type)].virtual_addr_start + (offset))// free memory// if memory_type is non-local, it is replaced with default non-local type#define FREE_MEM( mem_type, handle ) \ mem_free( \ di->memmgr[ mem_type == mt_nonlocal ? di->si->nonlocal_type : mem_type], \ handle, NULL ); #endifvoid Radeon_DiscardAllIndirectBuffers( device_info *di );#define RADEON_SCRATCH_REG_OFFSET 32void Radeon_FlushPixelCache( device_info *di );// wait until engine is idle;// acquire_lock - true, if lock must be hold// false, if lock is already acquired// keep_lock - true, keep lock on exit (only valid if acquire_lock is true)void Radeon_WaitForIdle( device_info *di, bool acquire_lock, bool keep_lock ){ if( acquire_lock ) ACQUIRE_BEN( di->si->cp.lock ); Radeon_WaitForFifo( di, 64 ); while( 1 ) { bigtime_t start_time = system_time(); do { if( (INREG( di->regs, RADEON_RBBM_STATUS ) & RADEON_RBBM_ACTIVE) == 0 ) { Radeon_FlushPixelCache( di ); if( acquire_lock && !keep_lock) RELEASE_BEN( di->si->cp.lock ); return; } snooze( 1 ); } while( system_time() - start_time < 1000000 ); SHOW_ERROR( 3, "Engine didn't become idle (rbbm_status=%lx, cp_stat=%lx, tlb_address=%lx, tlb_data=%lx)", INREG( di->regs, RADEON_RBBM_STATUS ), INREG( di->regs, RADEON_CP_STAT ), INREG( di->regs, RADEON_AIC_TLB_ADDR ), INREG( di->regs, RADEON_AIC_TLB_DATA )); LOG( di->si->log, _Radeon_WaitForIdle ); Radeon_ResetEngine( di ); }}// wait until "entries" FIFO entries are empty// lock must be holdvoid Radeon_WaitForFifo( device_info *di, int entries ){ while( 1 ) { bigtime_t start_time = system_time(); do { int slots = INREG( di->regs, RADEON_RBBM_STATUS ) & RADEON_RBBM_FIFOCNT_MASK; if ( slots >= entries ) return; snooze( 1 ); } while( system_time() - start_time < 1000000 ); LOG( di->si->log, _Radeon_WaitForFifo ); Radeon_ResetEngine( di ); }}// flush pixel cache of graphics cardvoid Radeon_FlushPixelCache( device_info *di ){ bigtime_t start_time; OUTREGP( di->regs, RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL, ~RADEON_RB2D_DC_FLUSH_ALL ); start_time = system_time(); do { if( (INREG( di->regs, RADEON_RB2D_DSTCACHE_CTLSTAT ) & RADEON_RB2D_DC_BUSY) == 0 ) return; snooze( 1 ); } while( system_time() - start_time < 1000000 ); LOG( di->si->log, _Radeon_FlushPixelCache ); SHOW_ERROR0( 0, "pixel cache didn't become empty" );}// reset graphics card's engine// lock must be holdvoid Radeon_ResetEngine( device_info *di ){ vuint8 *regs = di->regs; shared_info *si = di->si; uint32 clock_cntl_index, mclk_cntl, rbbm_soft_reset, host_path_cntl; uint32 cur_read_ptr; SHOW_FLOW0( 3, "" ); Radeon_FlushPixelCache( di ); clock_cntl_index = INREG( regs, RADEON_CLOCK_CNTL_INDEX ); R300_PLLFix( di->regs, di->asic ); // OUCH! // XFree disables any kind of automatic power power management // because of bugs of some ASIC revision (seems like the revisions // cannot be read out) // -> this is a very bad idea, especially when it comes to laptops // I comment it out for now, let's hope noone takes notice if( di->num_crtc > 1 ) { Radeon_OUTPLLP( regs, di->asic, RADEON_SCLK_CNTL, RADEON_CP_MAX_DYN_STOP_LAT | RADEON_SCLK_FORCEON_MASK, ~RADEON_DYN_STOP_LAT_MASK ); /* if( ai->si->asic == rt_rv200 ) { Radeon_OUTPLLP( ai, RADEON_SCLK_MORE_CNTL, RADEON_SCLK_MORE_FORCEON, ~0 ); }*/ } mclk_cntl = Radeon_INPLL( regs, di->asic, RADEON_MCLK_CNTL ); // enable clock of units to be reset Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl | RADEON_FORCEON_MCLKA | RADEON_FORCEON_MCLKB | RADEON_FORCEON_YCLKA | RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC | RADEON_FORCEON_AIC ); // do the reset host_path_cntl = INREG( regs, RADEON_HOST_PATH_CNTL ); rbbm_soft_reset = INREG( regs, RADEON_RBBM_SOFT_RESET ); switch( di->asic ) { case rt_r300: OUTREG( regs, RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_AIC )); INREG( regs, RADEON_RBBM_SOFT_RESET); OUTREG( regs, RADEON_RBBM_SOFT_RESET, 0); // this bit has no description OUTREGP( regs, RADEON_RB2D_DSTCACHE_MODE, (1 << 17), ~0 ); break; default: OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset | RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_RB | RADEON_SOFT_RESET_AIC ); INREG( regs, RADEON_RBBM_SOFT_RESET ); OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset & ~( RADEON_SOFT_RESET_CP | RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | RADEON_SOFT_RESET_E2 | RADEON_SOFT_RESET_RB | RADEON_SOFT_RESET_AIC ) ); INREG( regs, RADEON_RBBM_SOFT_RESET ); } OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET ); INREG( regs, RADEON_HOST_PATH_CNTL ); OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl ); // restore regs OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, clock_cntl_index ); R300_PLLFix( regs, di->asic ); Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl ); // reset ring buffer cur_read_ptr = INREG( regs, RADEON_CP_RB_RPTR ); OUTREG( regs, RADEON_CP_RB_WPTR, cur_read_ptr ); //if( si->cp.ring.head ) { // during init, there are no feedback data if( si->cp.feedback.mem_handle != 0 ) { *(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) = cur_read_ptr; // *si->cp.ring.head = cur_read_ptr; si->cp.ring.tail = cur_read_ptr; } ++si->engine.count; // mark all buffers as being finished Radeon_DiscardAllIndirectBuffers( di ); return;}// upload Micro-Code of CPstatic void loadMicroEngineRAMData( device_info *di ){ int i; const uint32 (*microcode)[2]; SHOW_FLOW0( 3, "" ); switch( di->asic ) { case rt_r300: case rt_r300_4p: case rt_rv350: case rt_rv360: case rt_r350: case rt_r360: microcode = r300_cp_microcode; break; case rt_r200:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -