void DMediaDriverNVMemory::Disconnect( DLocalDrive* aLocalDrive, TThreadMessage* aMsg )
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::Disconnect()");
	// Complete using the default implementation
	DMediaDriver::Disconnect(aLocalDrive, aMsg);
	__DEBUG_PRINT("<DMediaDriverNVMemory::Disconnect()");
	}
void DMediaDriverNVMemory::DoTransactionLaunchDfc()
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::DoTransactionLaunchDfc()");
	TInt request = iCurrentRequest->Id();
	TInt r(KErrNone);
	switch (request)
		{
		case DLocalDrive::ERead:
			r=Read();
		break;
		case DLocalDrive::EWrite:
			r=Write();
		break;
		case DLocalDrive::EFormat:
			r=Format();
		break;
		case DLocalDrive::EEnlarge:
		case DLocalDrive::EReduce:
		default:
			r=KErrNotSupported;
		break;
		}
	if( r != KErrNone )
		{
		// TODO some proper error handling here
		}
	__DEBUG_PRINT("<MediaDriverNVMemory::DoTransactionLaunchDfc %d",r);
	}
DECLARE_STANDARD_EXTENSION()
	{
	__DEBUG_PRINT("Registering NVMEM drive");
	TInt r=KErrNoMemory;

	DPrimaryMediaBase* pM=new DPrimaryMediaBase;

	TDynamicDfcQue* NVMemoryDfcQ;
	 
	r = Kern::DynamicDfcQCreate( NVMemoryDfcQ, KNVMemDfcThreadPriority, KNVMemDriveName );

	if( r == KErrNone )
		{
		pM->iDfcQ = NVMemoryDfcQ;
		}
	else
		{
		__DEBUG_PRINT("NVMEM DFCQ initialization failed");
		}

	if (pM)
		{
		r=LocDrv::RegisterMediaDevice(EFixedMedia1,NVMEM1_DRIVECOUNT,&NVMemDriveNumbers[0],pM,NVMEM1_NUMMEDIA,KNVMemDriveName);
		}

	pM->iMsgQ.Receive();

	__DEBUG_PRINT("Registering NVMEM drive - return %d",r);

	return r;
	}
TInt DMediaDriverNVMemory::Read()
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::Read() pos: %lx, size: %lx", iPos, iTotalLength);
	// Set our sector offset
	TUint32 transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
	TUint32 transactionLength = 0;
	TUint32 transactionDirection = NVMEM_TRANSACTION_READ;
	// Do we have an operation longer than our shared memory?
	if( iSplitted > 0 )
		{
		transactionLength = KNVMemTransferBufferSize;
		}
	else
		{
		// Do the whole operation in one go since we have enough room in our memory
		transactionLength = I64LOW(iTotalLength);
		// Read the "broken" tail sector
		if( iTail )
			{
			transactionLength += iTail;
			iAlignmentOverhead += iTail;
			}
		}
	// Read the "broken" head sector
	if( iHead > 0 )
		{
		transactionLength += iHead;
		iAlignmentOverhead += iHead;
		}

	// We should be ok to continue
	ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );
	__DEBUG_PRINT("<DMediaDriverNVMemory::Read()");
	return KErrNone;
	}
