⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vip.c

📁 ati driver
💻 C
字号:
/*	Copyright (c) 2002-04, Thomas Kurschel		Part of Radeon accelerant			Access to VIP		This code must be in kernel because we need for FIFO to become empty	during VIP access (which in turn requires locking the card, and locking	is a dangerous thing in user mode as the app can suddenly die, taking	the lock with it)*/#include "radeon_driver.h"#include "../shared/mmio.h"#include "../regs/vip_regs.h"#include "../regs/bios_regs.h"#include "../regs/theatre_regs.h"// moved to bottom to avoid inliningstatic bool Radeon_VIPWaitForIdle( device_info *di );// read data from VIP// CP lock must be holdstatic bool do_VIPRead( 	device_info *di, uint channel, uint address, uint32 *data ){	vuint8 *regs = di->regs;	Radeon_WaitForFifo( di, 2 );	// the 0x2000 is the nameless "register-read" flag	OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x2000 );		if( !Radeon_VIPWaitForIdle( di ))		return false;	// enable VIP register cycle reads	Radeon_WaitForFifo( di, 2 );	OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 0, 		~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );	//Radeon_WaitForIdle( di, false, false );		// this read starts a register cycle; the returned value has no meaning	INREG( regs, RADEON_VIPH_REG_DATA );		if( !Radeon_VIPWaitForIdle( di ))		return false;			//Radeon_WaitForIdle( di, false, false );		// register cycle is done, so disable any further cycle	Radeon_WaitForFifo( di, 2 );	OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 		~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );	//Radeon_WaitForIdle( di, false, false );		// get the data	*data = INREG( regs, RADEON_VIPH_REG_DATA );		//SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data );	if( !Radeon_VIPWaitForIdle( di ))		return false;	// disable register cycle again (according to sample code)	// IMHO, this is not necessary as it has been done before	Radeon_WaitForFifo( di, 2 );	OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 		~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );	return true;}// public function: read data from VIPbool Radeon_VIPRead( 	device_info *di, uint channel, uint address, uint32 *data, bool lock ){	bool res;	if( lock )		ACQUIRE_BEN( di->si->cp.lock );		res = do_VIPRead( di, channel, address, data );		if( lock )		RELEASE_BEN( di->si->cp.lock );			//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );	return res;}// write data to VIP// CP must be holdstatic bool do_VIPWrite( 	device_info *di, uint8 channel, uint address, uint32 data ){	vuint8 *regs = di->regs;	bool res;	Radeon_WaitForFifo( di, 2 );	OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) );	if( !Radeon_VIPWaitForIdle( di ))		return false;			//SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data );			Radeon_WaitForFifo( di, 2 );	OUTREG( regs, RADEON_VIPH_REG_DATA, data );		res = Radeon_VIPWaitForIdle( di );			return res;}// public function: write data to VIPbool Radeon_VIPWrite( 	device_info *di, uint8 channel, uint address, uint32 data, bool lock ){	bool res;	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );	if( lock )		ACQUIRE_BEN( di->si->cp.lock );		res = do_VIPWrite( di, channel, address, data );		if( lock )		RELEASE_BEN( di->si->cp.lock );		return res;}// reset VIPstatic void VIPReset( 	device_info *di, bool lock ){	vuint8 *regs = di->regs;	if( lock )		ACQUIRE_BEN( di->si->cp.lock );	Radeon_WaitForFifo( di, 5 );	OUTREG( regs, RADEON_VIPH_CONTROL, 		4 | 		(15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |		RADEON_VIPH_CONTROL_VIPH_DMA_MODE |		RADEON_VIPH_CONTROL_VIPH_EN );	OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 		~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);	OUTREG( regs, RADEON_VIPH_DV_LAT, 		0xff |		(4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) |		(4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) |		(4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) |		(4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT));	OUTREG( regs, RADEON_VIPH_DMA_CHUNK,		1 |		(1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH1_CHUNK_SHIFT) |		(1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH2_CHUNK_SHIFT) |		(1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH3_CHUNK_SHIFT));	OUTREGP( regs, RADEON_TEST_DEBUG_CNTL, 0, ~RADEON_TEST_DEBUG_CNTL_OUT_EN );	if( lock )		RELEASE_BEN( di->si->cp.lock );}// check whether VIP host is idle// lock must be holdstatic status_t Radeon_VIPIdle( 	device_info *di ){	vuint8 *regs = di->regs;	uint32 timeout;		//Radeon_WaitForIdle( di, false, false );		// if there is a stuck transaction, acknowledge that	timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT );	if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 ) {		OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 			RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK, 			~RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK & ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK );		if( (INREG( regs, RADEON_VIPH_CONTROL) & RADEON_VIPH_CONTROL_VIPH_REG_RDY) != 0 )			return B_BUSY;		else			return B_ERROR;	}		//Radeon_WaitForIdle( di, false, false );		if( (INREG( regs, RADEON_VIPH_CONTROL) & RADEON_VIPH_CONTROL_VIPH_REG_RDY) != 0 )		return B_BUSY;	else		return B_OK;}// wait until VIP host is idle// lock must be holdstatic bool Radeon_VIPWaitForIdle( 	device_info *di ){	int i;		// wait 100x 1ms before giving up	for( i = 0; i < 100; ++i ) {		status_t res;				res = Radeon_VIPIdle( di );		if( res != B_BUSY ) {			if( res == B_OK )				return true;			else				return false;		}					snooze( 1000 );	}		return false;}// find VIP channel of a device// return:	>= 0 channel of device//			< 0 no device foundint Radeon_FindVIPDevice( 	device_info *di, uint32 device_id ){	uint channel;	uint32 cur_device_id;		// if card has no VIP port, let hardware detection fail;	// in this case, noone will bother us again	if( !di->has_vip )		return -1;		ACQUIRE_BEN( di->si->cp.lock );	VIPReset( di, false );	// there are up to 4 devices, connected to one of 4 channels		for( channel = 0; channel < 4; ++channel ) {		// read device id		if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false ))			continue;				// compare device id directly		if( cur_device_id == device_id ) {			RELEASE_BEN( di->si->cp.lock );						return channel;		}	}		RELEASE_BEN( di->si->cp.lock );		// couldn't find device	return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -