Patch by Euan Kirkhope:
* VIP FIFO functions for Rage Theater200 support git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20278 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0caeca2af7
commit
7ce2eaa1e0
@ -20,8 +20,8 @@
|
||||
#include "ddc.h"
|
||||
|
||||
// magic code for ioctls
|
||||
// changed from TKRA to TKR1 for RADEON_WAITFORFIFO ioctl
|
||||
#define RADEON_PRIVATE_DATA_MAGIC 'TKR1'
|
||||
// changed from TKRA to TKR2 for VIP FIFO ioctls
|
||||
#define RADEON_PRIVATE_DATA_MAGIC 'TKR2'
|
||||
|
||||
#define MAX_RADEON_DEVICE_NAME_LENGTH MAXPATHLEN
|
||||
|
||||
@ -40,7 +40,10 @@ enum {
|
||||
RADEON_RESETENGINE,
|
||||
RADEON_VIPREAD,
|
||||
RADEON_VIPWRITE,
|
||||
RADEON_VIPFIFOREAD,
|
||||
RADEON_VIPFIFOWRITE,
|
||||
RADEON_FINDVIPDEVICE,
|
||||
RADEON_VIPRESET,
|
||||
|
||||
RADEON_WAIT_FOR_CAP_IRQ,
|
||||
RADEON_DMACOPY,
|
||||
@ -633,6 +636,26 @@ typedef struct {
|
||||
bool lock; // true, if CP lock must be acquired
|
||||
} radeon_vip_write;
|
||||
|
||||
// read VIP fifo
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
uint channel; // channel, i.e. device
|
||||
uint address; // address
|
||||
uint32 count; // size of buffer
|
||||
uint8 *data; // read data
|
||||
bool lock; // true, if CP lock must be acquired
|
||||
} radeon_vip_fifo_read;
|
||||
|
||||
// write VIP fifo
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
uint channel; // channel, i.e. device
|
||||
uint address; // address
|
||||
uint32 count; // size of buffer
|
||||
uint8 *data; // data to write
|
||||
bool lock; // true, if CP lock must be acquired
|
||||
} radeon_vip_fifo_write;
|
||||
|
||||
// find channel of device with given ID
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
@ -640,6 +663,13 @@ typedef struct {
|
||||
uint channel; // channel of device (-1 if not found)
|
||||
} radeon_find_vip_device;
|
||||
|
||||
// reset / init VIP
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
bool lock;
|
||||
} radeon_vip_reset;
|
||||
|
||||
|
||||
// wait for capture interrupt and get status about
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
|
@ -8,4 +8,4 @@
|
||||
*/
|
||||
|
||||
// current version
|
||||
#define RADEON_DRIVER_VERSION "Version: 5.1.4.9"
|
||||
#define RADEON_DRIVER_VERSION "Version: 5.1.5.0"
|
||||
|
@ -400,6 +400,26 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
|
||||
vw->lock ) ? B_OK : B_ERROR;
|
||||
} break;
|
||||
|
||||
case RADEON_VIPFIFOREAD: {
|
||||
radeon_vip_fifo_read *vr = (radeon_vip_fifo_read *)buf;
|
||||
|
||||
if( vr->magic != RADEON_PRIVATE_DATA_MAGIC )
|
||||
break;
|
||||
|
||||
result = Radeon_VIPFifoRead( di, vr->channel, vr->address, vr->count, vr->data,
|
||||
vr->lock ) ? B_OK : B_ERROR;
|
||||
} break;
|
||||
|
||||
case RADEON_VIPFIFOWRITE: {
|
||||
radeon_vip_fifo_write *vw = (radeon_vip_fifo_write *)buf;
|
||||
|
||||
if( vw->magic != RADEON_PRIVATE_DATA_MAGIC )
|
||||
break;
|
||||
|
||||
result = Radeon_VIPFifoWrite( di, vw->channel, vw->address, vw->count, vw->data,
|
||||
vw->lock ) ? B_OK : B_ERROR;
|
||||
} break;
|
||||
|
||||
case RADEON_FINDVIPDEVICE: {
|
||||
radeon_find_vip_device *fvd = (radeon_find_vip_device *)buf;
|
||||
|
||||
@ -409,7 +429,18 @@ static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
|
||||
fvd->channel = Radeon_FindVIPDevice( di, fvd->device_id );
|
||||
result = B_OK;
|
||||
} break;
|
||||
|
||||
|
||||
case RADEON_VIPRESET: {
|
||||
radeon_vip_reset *fvd = (radeon_vip_reset *)buf;
|
||||
|
||||
if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC )
|
||||
break;
|
||||
|
||||
Radeon_VIPReset( di, fvd->lock );
|
||||
result = B_OK;
|
||||
} break;
|
||||
|
||||
case RADEON_WAIT_FOR_CAP_IRQ: {
|
||||
radeon_wait_for_cap_irq *wvc = (radeon_wait_for_cap_irq *)buf;
|
||||
|
||||
|
@ -225,7 +225,10 @@ void Radeon_SetDynamicClock( device_info *di, int mode );
|
||||
// vip.c
|
||||
bool Radeon_VIPRead( device_info *di, uint channel, uint address, uint32 *data, bool lock );
|
||||
bool Radeon_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data, bool lock );
|
||||
bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock);
|
||||
bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock);
|
||||
int Radeon_FindVIPDevice( device_info *di, uint32 device_id );
|
||||
void Radeon_VIPReset( device_info *di, bool lock );
|
||||
|
||||
|
||||
// dma.c
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
// moved to bottom to avoid inlining
|
||||
static bool Radeon_VIPWaitForIdle( device_info *di );
|
||||
static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel);
|
||||
|
||||
|
||||
// read data from VIP
|
||||
@ -84,6 +85,96 @@ bool Radeon_VIPRead(
|
||||
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;
|
||||
}
|
||||
|
||||
static bool do_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer)
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
uint32 status, tmp;
|
||||
|
||||
if(count!=1)
|
||||
{
|
||||
SHOW_FLOW0( 2, "Attempt to access VIP bus with non-stadard transaction length\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SHOW_FLOW( 2, "address=%lx, count=%ld ", address, count );
|
||||
|
||||
Radeon_WaitForFifo( di, 2);
|
||||
SHOW_FLOW0( 2, "1");
|
||||
OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x3000);
|
||||
SHOW_FLOW0( 2, "3");
|
||||
while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
|
||||
if(B_OK != status) return false;
|
||||
|
||||
// disable VIPH_REGR_DIS to enable VIP cycle.
|
||||
// The LSB of VIPH_TIMEOUT_STAT are set to 0
|
||||
// because 1 would have acknowledged various VIP
|
||||
// interrupts unexpectedly
|
||||
|
||||
SHOW_FLOW0( 2, "4");
|
||||
Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
|
||||
SHOW_FLOW0( 2, "5");
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
|
||||
INREG( regs, RADEON_VIPH_TIMEOUT_STAT) &
|
||||
(0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS) );
|
||||
|
||||
// the value returned here is garbage. The read merely initiates
|
||||
// a register cycle
|
||||
SHOW_FLOW0( 2, "6");
|
||||
Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
|
||||
INREG( regs, RADEON_VIPH_REG_DATA);
|
||||
SHOW_FLOW0( 2, "7");
|
||||
while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
|
||||
if(B_OK != status) return false;
|
||||
|
||||
// set VIPH_REGR_DIS so that the read won't take too long.
|
||||
SHOW_FLOW0( 2, "8");
|
||||
Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
|
||||
SHOW_FLOW0( 2, "9");
|
||||
tmp = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
|
||||
|
||||
SHOW_FLOW0( 2, "10");
|
||||
Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
|
||||
switch(count){
|
||||
case 1:
|
||||
*buffer=(uint8)(INREG( regs, RADEON_VIPH_REG_DATA) & 0xff);
|
||||
break;
|
||||
case 2:
|
||||
*(uint16 *)buffer=(uint16) (INREG( regs, RADEON_VIPH_REG_DATA) & 0xffff);
|
||||
break;
|
||||
case 4:
|
||||
*(uint32 *)buffer=(uint32) ( INREG( regs, RADEON_VIPH_REG_DATA) & 0xffffffff);
|
||||
break;
|
||||
}
|
||||
SHOW_FLOW0( 2, "11");
|
||||
while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
|
||||
if(B_OK != status) return false;
|
||||
|
||||
// so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
|
||||
SHOW_FLOW0( 2, "12");
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
|
||||
(INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
|
||||
{
|
||||
bool res;
|
||||
|
||||
if( lock )
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
res = do_VIPFifoRead( di, channel, address, count, buffer );
|
||||
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
@ -95,31 +186,26 @@ bool Radeon_VIPRead(
|
||||
|
||||
// write data to VIP
|
||||
// CP must be hold
|
||||
static bool do_VIPWrite(
|
||||
device_info *di, uint8 channel, uint address, uint32 data )
|
||||
static 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;
|
||||
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 Radeon_VIPWaitForIdle( di );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// public function: write data to VIP
|
||||
bool Radeon_VIPWrite(
|
||||
device_info *di, uint8 channel, uint address, uint32 data, bool lock )
|
||||
bool Radeon_VIPWrite(device_info *di, uint8 channel, uint address, uint32 data, bool lock )
|
||||
{
|
||||
bool res;
|
||||
|
||||
@ -137,8 +223,64 @@ bool Radeon_VIPWrite(
|
||||
}
|
||||
|
||||
|
||||
static bool do_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer)
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
|
||||
uint32 status;
|
||||
uint32 i;
|
||||
|
||||
SHOW_FLOW( 2, "address=%lx, count=%ld, ", address, count );
|
||||
|
||||
Radeon_WaitForFifo( di, 2 );
|
||||
OUTREG( regs, RADEON_VIPH_REG_ADDR, ((channel << 14) | address | 0x1000) & ~0x2000 );
|
||||
SHOW_FLOW0( 2, "1");
|
||||
while(B_BUSY == (status = RADEON_VIPFifoIdle( di, 0x0f)));
|
||||
|
||||
|
||||
if(B_OK != status){
|
||||
SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n", (unsigned int)address);
|
||||
return false;
|
||||
}
|
||||
|
||||
SHOW_FLOW0( 2, "2");
|
||||
for (i = 0; i < count; i+=4)
|
||||
{
|
||||
Radeon_WaitForFifo( di, 2);
|
||||
SHOW_FLOW( 2, "count %ld", count);
|
||||
OUTREG( regs, RADEON_VIPH_REG_DATA, *(uint32*)(buffer + i));
|
||||
while(B_BUSY == (status = RADEON_VIPFifoIdle( di, 0x0f)));
|
||||
if(B_OK != status)
|
||||
{
|
||||
SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
|
||||
{
|
||||
bool res;
|
||||
|
||||
//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
|
||||
|
||||
if( lock )
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
Radeon_VIPReset( di, false);
|
||||
res = do_VIPFifoWrite( di, channel, address, count, buffer );
|
||||
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// reset VIP
|
||||
static void VIPReset(
|
||||
void Radeon_VIPReset(
|
||||
device_info *di, bool lock )
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
@ -146,27 +288,43 @@ static void VIPReset(
|
||||
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 );
|
||||
Radeon_WaitForFifo( di, 5 ); // Radeon_WaitForIdle( di, false, false );
|
||||
switch(di->asic){
|
||||
case rt_r200:
|
||||
case rt_rs200:
|
||||
case rt_rv200:
|
||||
case rt_rs100:
|
||||
case rt_rv100:
|
||||
case rt_r100:
|
||||
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 ); // slowest, timeout in 16 phases
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
|
||||
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)); // set timeslice
|
||||
OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x151);
|
||||
OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
|
||||
default:
|
||||
OUTREG( regs, RADEON_VIPH_CONTROL, 9 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |
|
||||
RADEON_VIPH_CONTROL_VIPH_DMA_MODE | RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
|
||||
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)); // set timeslice
|
||||
OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x0);
|
||||
OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if( lock )
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
}
|
||||
@ -184,25 +342,30 @@ static status_t Radeon_VIPIdle(
|
||||
|
||||
// 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;
|
||||
if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 )
|
||||
{
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
|
||||
(timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK);
|
||||
return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : 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;
|
||||
return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK;
|
||||
}
|
||||
|
||||
static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel)
|
||||
{
|
||||
vuint8 *regs = di->regs;
|
||||
uint32 timeout;
|
||||
|
||||
timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
|
||||
if((timeout & 0x0000000f) & channel) /* lockup ?? */
|
||||
{
|
||||
OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel);
|
||||
return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
|
||||
}
|
||||
return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK ;
|
||||
}
|
||||
|
||||
|
||||
// wait until VIP host is idle
|
||||
// lock must be hold
|
||||
static bool Radeon_VIPWaitForIdle(
|
||||
@ -240,23 +403,28 @@ int Radeon_FindVIPDevice(
|
||||
|
||||
// if card has no VIP port, let hardware detection fail;
|
||||
// in this case, noone will bother us again
|
||||
if( !di->has_vip )
|
||||
if( !di->has_vip ) {
|
||||
SHOW_FLOW0( 3, "This Device has no VIP Bus.");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
ACQUIRE_BEN( di->si->cp.lock );
|
||||
|
||||
VIPReset( di, false );
|
||||
Radeon_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 ))
|
||||
if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false )) {
|
||||
SHOW_FLOW( 3, "No device found on channel %d", channel);
|
||||
continue;
|
||||
}
|
||||
|
||||
// compare device id directly
|
||||
if( cur_device_id == device_id ) {
|
||||
SHOW_FLOW( 3, "Device %08lx found on channel %d", device_id, channel);
|
||||
RELEASE_BEN( di->si->cp.lock );
|
||||
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user