TInt DMediaDriverNVMemory::DoCreate(TInt /*aMediaId*/)
//
// Create the media driver.
//
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::DoCreate");
	TInt r = KErrNone; 
	// Inform our size
	Int64 size=GetNVMemSize()<<KDiskSectorShift;
	if( size<=0 )
		{
		Kern::Fault("DMediaDriverNVMemory zero size nv memory array", 0);
		}
	SetTotalSizeInBytes(size);
	// Some dfc initialization
	if( r==KErrNone )
		{
		iSessionEndDfc.SetDfcQ( this->iPrimaryMedia->iDfcQ );
		iTransactionLaunchDfc.SetDfcQ( this->iPrimaryMedia->iDfcQ );
		}
	// Create our piece of physically contiguous transfer buffer. 
	r = Epoc::AllocPhysicalRam( KNVMemTransferBufferSize, iTransferBufferPhys );
	if( r != KErrNone )
		{
		Kern::Fault("DMediaDriverNVMemory Allocate Ram %d",r);
		}

    DPlatChunkHw* bufChunk = NULL;

    // Create HW Memory Chunk
    r = DPlatChunkHw::New( bufChunk, iTransferBufferPhys, KNVMemTransferBufferSize, EMapAttrUserRw | EMapAttrFullyBlocking );

    if( r != KErrNone )
        {
        // Check Physical Memory
        if( iTransferBufferPhys )
			{
            // Free Physical Memory
            Epoc::FreePhysicalRam( iTransferBufferPhys, KNVMemTransferBufferSize );
			}
		Kern::Fault("DMediaDriverNVMemory error in creating transfer buffer", r);
        }

    // Set Main Buffer Pointer
    iTransferBufferLin = reinterpret_cast<TUint8*>(bufChunk->LinearAddress());

  	// Inform "hardware" about the shared memory
  	WriteReg( KHwNVMemoryDevice, R_NVMEM_SHARED_MEMORY_BASE, iTransferBufferPhys );
  	WriteReg( KHwNVMemoryDevice, R_NVMEM_SHARED_MEMORY_SIZE, KNVMemTransferBufferSize );
  	WriteReg( KHwNVMemoryDevice, R_NVMEM_ENABLE, 1 );

	// Set up interrupt service
  	r = Interrupt::Bind( EIntNVMemoryDevice, Isr, this );
  	Interrupt::Enable( EIntNVMemoryDevice );


	__DEBUG_PRINT("<DMediaDriverNVMemory::DoCreate %d", r);
	return(r);
	}
void DPhysicalDeviceMediaNVMemory::GetCaps(TDes8& /*aDes*/) const
//
// Return the media drivers capabilities.
//
	{
	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::GetCaps()");
	}
TInt DMediaDriverStaticRD::ContinueTransaction( TUint32 aTransactionSectorOffset, TUint32 aTransactionSectorCount, TUint32 aTransactionDirection )
	{
	__DEBUG_PRINT("DMediaDriverStaticRD::ContinueTransaction() sectoroffset: %d, sectorcount: %d, direction: %d", aTransactionSectorOffset, aTransactionSectorCount, aTransactionDirection);
	if( aTransactionDirection != NVMEM_TRANSACTION_UNDEFINED )
		{
	  	//WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_OFFSET, aTransactionSectorOffset );
	  	//WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_SIZE, aTransactionSectorCount );
	  	//WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_DIRECTION, aTransactionDirection );
	  	//WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_EXECUTE, aTransactionDirection );
		if ( aTransactionDirection == NVMEM_TRANSACTION_WRITE )
		{
			memcpy( (TAny *)(iDiscBufferLin+(aTransactionSectorOffset<<9)), iTransferBufferLin, aTransactionSectorCount*512 );
		}
		else if ( aTransactionDirection == NVMEM_TRANSACTION_READ )
		{
			memcpy( iTransferBufferLin, (TAny *)(iDiscBufferLin+(aTransactionSectorOffset<<9)), aTransactionSectorCount*512 );
		}
		iLatestTransferSectorCount = aTransactionSectorCount;
		Isr(this); // terrible hack, we've yransferred all the sectors and now we pretend to generate an interrupt
		}
	else
		{
		Kern::Fault("DMediaDriverStaticRD::ContinueTransaction: Undefined transaction!", 0);
		}
	return KErrNone;
	}
TInt DPhysicalDeviceMediaNVMemory::Install()
//
// Install the Internal NVMem PDD.
//
	{
	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Install()");
	return SetName(&KNVMemPddName);
	}
Ejemplo n.º 9
0
int sthread_cond_wait(sthread_cond_t *cond, sthread_mutex_t *mutex)
{
	if(cond->cond) {
		__DEBUG_PRINT(("tid %d cond 1 \n", __selftid));
		setup_sync();
		wait_to_enter();
		__DEBUG_PRINT(("tid %d cond 2 \n", __selftid));
//		if(__threadpool[])
		v_next_mutex(mutex->mutex);
		__threadpool[__selftid].mutex = NULL;
		__mvspace_commit();
		__threadpool[__selftid].state = E_STOPPED;
		__threadpool[__selftid].cond = cond->cond;
		
		__DEBUG_PRINT(("tid %d cond 3 \n", __selftid));
		v_next_and_wait();
		__DEBUG_PRINT(("tid %d cond 4 \n", __selftid));

		__mvspace_pull();

		__DEBUG_PRINT(("tid %d cond 5 \n", __selftid));
		wait_sem(cond->cond->locks, __selftid);
		__threadpool[__selftid].mutex = mutex->mutex;
		__DEBUG_PRINT(("tid %d cond 5.5 \n", __selftid));
		wait_sem(mutex->mutex->locks, __selftid);
		__threadpool[__selftid].state = E_NORMAL;

		__DEBUG_PRINT(("tid %d cond 6 \n", __selftid));
		leave_sync();
		return 0;
	}
	return -1;
}
TInt DPhysicalDeviceMediaNVMemory::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
	{
	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Validate()");
	if (!Kern::QueryVersionSupported(iVersion,aVer))
		return KErrNotSupported;
	if (aDeviceType!=EFixedMedia1)
		return KErrNotSupported;
	return KErrNone;
	}
