示例#1
0
static OSDEV_IoctlEntrypoint( H264ppIoctl )
{
OSDEV_Status_t           Status;
H264ppContext_t      *H264ppContext;

/* --- */

    OSDEV_IoctlEntry();
    H264ppContext    = (H264ppContext_t  *)OSDEV_PrivateData;

    switch( OSDEV_IoctlCode )
    {
	case H264_PP_IOCTL_QUEUE_BUFFER:
			Status = H264ppIoctlQueueBuffer(                H264ppContext, OSDEV_ParameterAddress );
			break;

	case H264_PP_IOCTL_GET_PREPROCESSED_BUFFER:
			Status = H264ppIoctlGetPreprocessedBuffer(      H264ppContext, OSDEV_ParameterAddress );
			break;

	default:        OSDEV_Print( "H264ppIoctl : Invalid ioctl %08x\n", OSDEV_IoctlCode );
			Status = OSDEV_Error;
    }

/* --- */

    OSDEV_IoctlExit( Status );
}
示例#2
0
static OSDEV_OpenEntrypoint(  AllocatorOpen )
{
AllocatorContext_t      *AllocatorContext;

    //
    // Entry
    //

    OSDEV_OpenEntry();

    //
    // Allocate and initialize the private data structure.
    //

    AllocatorContext    = (AllocatorContext_t *)OSDEV_Malloc( sizeof(AllocatorContext_t) );
    OSDEV_PrivateData   = (void *)AllocatorContext;

    if( AllocatorContext == NULL )
    {
	OSDEV_Print( "AllocatorOpen - Unable to allocate memory for open context.\n" );
	OSDEV_OpenExit( OSDEV_Error );
    }

//

    memset( AllocatorContext, 0x00, sizeof(AllocatorContext_t) );

    AllocatorContext->Size      = 0;
    AllocatorContext->Memory    = NULL;

//

    OSDEV_OpenExit( OSDEV_NoError );
}
示例#3
0
OS_Status_t OS_GetMessageCode(OS_MessageQueue_t Queue,
			      unsigned int *Code,
			      bool Blocking)
{
	OSDEV_Print("%s not implemented\n", __FUNCTION__);
	return OS_ERROR;
}
static void __exit StmUnloadModule (void)
{

    Mpeg2InterruptUninstall();
    UnMapRegisters();

    OSDEV_Print("Module unloaded\n");
}
static int __init StmLoadModule(void)
{
	MME_ERROR status = MME_SUCCESS;
	// Now do the MME Init
	status =  MME_RegisterTransformer(
				  mmeName,
				  abortCmd,
				  getTransformerCapability,
				  initTransformer,
				  processCommand,
				  termTransformer);
	if (status == MME_SUCCESS)
		OSDEV_Print("%s loaded\n", MODULE_NAME);
	else
		OSDEV_Print("Error registering %s with MME (%d)\n", MODULE_NAME, status);
	return status;
}
示例#6
0
static OSDEV_CloseEntrypoint(  AllocatorClose )
{
AllocatorContext_t      *AllocatorContext;

//

    OSDEV_CloseEntry();
    AllocatorContext    = (AllocatorContext_t  *)OSDEV_PrivateData;

    //
    // Perform the release activity
    //

    if( AllocatorContext->Memory != NULL )
    {
        // Do what is necessary to free up any mapping here
        
//        OSDEV_Print( "Freeing up bpa 2 partition - phys %p - C %p - UC %p\n", AllocatorContext->PhysicalAddress,AllocatorContext->CachedAddress,AllocatorContext->UnCachedAddress);
#if defined(MULTICOM406)
        ICS_ERROR IcsErr;

        IcsErr = ICS_region_remove(AllocatorContext->CachedRegion, 0);
        if( IcsErr != ICS_SUCCESS )
        {
            OSDEV_Print( "Close Entry Point - Unable to remove Cached ICS region.\n" );
       }

        IcsErr = ICS_region_remove(AllocatorContext->UnCachedRegion, 0);
        if( IcsErr != ICS_SUCCESS )
        {
            OSDEV_Print( "Close Entry Point - Unable to remove Uncached ICS region.\n" );
        }
#endif
        OSDEV_IOUnMap( (unsigned int)AllocatorContext->UnCachedAddress );
        OSDEV_IOUnMap( (unsigned int)AllocatorContext->CachedAddress );
        OSDEV_FreePartitioned( AllocatorContext->PartitionName, AllocatorContext->PhysicalAddress );
        
    }

    OSDEV_Free( AllocatorContext );

//

    OSDEV_CloseExit( OSDEV_NoError );
}
示例#7
0
static OSDEV_Status_t AllocatorIoctlAllocateData( AllocatorContext_t    *AllocatorContext,
						  unsigned int           ParameterAddress )
{
allocator_ioctl_allocate_t      params;

//

    OSDEV_CopyToDeviceSpace( &params, ParameterAddress, sizeof(allocator_ioctl_allocate_t) );

//

    AllocatorContext->Size              = params.RequiredSize;
    memcpy( AllocatorContext->PartitionName, params.PartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE );

//

    AllocatorContext->Memory        = OSDEV_MallocPartitioned( 	AllocatorContext->PartitionName, 
								AllocatorContext->Size );

    if( AllocatorContext->Memory == NULL )
    {
	OSDEV_Print( "AllocatorIoctlAllocateData : Unable to allocate memory\n" );
	return OSDEV_Error;
    }

    //
    // The memory supplied by BPA2 is physical, get the necessary mappings
    //

    AllocatorContext->CachedAddress	= NULL;
    AllocatorContext->UnCachedAddress	= NULL;
    AllocatorContext->PhysicalAddress	= NULL;

        
    AllocatorContext->CachedAddress	= ioremap_cache((unsigned int)AllocatorContext->Memory,AllocatorContext->Size);
    AllocatorContext->PhysicalAddress	= AllocatorContext->Memory ;
    AllocatorContext->UnCachedAddress	= (unsigned char *)OSDEV_IOReMap( (unsigned int)AllocatorContext->PhysicalAddress, AllocatorContext->Size );

/*    
    OSDEV_Print("Alloc - Phys %p - C %p - UC %p  -- Size 0x%x\n",AllocatorContext->PhysicalAddress,
                AllocatorContext->CachedAddress, AllocatorContext->UnCachedAddress,AllocatorContext->Size);
*/    
    //
    // Copy the data into the parameters and pass back 
    //

    params.CachedAddress	= AllocatorContext->CachedAddress;
    params.UnCachedAddress	= AllocatorContext->UnCachedAddress;
    params.PhysicalAddress	= AllocatorContext->PhysicalAddress;

    OSDEV_CopyToUserSpace( ParameterAddress, &params, sizeof(allocator_ioctl_allocate_t) );

//

    return OSDEV_NoError;
}
示例#8
0
static OSDEV_Status_t H264ppIoctlGetPreprocessedBuffer( H264ppContext_t         *H264ppContext,
							unsigned int             ParameterAddress )
{
h264pp_ioctl_dequeue_t           params;
H264ppProcessedBuffer_t		*Record;

//

    do
    {
	//
	// Anything to report
	//

	if( H264ppContext->BufferProcessed[H264ppContext->BufferProcessedExtract].Filled )
	{
	    Record					 = &H264ppContext->BufferProcessed[H264ppContext->BufferProcessedExtract++];
	    H264ppContext->BufferProcessedExtract	%= H264_PP_MAX_SUPPORTED_BUFFERS;

#if 0
	    if( Record->PP_ITS != PP_ITM__DMA_CMP )
		printk( "H264ppIoctlGPB (PP %d)  - Took %dms - ITS = %04x - QID = %d\n", Record->PP, Record->DecodeTime, Record->PP_ITS, Record->QueueIdentifier );
#endif

	    //
	    // Take the buffer
	    //

	    params.QueueIdentifier	= Record->QueueIdentifier;
	    params.OutputSize		= Record->OutputSize;
	    params.ErrorMask		= Record->PP_ITS & ~(PP_ITM__SRS_COMP | PP_ITM__DMA_CMP);
	    OSDEV_CopyToUserSpace( ParameterAddress, &params, sizeof(h264pp_ioctl_dequeue_t) );

	    //
	    // Free up the record for re-use
	    //

	    Record->Filled		= 0;
	    OSDEV_ReleaseSemaphore( &H264ppContext->ProcessedBufferListEntry );

	    return OSDEV_NoError;
	}

	//
	// Wait for a buffer completed signal
	//

	OSDEV_ClaimSemaphore( &H264ppContext->ProcessedBuffer );

    } while( !H264ppContext->Closing );

//

    OSDEV_Print( "H264ppIoctlGetPreprocessedBuffer - device closing.\n" );
    return OSDEV_Error;
}
示例#9
0
static OSDEV_MmapEntrypoint( H264ppMmap )
{
H264ppContext_t  *H264ppContext;
OSDEV_Status_t    MappingStatus;

//

    OSDEV_MmapEntry();
    H264ppContext    = (H264ppContext_t  *)OSDEV_PrivateData;

//

    OSDEV_Print( "H264ppMmap - No allocated memory to map.\n" );
    MappingStatus	= OSDEV_Error;

//

    OSDEV_MmapExit( MappingStatus );
}
示例#10
0
static OSDEV_IoctlEntrypoint( AllocatorIoctl )
{
OSDEV_Status_t           Status;
AllocatorContext_t      *AllocatorContext;

/* --- */

    OSDEV_IoctlEntry();
    AllocatorContext    = (AllocatorContext_t  *)OSDEV_PrivateData;

    switch( OSDEV_IoctlCode )
    {
	case    ALLOCATOR_IOCTL_ALLOCATE_DATA:  Status = AllocatorIoctlAllocateData(    AllocatorContext, OSDEV_ParameterAddress );             break;

	default:        OSDEV_Print( "AllocatorIoctl : Invalid ioctl %08x\n", OSDEV_IoctlCode );
			Status = OSDEV_Error;
    }

/* --- */

    OSDEV_IoctlExit( Status );
}
示例#11
0
static OSDEV_Status_t AllocatorIoctlAllocateData( AllocatorContext_t    *AllocatorContext,
						  unsigned int           ParameterAddress )
{
allocator_ioctl_allocate_t      params;
#if defined(MULTICOM406)
ICS_ERROR IcsErr;
#endif

//

    OSDEV_CopyToDeviceSpace( &params, ParameterAddress, sizeof(allocator_ioctl_allocate_t) );

//

    AllocatorContext->Size              = params.RequiredSize;
    memcpy( AllocatorContext->PartitionName, params.PartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE );

//

    AllocatorContext->Memory        = OSDEV_MallocPartitioned( 	AllocatorContext->PartitionName, 
								AllocatorContext->Size );

    if( AllocatorContext->Memory == NULL )
    {
	OSDEV_Print( "AllocatorIoctlAllocateData : Unable to allocate memory\n" );
	return OSDEV_Error;
    }

    //
    // The memory supplied by BPA2 is physical, get the necessary mappings
    //

    AllocatorContext->CachedAddress	= NULL;
    AllocatorContext->UnCachedAddress	= NULL;
    AllocatorContext->PhysicalAddress	= NULL;

        
    AllocatorContext->CachedAddress	= ioremap_cache((unsigned int)AllocatorContext->Memory,AllocatorContext->Size);
    AllocatorContext->PhysicalAddress	= AllocatorContext->Memory ;
    AllocatorContext->UnCachedAddress	= (unsigned char *)OSDEV_IOReMap( (unsigned int)AllocatorContext->PhysicalAddress, AllocatorContext->Size );

#if defined(MULTICOM406)
    IcsErr = ICS_region_add(AllocatorContext->CachedAddress, AllocatorContext->PhysicalAddress, AllocatorContext->Size,
                         ICS_CACHED, ics_cpu_mask(), &AllocatorContext->CachedRegion);
    if( IcsErr != ICS_SUCCESS )
    {
        OSDEV_Print( "AllocatorIoctlAllocateData : - Unable to allocate Cached ICS region.\n" );
        return OSDEV_Error;
    }

    IcsErr = ICS_region_add(AllocatorContext->UnCachedAddress, AllocatorContext->PhysicalAddress, AllocatorContext->Size,
                            ICS_UNCACHED, ics_cpu_mask(), &AllocatorContext->UnCachedRegion);
    if( IcsErr != ICS_SUCCESS )
    {
        OSDEV_Print( "AllocatorIoctlAllocateData : - Unable to allocate Uncached ICS region.\n" );
        return OSDEV_Error;
    }
#endif

/*    
    OSDEV_Print("Alloc - Phys %p - C %p - UC %p  -- Size 0x%x\n",AllocatorContext->PhysicalAddress,
                AllocatorContext->CachedAddress, AllocatorContext->UnCachedAddress,AllocatorContext->Size);
*/    
    //
    // Copy the data into the parameters and pass back 
    //

    params.CachedAddress	= AllocatorContext->CachedAddress;
    params.UnCachedAddress	= AllocatorContext->UnCachedAddress;
    params.PhysicalAddress	= AllocatorContext->PhysicalAddress;

    OSDEV_CopyToUserSpace( ParameterAddress, &params, sizeof(allocator_ioctl_allocate_t) );

//

    return OSDEV_NoError;
}
示例#12
0
OS_Status_t OS_SendMessageCode(OS_MessageQueue_t Queue,
			       unsigned int Code)
{
	OSDEV_Print("%s not implemented\n", __FUNCTION__);
	return OS_ERROR;
}
示例#13
0
OS_Status_t OS_InitializeMessageQueue(OS_MessageQueue_t *Queue)
{
	OSDEV_Print("%s not implemented\n", __FUNCTION__);
	return OS_ERROR;
}
示例#14
0
static void H264ppWorkAroundGNBvd42331( H264ppIndividualContext_t	 *SubContext,
					unsigned int			  N )
{
unsigned int	i;
unsigned int	mb_adaptive_frame_field_flag;
unsigned int	entropy_coding_mode_flag;
unsigned int	PerformWorkaround;
unsigned int	SavedITM;
unsigned int	BufferBase;
unsigned int	SourceAddress;
unsigned int	EndAddress;
unsigned int	SliceErrorStatusAddress;
unsigned int	IntermediateAddress;
unsigned int	IntermediateEndAddress;

    //
    // Do we have to worry.
    //

    mb_adaptive_frame_field_flag			= ((SubContext->Parameters.Cfg & 1) != 0);
    entropy_coding_mode_flag				= ((SubContext->Parameters.Cfg & 2) != 0);

    PerformWorkaround					= !mb_adaptive_frame_field_flag && 
							  SubContext->last_mb_adaptive_frame_field_flag &&
							  entropy_coding_mode_flag;

    SubContext->last_mb_adaptive_frame_field_flag	= mb_adaptive_frame_field_flag;

    if( !PerformWorkaround && !SubContext->ForceWorkAroundGNBvd42331 )
	return;

//OSDEV_Print( "H264ppWorkAroundGNBvd42331 - Deploying GNBvd42331 workaround block to PP %d - %08x.\n", N, SubContext->Parameters.Cfg );

    SubContext->ForceWorkAroundGNBvd42331	= 0;

    //
    // we transfer the workaround stream to the output buffer (offset by 64k to not interfere with the output).
    //

    memcpy( (void *)((unsigned int)SubContext->Parameters.BufferCachedAddress + 0x10000), GNBvd42331Data, sizeof(GNBvd42331Data) );

    GNBvd42331DataPhysicalAddress	= (unsigned char *)SubContext->Parameters.BufferPhysicalAddress + 0x10000;

#ifdef __TDT__
/* found somewhere this patch which should increase performance about 1%.
 * ->should be revised!
 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
    dma_cache_wback((SubContext->Parameters.BufferCachedAddress + 0x10000),sizeof(GNBvd42331Data));
#else
    writeback_ioremap_region(0, (SubContext->Parameters.BufferCachedAddress + 0x10000),
    		0, sizeof(GNBvd42331Data));
#endif

#else
    flush_cache_all();
#endif

    //
    // Derive the pointers - we use the next buffer to be queued as output as our output 
    //

    BufferBase                  = (unsigned int)SubContext->Parameters.BufferPhysicalAddress;

    SliceErrorStatusAddress     = BufferBase;
    IntermediateAddress         = BufferBase + H264_PP_SESB_SIZE;
    IntermediateEndAddress      = IntermediateAddress + H264_PP_OUTPUT_SIZE - 1;
    SourceAddress               = (unsigned int)GNBvd42331DataPhysicalAddress;
    EndAddress                  = (unsigned int)GNBvd42331DataPhysicalAddress + sizeof(GNBvd42331Data) - 1;

    //
    // Launch the workaround block
    //

    SavedITM		= OSDEV_ReadLong(PP_ITM(N));			// Turn off interrupts
    OSDEV_WriteLong( PP_ITM(N), 0 );

    OSDEV_WriteLong( PP_BBG(N),                 (SourceAddress & 0xfffffff8) );
    OSDEV_WriteLong( PP_BBS(N),                 (EndAddress    | 0x7) );
    OSDEV_WriteLong( PP_READ_START(N),          SourceAddress );
    OSDEV_WriteLong( PP_READ_STOP(N),           EndAddress );

    OSDEV_WriteLong( PP_ISBG(N),                SliceErrorStatusAddress );
    OSDEV_WriteLong( PP_IPBG(N),                IntermediateAddress );
    OSDEV_WriteLong( PP_IBS(N),                 IntermediateEndAddress );

    OSDEV_WriteLong( PP_CFG(N),                 GNBvd42331_CFG );
    OSDEV_WriteLong( PP_PICWIDTH(N),            GNBvd42331_PICWIDTH );
    OSDEV_WriteLong( PP_CODELENGTH(N),          GNBvd42331_CODELENGTH );

    OSDEV_WriteLong( PP_ITS(N),                 0xffffffff );		// Clear interrupt status
    OSDEV_WriteLong( PP_START(N),               1 );

    //
    // Wait for it to complete
    //

    for( i=0; i<H264_PP_RESET_TIME_LIMIT; i++ )
    {
	OSDEV_SleepMilliSeconds( 1 );

	if( (OSDEV_ReadLong(PP_ITS(N)) & PP_ITM__DMA_CMP) != 0 )
	    break;

    }

    if( (i == H264_PP_RESET_TIME_LIMIT) || (OSDEV_ReadLong(PP_ITS(N)) != PP_ITM__DMA_CMP) )
	OSDEV_Print( "H264ppWorkAroundGNBvd42331 - Failed to execute GNBvd42331 workaround block to PP %d (ITS %08x).\n", N, OSDEV_ReadLong(PP_ITS(N)) );

    //
    // Restore the interrupts
    //

    OSDEV_WriteLong( PP_ITS(N),                     0xffffffff );           // Clear interrupt status
    OSDEV_WriteLong( PP_ITM(N), SavedITM );

}
示例#15
0
static OSDEV_Status_t H264ppIoctlQueueBuffer(   H264ppContext_t         *H264ppContext,
						unsigned int             ParameterAddress )
{
unsigned int                     i;
H264ppIndividualContext_t       *SubContext;
h264pp_ioctl_queue_t            *params;
unsigned int                     N;
unsigned int                     BufferBase;
unsigned int                     SourceAddress;
unsigned int                     EndAddress;
unsigned int                     SliceErrorStatusAddress;
unsigned int                     IntermediateAddress;
unsigned int                     IntermediateEndAddress;

    //
    // Claim resources
    //

    OSDEV_ClaimSemaphore( &H264ppContext->ProcessedBufferListEntry );   // Claim somewhere to store a record of the preprocessor output
    OSDEV_ClaimSemaphore( &H264ppContext->PreProcessor );               // Claim the preprocessor hardware

    if( H264ppContext->Closing )
    {
	OSDEV_Print( "H264ppIoctlQueueBuffer - device closing.\n" );
	return OSDEV_Error;
    }

    for( i=0; i<H264_PP_PER_INSTANCE; i++ )
	if( !H264ppContext->SubContext[i].Busy )
	{
	    SubContext          = &H264ppContext->SubContext[i];
	    N                   = H264ppContext->Index + i;
	    SubContext->Busy    = 1;
	    break;
	}

    if( i >= H264_PP_PER_INSTANCE )
    {
	OSDEV_Print( "H264ppIoctlQueueBuffer - No free sub-context - implementation error (should be one, the semaphore says there is).\n" );
	return OSDEV_Error;
    }

//

    params			= &SubContext->Parameters;
    OSDEV_CopyToDeviceSpace( params, ParameterAddress, sizeof(h264pp_ioctl_queue_t) );

    //
    // Optionally check for and perform the workaround to GNBvd42331
    //

    if( h264_pp_workaround_gnbvd42331 )
	H264ppWorkAroundGNBvd42331( SubContext, N );

    //
    // Calculate the address values
    //

    BufferBase                  = (unsigned int)params->BufferPhysicalAddress;

    SliceErrorStatusAddress     = BufferBase;
    IntermediateAddress         = BufferBase + H264_PP_SESB_SIZE;
    IntermediateEndAddress      = IntermediateAddress + H264_PP_OUTPUT_SIZE - 1;
    SourceAddress               = IntermediateAddress + H264_PP_OUTPUT_SIZE;
    EndAddress                  = SourceAddress + params->InputSize - 1;

    //
    // Program the preprocessor
    //
    // Standard pre-processor initialization
    //

    flush_cache_all();
    OSDEV_WriteLong( PP_ITS(N),                 0xffffffff );                           // Clear interrupt status

#if 1
    OSDEV_WriteLong( PP_ITM(N),                 PP_ITM__BIT_BUFFER_OVERFLOW |           // We are interested in every interrupt
						PP_ITM__BIT_BUFFER_UNDERFLOW |
						PP_ITM__INT_BUFFER_OVERFLOW |
						PP_ITM__ERROR_BIT_INSERTED |
						PP_ITM__ERROR_SC_DETECTED |
						PP_ITM__SRS_COMP |
						PP_ITM__DMA_CMP );
#else
    OSDEV_WriteLong( PP_ITM(N),                 PP_ITM__DMA_CMP );
#endif

    //
    // Setup the decode
    //

    OSDEV_WriteLong( PP_BBG(N),                 (SourceAddress & 0xfffffff8) );
    OSDEV_WriteLong( PP_BBS(N),                 (EndAddress    | 0x7) );
    OSDEV_WriteLong( PP_READ_START(N),          SourceAddress );
    OSDEV_WriteLong( PP_READ_STOP(N),           EndAddress );

    OSDEV_WriteLong( PP_ISBG(N),                SliceErrorStatusAddress );
    OSDEV_WriteLong( PP_IPBG(N),                IntermediateAddress );
    OSDEV_WriteLong( PP_IBS(N),                 IntermediateEndAddress );

    OSDEV_WriteLong( PP_CFG(N),                 PP_CFG__CONTROL_MODE__START_STOP | params->Cfg );
    OSDEV_WriteLong( PP_PICWIDTH(N),            params->PicWidth );
    OSDEV_WriteLong( PP_CODELENGTH(N),          params->CodeLength );

    //
    // Launch the pre-processor
    //

    SubContext->BufferProcessedInsert		= H264ppContext->BufferProcessedInsert++;
    SubContext->DecodeTime             		= OSDEV_GetTimeInMilliSeconds();
    SubContext->Accumulated_ITS			= 0;

    OSDEV_WriteLong( PP_START(N),               1 );

//

    H264ppContext->BufferProcessedInsert	%= H264_PP_MAX_SUPPORTED_BUFFERS;

//

    return OSDEV_NoError;
}
示例#16
0
static OSDEV_OpenEntrypoint(  H264ppOpen )
{
unsigned int      i,j;
H264ppContext_t  *H264ppContext;
int               Status;
unsigned int      N;

    //
    // Entry
    //

    OSDEV_OpenEntry();

    //
    // Is there a set of PPs to get.
    //

    OSDEV_ClaimSemaphore( &Lock );
    if( OpenMask == ((1 << H264_PP_NUMBER_OF_PRE_PROCESSORS) - 1) )
    {
	OSDEV_Print( "H264ppOpen - Too many opens.\n" );
	OSDEV_ReleaseSemaphore( &Lock );
	OSDEV_OpenExit( OSDEV_Error );
    }

    //
    // Allocate and initialize the private data structure.
    //

    H264ppContext    = (H264ppContext_t *)OSDEV_Malloc( sizeof(H264ppContext_t) );
    OSDEV_PrivateData   = (void *)H264ppContext;

    if( H264ppContext == NULL )
    {
	OSDEV_Print( "H264ppOpen - Unable to allocate memory for open context.\n" );
	OSDEV_ReleaseSemaphore( &Lock );
	OSDEV_OpenExit( OSDEV_Error );
    }

//

    memset( H264ppContext, 0x00, sizeof(H264ppContext_t) );

    H264ppContext->Closing              = false;

    //
    // Find a free pair of PPs
    //

    for( H264ppContext->Index   = 0;
	 ((OpenMask & (H264_PP_PER_INSTANCE_MASK<<H264ppContext->Index)) != 0);
	 H264ppContext->Index += H264_PP_PER_INSTANCE );

    OpenMask    |= (H264_PP_PER_INSTANCE_MASK<<H264ppContext->Index);

    //
    // Initialize the processed buffer list indices
    //

    H264ppContext->BufferProcessedInsert	= 0;
    H264ppContext->BufferProcessedExtract	= 0;

    //
    // Initialize the semaphores
    //

    OSDEV_InitializeSemaphore( &H264ppContext->PreProcessor, H264_PP_PER_INSTANCE ); 				// No one currently using the pre-processors - so they are free
    OSDEV_InitializeSemaphore( &H264ppContext->ProcessedBufferListEntry, H264_PP_MAX_SUPPORTED_BUFFERS );	// The table contains this many entries
    OSDEV_InitializeSemaphore( &H264ppContext->ProcessedBuffer, 0 );                    			// There are no processed buffers to signal

    //
    // Ensure we will have no interrupt surprises and install the interrupt handler
    //

    for( i=0; i<H264_PP_PER_INSTANCE; i++ )
    {
	N = H264ppContext->Index + i;

	OSDEV_WriteLong( PP_ITS(N),                     0xffffffff );           // Clear interrupt status
	OSDEV_WriteLong( PP_ITM(N),                     0x00000000 );

	//
	// Initialize subcontect data
	//

	H264ppContext->SubContext[i].ForceWorkAroundGNBvd42331		= 1;
	H264ppContext->SubContext[i].last_mb_adaptive_frame_field_flag	= 0;	// Doesn't matter, will be initialized on first frame

	//
	// Perform soft reset
	//

	OSDEV_WriteLong( PP_SRS(N),			1 );			// Perform a soft reset
	for( j=0; j<H264_PP_RESET_TIME_LIMIT; j++ )
	{
	    if( (OSDEV_ReadLong(PP_ITS(N)) & PP_ITM__SRS_COMP) != 0 )
		break;

	    OSDEV_SleepMilliSeconds( 1 );
	}

	if( j == H264_PP_RESET_TIME_LIMIT )
	    OSDEV_Print( "H264ppOpen - Failed to soft reset PP %d.\n", N );

	OSDEV_WriteLong( PP_ITS(N),                     0xffffffff );           // Clear interrupt status

//

	OSDEV_WriteLong( PP_MAX_OPC_SIZE(N),            5 );                    // Setup the ST bus parameters
	OSDEV_WriteLong( PP_MAX_CHUNK_SIZE(N),          0 );
	OSDEV_WriteLong( PP_MAX_MESSAGE_SIZE(N),        3 );

//

	Status  = request_irq( H264_PP_INTERRUPT(N), H264ppInterruptHandler, 0, "H264 PP", (void *)((unsigned int)H264ppContext + i) );
	if( Status != 0 )
	{
	    OSDEV_Print( "H264ppOpen - Unable to request an IRQ for PP %d.\n", N );

	    OSDEV_DeInitializeSemaphore( &H264ppContext->PreProcessor );
	    OSDEV_DeInitializeSemaphore( &H264ppContext->ProcessedBufferListEntry );
	    OSDEV_DeInitializeSemaphore( &H264ppContext->ProcessedBuffer );

	    for( j=0; j<i; j++ )
		free_irq( H264_PP_INTERRUPT((H264ppContext->Index + j)), (void *)((unsigned int)H264ppContext+j) );

	    OpenMask    ^= (H264_PP_PER_INSTANCE_MASK<<H264ppContext->Index);

	    OSDEV_ReleaseSemaphore( &Lock );
	    OSDEV_OpenExit( OSDEV_Error );
	}
    }

//

    OSDEV_ReleaseSemaphore( &Lock );
    OSDEV_OpenExit( OSDEV_NoError );
}