DPhysicalDeviceMediaNVMemory::DPhysicalDeviceMediaNVMemory()
//
// Constructor
//
	{
	__DEBUG_PRINT(">DPhysicalDeviceMediaNVMemory::DPhysicalDeviceMediaNVMemory");
	iUnitsMask=0x1;
	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
	}
TInt DPhysicalDeviceMediaNVMemory::Info(TInt aFunction, TAny*)
//
// Return the priority of this media driver
//
	{
	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Info()");
	if (aFunction==EPriority)
		return KMediaDriverPriorityNormal;
	return KErrNotSupported;
	}
DMediaDriverNVMemory::DMediaDriverNVMemory(TInt aMediaId)
//
// Constructor.
//
	:	DMediaDriver(aMediaId),
		iSessionEndDfc(DMediaDriverNVMemory::SessionEndDfc, this, 1),
		iTransferBufferPhys(0),
		iTransactionLaunchDfc(DMediaDriverNVMemory::TransactionLaunchDfc, this, KMaxDfcPriority)
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::DMediaDriverNVMemory()");
	}
TInt DMediaDriverNVMemory::PartitionInfo(TPartitionInfo& anInfo)
//
// Return partition information on the media.
//
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::PartitionInfo()");
	anInfo.iPartitionCount=1;
	anInfo.iEntry[0].iPartitionBaseAddr=0;
	anInfo.iEntry[0].iPartitionLen=anInfo.iMediaSizeInBytes=TotalSizeInBytes();
	anInfo.iEntry[0].iPartitionType=KPartitionTypeFAT16;
	return KErrCompletion;
	}
Ejemplo n.º 15
0
int sthread_cond_signal(sthread_cond_t *cond)
{
	if(cond->cond)
	{
		int i;
		__DEBUG_PRINT(("tid %d signal 1 \n", __selftid));
		setup_sync();
		__DEBUG_PRINT(("tid %d signal 2 \n", __selftid));
		wait_to_enter();
		__DEBUG_PRINT(("tid %d signal 3 \n", __selftid));
		__mvspace_commit();
		v_next_and_wait();
		__DEBUG_PRINT(("tid %d signal 3 \n", __selftid));
		__mvspace_pull();

		for(i=0;i<MAXTHREADS;i++)
			post_sem(cond->cond->locks, i);
		__DEBUG_PRINT(("tid %d signal 4 \n", __selftid));

		leave_sync();
		__DEBUG_PRINT(("tid %d signal 5 \n", __selftid));
			
		return 0;
	}
	return -1;
}
Ejemplo n.º 16
0
DDisplayLdd::~DDisplayLdd()
	{
	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
     // cancel outstanding requests and destroy the queue of TClientRequest objects
    for(TInt k = 0; k < KPendingReqArraySize ; k++)
    	{
		for(TInt i = 0; i < KMaxQueuedRequests; i++)
			{
			//Method IsReady() returns true if the client’s request SetStatus method has been called but the 
			//coresponding QueueRequestComplete method hasn't.			
			if(iPendingReq[k][i].iTClientReq)        
				{
				if(iPendingReq[k][i].iTClientReq->IsReady() )
					{
					CompleteRequest(iPendingReq[k][i].iOwningThread,iPendingReq[k][i].iTClientReq,KErrCancel);        	
					}     		
				}			
			Kern::DestroyClientRequest(iClientRequest[k][i]);
			}
		}
    
    //Close User Buffer chunks not yet destroyed.
	for(TInt i = 0; i < KDisplayUBMax; i++)
		{
		if(iUserBuffer[i].iChunk != 0)
			{
    		Kern::ChunkClose(iUserBuffer[i].iChunk);
    		iUserBuffer[i].iChunk= NULL;
			}
		}
    	
    Kern::SafeClose((DObject*&)iClient, NULL);  
    
    
    if (iClientRequestMutex != NULL)
         {
         iClientRequestMutex->Close(NULL);
         }
    
    __ASSERT_DEBUG(iThreadOpenCount == 0,Kern::Fault(KDisplayLddPanic,__LINE__));
    __ASSERT_DEBUG(iAsyncReqCount   == 0,Kern::Fault(KDisplayLddPanic,__LINE__));  
    	
    // Clear the 'units open mask' in the LDD factory.
	if (iUnit>=0)
		((DDisplayLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);	 	

#ifdef _DEBUG
	// Close the UDEB user mode chunk, if it exists
	if (iChunk)
		Kern::ChunkClose(iChunk);
#endif // _DEBUG
	}
TInt DMediaDriverNVMemory::Format()
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::Format() pos: 0x%lx, size: 0x%lx", iPos, iTotalLength);
	memset( iTransferBufferLin, 0x00, KNVMemTransferBufferSize );
	// Stop the nonsense here. Write operations should be used for partial sector data removal operations
	if( iHead > 0 || iTail > 0 )
		{
		Kern::Fault("DMediaDriverNVMemory::Format: alignment violation!", 0);
		}
	Write();
//	DoTransaction( m, NVMEM_TRANSACTION_WRITE );
	return KErrNone;
	}
void DMediaDriverNVMemory::CompleteRequest(TInt aReason)
//
// completes the request which is being currently processed
//
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::CompleteRequest() reason: %d", aReason);
	TLocDrvRequest* pR=iCurrentRequest;
	if (pR)
		{
		iCurrentRequest=NULL;
		DMediaDriver::Complete(*pR,aReason);
		}
	}
void DMediaDriverNVMemory::Isr(TAny* aPtr)
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::Isr");

    DMediaDriverNVMemory* nvMem = reinterpret_cast<DMediaDriverNVMemory*>(aPtr);

	// Save the amount of transferred sectors. This clears the interrupt from HW as well
	nvMem->iLatestTransferSectorCount = ReadReg( KHwNVMemoryDevice, R_NVMEM_STATUS );

	// Clear from framework
	Interrupt::Clear( EIntNVMemoryDevice );

	nvMem->iSessionEndDfc.Add();
	}
TInt DMediaDriverNVMemory::ContinueTransaction( TUint32 aTransactionSectorOffset, TUint32 aTransactionSectorCount, TUint32 aTransactionDirection )
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::ContinueTransaction() sectoroffset: %d, sectorcount: %d, direction: %d", aTransactionSectorOffset, aTransactionSectorCount, aTransactionDirection);
	if( aTransactionDirection != NVMEM_TRANSACTION_UNDEFINED )
		{
	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_OFFSET, aTransactionSectorOffset );
	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_SIZE, aTransactionSectorCount );
	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_DIRECTION, aTransactionDirection );
	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_EXECUTE, aTransactionDirection );
		}
	else
		{
		Kern::Fault("DMediaDriverNVMemory::ContinueTransaction: Undefined transaction!", 0);
		}
	return KErrNone;
	}
Ejemplo n.º 21
0
/************************************************************************************
 *            DDisplayLdd LDD class implementation
 ************************************************************************************/
DDisplayLdd::DDisplayLdd()		
	{	
	__DEBUG_PRINT("DDisplayLdd::DDisplayLdd()\n");
	// store the pointer to the current thread for request completion
  	iClient = &Kern::CurrentThread();
    __NK_ASSERT_DEBUG(iClient);
	// Open a reference on the client thread so it's control block can't disappear until the driver has finished with it.
    iClient->Open();
    iCurrentPostCount   = 0;
    iRequestedPostCount = 0;
    iCompositionBuffIdx = 0;
    iUnit				= -1;
    iThreadOpenCount    = 0;
    iAsyncReqCount		= 0;
    iClientRequestMutex = 0;	
	}
TInt DMediaDriverNVMemory::Caps(TLocDrvRequest& m)
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::Caps()");
	TLocalDriveCapsV6& caps=*(TLocalDriveCapsV6*)m.RemoteDes();
	caps.iType=EMediaHardDisk;
	caps.iConnectionBusType=EConnectionBusInternal;
	caps.iDriveAtt=KDriveAttLocal|KDriveAttInternal;
	caps.iMediaAtt=KMediaAttFormattable;
	caps.iFileSystemId=KDriveFileSysFAT;
	caps.iPartitionType=KPartitionTypeFAT16;
	caps.iSize=m.Drive()->iPartitionLen;
	caps.iHiddenSectors=0;
	caps.iEraseBlockSize = KNVMemTransferBufferSize; 
	caps.iBlockSize=KDiskSectorSize;
	caps.iMaxBytesPerFormat = KNVMemTransferBufferSize;

	return KErrCompletion;									
	}
Ejemplo n.º 23
0
void sthread_shared(void *addr, size_t size)
{

		__setup_sync();
//		__DEBUG_PRINT(("tid %d shared 0 \n", __selftid));
//		__DEBUG_PRINT(("tid %d shared 0.1 barrier %d \n", __selftid, *(__global_barrier1.val)));
		wait_to_enter();	
//		__DEBUG_PRINT(("tid %d shared 0.2 barrier %d \n", __selftid, *(__global_barrier1.val)));
//		__DEBUG_PRINT(("tid %d shared 1 \n", __selftid));
		//		if(__selftid == 1) {
	//	__acquire_lock(__sharedlist->lock);
		if(!__in_sharedlist(addr)) {
		__DEBUG_PRINT(("tid %d shared 1.05 barrier %d \n", __selftid, *(__global_barrier1.val)));
				void *p = mvshared_malloc(size);
				void *p2 = mvshared_malloc(size);
				int __vamsize = __sharedlist->__vamsize;
				(__sharedlist->__vamap)[__vamsize].addr = addr;
//		__DEBUG_PRINT(("tid %d shared 1.1 barrier %d \n", __selftid, *(__global_barrier1.val)));
				(__sharedlist->__vamap)[__vamsize].addr = addr;
//		__DEBUG_PRINT(("tid %d shared 1.15 barrier %d \n", __selftid, *(__global_barrier1.val)));
				(__sharedlist->__vamap)[__vamsize].shared = p;
//		__DEBUG_PRINT(("tid %d shared 1.2 barrier %d \n", __selftid, *(__global_barrier1.val)));
				(__sharedlist->__vamap)[__vamsize].backup = p2;
//		__DEBUG_PRINT(("tid %d shared 1.3 barrier %d \n", __selftid, *(__global_barrier1.val)));
				(__sharedlist->__vamap)[__vamsize].size = size;
//		__DEBUG_PRINT(("tid %d shared 1.4 p2 %ld p %ld barrierpoint %ld \n", __selftid, p2, p, (__global_barrier1.val)));
//			memcpy(p2, addr, size);
//				memcpy(p, addr, size);
		__mem_copy(p2, addr, size);
		__mem_copy(p, addr, size);

//		__DEBUG_PRINT(("tid %d shared 1.5 barrier %d \n", __selftid, *(__global_barrier1.val)));
				(__sharedlist->__vamsize)++;
//		__DEBUG_PRINT(("tid %d shared 1.6 barrier %d \n", __selftid, *(__global_barrier1.val)));
		}
	//	__release_lock(__sharedlist->lock);
		v_next_and_wait();
//		__DEBUG_PRINT(("tid %d shared 2 \n", __selftid));
		leave_sync();
//		__DEBUG_PRINT(("tid %d shared 3 \n", __selftid));
		//		}
}
TInt DPhysicalDeviceMediaNVMemory::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
//
// Create an Internal Ram media driver.
//
	{
	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Create()");
	if (!Kern::QueryVersionSupported(iVersion,aVer))
		return KErrNotSupported;
	TInt r=KErrNoMemory;
	DMediaDriverNVMemory* pD=new DMediaDriverNVMemory(aMediaId);
	aChannel=pD;
	if (pD)
		{
		r=pD->DoCreate(aMediaId);
		}
	if( r==KErrNone )
		{
		pD->OpenMediaDriverComplete(KErrNone);
		}

	return r;
	}
Ejemplo n.º 25
0
int sthread_barrier_wait(sthread_barrier_t *barrier)
{
	if(barrier->barrier) {
		setup_sync();
		//setup_barrier_sync(barrier->barrier);
		__DEBUG_PRINT(("tid %d barrier1\n", __selftid));
		wait_to_enter();
		__mvspace_commit();
		__threadpool[__selftid].state = E_STOPPED;
		__threadpool[__selftid].barrier = barrier->barrier;
		__DEBUG_PRINT(("tid %d barrier2\n", __selftid));
		v_next_and_wait();
		setup_barrier_sync(barrier->barrier);
		__sync_fetch_and_add(&(barrier->barrier->num), 1);
		__DEBUG_PRINT(("tid %d barrier3\n", __selftid));
		__mvspace_pull();

		if(barrier->barrier->total == barrier->barrier->num) {
			int i;
			for(i=0;i<MAXTHREADS;i++) {
				if(__threadpool[i].barrier == barrier->barrier)
					__threadpool[i].state = E_NORMAL;
			}
		__DEBUG_PRINT(("tid %d barrier3.5\n", __selftid));
			barrier->barrier->inited = 0;
			post_sem(barrier->barrier->sema, 0);
		}
		__DEBUG_PRINT(("tid %d barrier4\n", __selftid));
		wait_sem(barrier->barrier->sema, 0);
		__DEBUG_PRINT(("tid %d barrier5\n", __selftid));
		post_sem(barrier->barrier->sema, 0);
		__threadpool[__selftid].barrier = NULL;
		__threadpool[__selftid].state = E_NORMAL;

		leave_sync();

		return 0;
	}
	return -1;
}
Ejemplo n.º 26
0
/**
	LDD second stage constructor
*/
TInt DDisplayLdd::DoCreate(TInt aUnit, const TDesC8* /* anInfo*/, const TVersion& aVer)
	{ 
	
	__DEBUG_PRINT("DDisplayLdd::DoCreate()\n"); 

	if(    !Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,      __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
		|| !Kern::CurrentThreadHasCapability(ECapabilityReadDeviceData, __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
		|| !Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
		|| !Kern::CurrentThreadHasCapability(ECapabilityProtServ,       __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") ) )
		{
		return KErrPermissionDenied;
		}
		  
	// Check that the display driver version specified by the client is compatible.
	if (!Kern::QueryVersionSupported(RDisplayChannel::VersionRequired(),aVer))
		{
		return(KErrNotSupported);		
		}
				
	// Check that a channel hasn't already been opened on this unit.
	TInt r=((DDisplayLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
	if (r!=KErrNone)
		return r;
	iUnit=aUnit;

 	Pdd()->iLdd	= this;
 	
 	r		= Pdd()->CreateChannelSetup(aUnit); 	
 	if ( r!= KErrNone)
 		{
 		return r; 		
 		}
 
     // set up user buffer nodes
    for (TInt node = 0; node < KDisplayUBMax; node++)
    	{
        iUserBuffer[node].iType 	= EBufferTypeUser;
        iUserBuffer[node].iBufferId = (node + 1);
        iUserBuffer[node].iFree 	= ETrue;
        iUserBuffer[node].iState 	= EBufferFree;
        iUserBuffer[node].iAddress  = 0;
        iUserBuffer[node].iSize  	= 0;
        iUserBuffer[node].iHandle  	= 0;
        iUserBuffer[node].iChunk  	= 0;
        iUserBuffer[node].iOffset 	= 0;
        iUserBuffer[node].iPendingRequest = 0;
    	}

    //Initialise pending queue for asynchronous requests and queue of TClientRequests
    for(TInt k = 0; k < KPendingReqArraySize; k++) 
    	{
    	
    	iPendingIndex[k]=0;
    	
		for(TInt i = 0; i < KMaxQueuedRequests; i++)
			{
			iPendingReq[k][i].iTClientReq   = 0;
			iPendingReq[k][i].iOwningThread = 0;
			
			
			r = Kern::CreateClientRequest(iClientRequest[k][i]);
			if (r != KErrNone)
				{
				return r;      	
				}
			}	
    	} 
    
    r = Kern::MutexCreate(iClientRequestMutex, KClientRequestMutex, KMutexOrder);	
	if (r != KErrNone)
		{
		return r;
		}	
    
          
    Pdd()->SetGceMode();	
	SetDfcQ(Pdd()->DfcQ(aUnit));	   
    iMsgQ.Receive();
    
    return KErrNone;		
}
DECLARE_EXTENSION_PDD()
	{
	__DEBUG_PRINT(">MediaDriverNVMemory create device");
	return new DPhysicalDeviceMediaNVMemory;
	}
TUint32  DMediaDriverNVMemory::GetNVMemSize( void )
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::GetNVMemSize()");
	TUint32 sizeInSectors = ReadReg( KHwNVMemoryDevice, R_NVMEM_NV_MEMORY_SIZE );
	return sizeInSectors; 
	}
void DMediaDriverNVMemory::DoSessionEndDfc()
	{
	__DEBUG_PRINT(">DMediaDriverNVMemory::DoSessionEndDfc()");
	TInt r = KErrNone;
	// Check that we have a request in process
	if( iCurrentRequest )
		{
		// Transaction variables
		TUint32 transactionSectorOffset(0);
		TUint32 transactionLength(0);
		TUint32 transactionDirection( NVMEM_TRANSACTION_UNDEFINED );
		// How much did we actually transfer? 
		TUint32 latestTransferSize = (iLatestTransferSectorCount * KDiskSectorSize);
		__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() latestTransferSize: %d", latestTransferSize );
		// Subtract alignment overhead
		latestTransferSize = latestTransferSize - iAlignmentOverhead;
		// For decision whether the buffer is ready for operation already
		TBool bufferReady(EFalse);
		// For decision whether we have finished the latest request
		TBool sessionComplete(EFalse);

		// Was there a read-modify-write (RWM) for which we need to do some buffer manipulation before proceeding?
		// Note that in case of format we triggered to alignment violation in earlier method already and can not enter to following 
		// condition when there is a format operation going on
		if( iReadModifyWrite )
			{
			bufferReady = ETrue;
			iReadModifyWrite = EFalse;
			// Was it a splitted operation for which we only need to take care of the broken head sector.
			if( iSplitted > 0 )
				{
				// We have a sector here here filled with data from mass memory. Modify with client data.
				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() readremote splitted: %d head: %d", latestTransferSize, iHead );
				TPtr8 targetDescriptor(&iTransferBufferLin[iHead], KNVMemTransferBufferSize - iHead);
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
				r = iCurrentRequest->ReadRemote(&targetDescriptor,iSplitLength); 
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end
				}
			// Else we need to take care of both head and tail
			else
				{
				// We have a piece of data read from mass memory. Modify with client data.
				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() readremote: %d head: %d", I64LOW(iTotalLength - iProsessedLength), iHead );
				TPtr8 targetDescriptor(&iTransferBufferLin[iHead], I64LOW(iTotalLength - iProsessedLength));
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
				r = iCurrentRequest->ReadRemote(&targetDescriptor,iSplitLength);
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end

//				latestTransferSize -= (KDiskSectorSize - iTail);
				iTail = 0;
				}
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
			iSplitLength+= latestTransferSize; // Update split transfer position count
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end
			}
		else
			{
			// Overhead is processed when we enter here
			iAlignmentOverhead = 0;
			// Update position
			iPos += latestTransferSize;
			// Save the information on how many bytes we transferred already
			iProsessedLength += latestTransferSize; 
			// Update the splitted information. We don't take head into account here anymore since it is already taken care of
			iSplitted = (iTotalLength - iProsessedLength + iTail) / KNVMemTransferBufferSize;
			// Check if we have done already
			if( iProsessedLength >= iTotalLength )
				{
				// If this was the final transfer for this request let's take tail into account as well (if not taken already)
				// iProsessedLength -= iTail;
				// latestTransferSize -= iTail;
				if( iProsessedLength > iTotalLength )
					{
					Kern::Fault("DMediaDriverNVMemory: Illegal transfer operation!", 0);
					}
				sessionComplete = ETrue;
				}
			}

		TInt request = iCurrentRequest->Id();

		// Set our sector offset
		transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
		
		if( bufferReady )
			{
			// Write as much as we read in RMW operation
			transactionLength = (iLatestTransferSectorCount * KDiskSectorSize);
			}
		else
			{
			// Do we have an operation longer than our shared memory?
			if( iSplitted > 0 )
				{
				transactionLength = KNVMemTransferBufferSize;
				}
			else
				{
				// Do the whole operation in one go since we have enough room in our memory
				transactionLength = I64LOW(iTotalLength - iProsessedLength);
				// Read the "broken" tail sector
				if( iTail > 0 && request == DLocalDrive::EWrite )
					{
					iReadModifyWrite = ETrue;
					// Read the "broken" tail sector
					transactionLength += iTail;
	   				iAlignmentOverhead = iTail;
	   				}
				}
			}
		
		// Was there a need to read-modify before writing
		if( iReadModifyWrite )
			{
			transactionDirection = NVMEM_TRANSACTION_READ;
			}
		else
			{
			if( request == DLocalDrive::ERead )
				{
				transactionDirection = NVMEM_TRANSACTION_READ;
				// Write to client
				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() WriteRemote: %d head: %d", latestTransferSize, iHead );
				TPtrC8 sourceDescriptor(&iTransferBufferLin[iHead], latestTransferSize);

//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
				r = iCurrentRequest->WriteRemote( &sourceDescriptor, iSplitLength ); // Allow for "splitted" operations
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end

				}
			// Head is processed
			iHead = 0;
			if( request == DLocalDrive::EWrite && !sessionComplete )
				{
				transactionDirection = NVMEM_TRANSACTION_WRITE;
				if( bufferReady )
					{
					// Actually no need for any actions here
					}
				else
					{
					// Prepare a buffer for transfer
					__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() ReadRemote: %d head: %d", latestTransferSize, iHead );
					TPtr8 targetDescriptor(iTransferBufferLin, transactionLength);
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
					r = iCurrentRequest->ReadRemote(&targetDescriptor,iSplitLength); // allow for "splitted" operations
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end
					}
				}

//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
			iSplitLength+= latestTransferSize; // Update split transfer position count
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end
			
			if( request == DLocalDrive::EFormat )
				{
				transactionDirection = NVMEM_TRANSACTION_WRITE;
				}
			}
		if( sessionComplete )
			{
			CompleteRequest( r );
			}
		else
			{
			ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );
			}
		}
	else
		{
		// Let's just flow through for now
		}

	__DEBUG_PRINT("<DMediaDriverNVMemory::DoSessionEndDfc()" );
	}
TInt DMediaDriverNVMemory::Write()
	{
	__DEBUG_PRINT("DMediaDriverNVMemory::Write() pos: 0x%lx, size: 0x%lx", iPos, iTotalLength);
	TInt r = KErrNone;
	// Set our sector offset
	TUint32 transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
	TUint32 transactionLength = 0;
	TUint32 transactionDirection = NVMEM_TRANSACTION_WRITE;
	// Do we have an operation longer than our shared memory?
	if( iSplitted > 0 )
		{
		transactionLength = KNVMemTransferBufferSize;
		}
	else
		{
		// Do the whole operation in one go since we have enough room in our memory
		transactionLength = I64LOW(iTotalLength);
		if( iTail )
			{
			iReadModifyWrite = ETrue;
			// Read the "broken" tail sector
			transactionLength += iTail;
			iAlignmentOverhead += iTail;
			}
		}
	// Is there a need to read modify write the "broken" head sector of the operation
	if( iHead > 0 )
		{
		iReadModifyWrite = ETrue;
		// If splitted operation we only need the broken sector
		if( iSplitted > 0 )
			{
			transactionLength = KDiskSectorSize;
			iAlignmentOverhead += iHead;
			}
		else
			{
			// Read the "broken" head sector in addition to everything else
			transactionLength += iHead;
			iAlignmentOverhead += iHead;
			}
		}
	
	// Was there a need to read-modify before writing
	if( iReadModifyWrite )
		{
		transactionDirection = NVMEM_TRANSACTION_READ;
		}
	else
		{
		// Handle format here
		if( iCurrentRequest->Id() == DLocalDrive::EFormat )
			{
			// Not much handling just flow through since we have filled the shared memory with zeroes already
			}
		else
			{
			// Read from client
			TPtr8 targetDescriptor(iTransferBufferLin, transactionLength);
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - start
			r = iCurrentRequest->ReadRemote(&targetDescriptor,iSplitLength);
			iSplitLength+= transactionLength;
//  SF BUG 3759 - NVM drives do not support operations larger than 262144 bytes correctly - end
			}
		}
	
	// We should be ok to continue
	ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );

	return r;
	}