kernel/eka/drivers/display/display.cpp
changeset 31 56f325a607ea
parent 0 a41df078684a
--- a/kernel/eka/drivers/display/display.cpp	Mon Dec 21 16:14:42 2009 +0000
+++ b/kernel/eka/drivers/display/display.cpp	Wed Dec 23 11:43:31 2009 +0000
@@ -11,8 +11,7 @@
 // Contributors:
 //
 // Description:
-// e32\drivers\display\display.cpp  
-// LDD for a Display driver with GCE support
+// os\kernelhwsrv\kernel\eka\drivers\display\display.cpp  
 // LDD for a Display driver with GCE support
 // 
 //
@@ -28,8 +27,11 @@
 #include <kernel/kern_priv.h>
 
 
+const TUint8  KMutexOrder             = 0x3f;
 
-static const char KDisplayLddPanic[]="DISPLAY/GCE LDD";
+static const char KDisplayLddPanic[]  ="DISPLAY/GCE LDD";
+
+_LIT(KClientRequestMutex, "ClientRequestMutex");
 
 
 /************************************************************************************
@@ -47,21 +49,32 @@
     iRequestedPostCount = 0;
     iCompositionBuffIdx = 0;
     iUnit				= -1;
-    iThreadOpenCount    = 0;	
+    iThreadOpenCount    = 0;
+    iAsyncReqCount		= 0;
+    iClientRequestMutex = 0;	
 	}
 
 
 DDisplayLdd::~DDisplayLdd()
 	{
 	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
-     // cancel outstanding requests
+     // cancel outstanding requests and destroy the queue of TClientRequest objects
     for(TInt k = 0; k < KPendingReqArraySize ; k++)
     	{
-        if(iPendingReq[k].iStatus)
-        	{
-     		CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);        	
-        	}
-    	}
+		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++)
@@ -75,11 +88,24 @@
     	
     Kern::SafeClose((DObject*&)iClient, NULL);  
     
-    __ASSERT_DEBUG(iThreadOpenCount==0,Kern::Fault(KDisplayLddPanic,__LINE__)); 
+    
+    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
 	}
  
 
@@ -92,9 +118,9 @@
 	__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)") ) )
+		|| !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;
 		}
@@ -108,10 +134,9 @@
 	// 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); 	
@@ -135,12 +160,32 @@
         iUserBuffer[node].iPendingRequest = 0;
     	}
 
-    //Initialise pending queue for asynchronous requests
-    for(int k = 0; k < KPendingReqArraySize; k++) 
+    //Initialise pending queue for asynchronous requests and queue of TClientRequests
+    for(TInt k = 0; k < KPendingReqArraySize; k++) 
     	{
-      	iPendingReq[k].iStatus = 0;
-      	iPendingReq[k].iOwningThread = 0;
-    	}
+    	
+    	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));	   
@@ -151,11 +196,337 @@
 
 
 /**
- * All driver's client requests (synchronous and asynchronous) are sent as
- * kernel messages by generic kernel to logical channel. This function
- * catches messages sent by the generic kernel
- *
- * @param aMsg KErnel side thread messaging
+Override DLogicalChannel::SendMsg to process a client message before and after sending the message 
+to the DFC thread for processing by HandleMsg().
+ 
+This function is called in the context of the client thread.
+
+The function is used to pin client data in the context of the client thread, so that data can be safely
+accessed from kernel threads without the possibility of taking page faults.
+ 
+@param aMsg  The message to process.
+             The iValue member of this distinguishes the message type:
+			 iValue==ECloseMsg, channel close message
+			 iValue==KMaxTInt, a 'DoCancel' message
+			 iValue>=0, a 'DoControl' message with function number equal to iValue
+			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
+  
+ @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
+        codes.
+ 
+ */ 
+
+TInt DDisplayLdd::SendMsg(TMessageBase* aMsg)
+	{
+	TThreadMessage& m=*(TThreadMessage*)aMsg;
+    TInt id = m.iValue;
+	
+	TInt r = KErrNone;	
+	 // close msg or cancel
+	if (id == (TInt)ECloseMsg || id == KMaxTInt)
+		{
+		r = DLogicalChannel::SendMsg(aMsg);
+		}
+	//asynchronous request
+	else if (id < 0)
+		{
+		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+		r = SendRequest(aMsg);
+		if (r != KErrNone)
+			Kern::RequestComplete(pS,r);
+		}
+	 // synchronous request
+	else{
+		r = SendControl(aMsg);
+		}
+	
+	return r;
+	}
+
+
+/**
+Validate, pre-process, send and post-process data for an asynchronous client request, so that data can be safely
+accessed from kernel threads without the possibility of taking page faults. 
+
+This function is called in the context of the client thread.
+ 
+@param aMsg  The message to process.
+             The iValue member of this distinguishes the message type:
+			 iValue==ECloseMsg, channel close message
+			 iValue==KMaxTInt, a 'DoCancel' message
+			 iValue>=0, a 'DoControl' message with function number equal to iValue
+			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
+ 
+ @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
+        codes.
+ */ 
+TInt DDisplayLdd::SendRequest(TMessageBase* aMsg)
+	{
+	TThreadMessage& m	=*(TThreadMessage*)aMsg;
+    TInt aReqNumber 	= ~m.iValue;
+	TRequestStatus* pS	=(TRequestStatus*)m.Ptr0();
+	
+	#ifdef _GCE_DISPLAY_DEBUG
+	DThread* client 	= m.Client();
+	#endif		
+			
+	TInt r 				= KErrNotSupported;
+	TInt pendingIndex;
+
+	/*Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
+	Using thread local copies is possible even for asynchronous requests, since the values to be returned are known 
+	when processing the request( inside DoRequest ) and not at a later stage.*/
+	
+	TInt kernelCompBuffIdx;
+	TInt kernelpack[2];	
+	RDisplayChannel::TPostCount  kernelCount;
+	
+	
+	//In asynchronous requests m.Ptr0 is used for the TRequestStatus object.
+	TAny* userConfigData1 = m.Ptr1();
+	TAny* userConfigData2 = m.Ptr2();
+	
+	/*
+	If the client request needs to pass some data to the DFC thread then we copy these to a thread local
+	copy(created in the thread supervisor stack) and then update the message to point to that local copy. 
+	If the client will have to read a value updated in the DFC thread, then the message should just be 
+	updated and point to the local copy. After the request has completed the updated data will be copied
+	from the local copy to the client, in the context of the client thread. 
+	*/
+    
+    switch (aReqNumber)
+		{
+	    case RDisplayChannel::EReqGetCompositionBuffer:	//Client should read data updated in the DFC thread.
+				m.iArg[1] = &kernelCompBuffIdx;				
+				break;
+
+        case RDisplayChannel::EReqPostUserBuffer:    	//Both the client and DFC thread need to read data.
+				umemget32(&kernelpack, userConfigData1, (sizeof(TInt)*2) );
+				m.iArg[1] = &kernelpack;
+				m.iArg[2] = &kernelCount;
+				break;		
+		
+		case RDisplayChannel::EReqWaitForPost:			//Client data should be passed to the DFC thread.	
+				umemget32(&kernelCount, userConfigData1, sizeof(RDisplayChannel::TPostCount) );
+				m.iArg[1] = &kernelCount;							
+				break;
+		default:
+				return KErrNotSupported; 
+		
+		}
+		
+	/* 		
+	The TClientRequest objects associated with each asynchronous request need to be accessed by both the client and DFC
+	threads. To resolve the potential synchronization problem we maintain two seperate pointers(iClientRequest and 
+	iPendingReq.iClientReq )to the same TClientRequest object. iClientRequestMutex is used to synchronise access to 
+	iClientRequest from different client threads. The first client thread that acquires the mutex will set the status
+	of an available TClientRequest object and send the message(call SendMsg). Consequently method DoRequest is queued for 
+	execution by the DFC thread. DoRequest initialy saves iClientRequest to iPendingReq.iClientReq and queues the request. 
+	Only then, the mutex is signaled. Another client thread trying to access iClientRequest will block in the mutex until
+	DoRequest has updated iPendingReq.iClientReq. Even more the DFC thread only accesses iClientRequest in DoRequest and 
+	then iPendingReq.iClientReq is only used, so synchronizing access to iPendingReq.iClientReq is handled by the DFC queue.
+	*/
+	
+	// Need to be in critical section whilst holding a DMutex
+	NKern::ThreadEnterCS();
+	
+	Kern::MutexWait(*iClientRequestMutex);	
+	//Save the TRequestStatus in any available TClientRequest object for that asynchronous request.
+	
+	for( TInt k=0; k< KMaxQueuedRequests; k++) 
+		{
+		//setStatus will return KErrInUse if a previous client request hasn't completed yet.
+		r = iClientRequest[aReqNumber][k]->SetStatus(pS);
+		if( r == KErrNone)
+			{
+			pendingIndex = k;
+			//The current available index for this pending request will be passed as 
+			//another message argument to the DFC thread.
+			m.iArg[3] =  (TAny*) pendingIndex; 
+			break;
+			}		 			
+		}
+					 						
+	if (r == KErrNone)
+		{
+		r = DLogicalChannel::SendMsg(aMsg);
+		}
+	else
+		{
+		__DEBUG_PRINT3("Client %08x trying to issue asynchronous request %d", client, aReqNumber);
+		//Fail if there aren't any available TClientRequest object
+		__ASSERT_DEBUG(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));				
+		}
+	
+	Kern::MutexSignal(*iClientRequestMutex);
+
+    NKern::ThreadLeaveCS();
+    
+    //Copy config data from local copies to client, in context of client thread
+    switch (aReqNumber)
+		{
+	    case RDisplayChannel::EReqGetCompositionBuffer:
+	    		__DEBUG_PRINT2("EReqGetCompositionBuffer: kernelCompBuffIdx returned =%d",kernelCompBuffIdx);						
+				umemput32(userConfigData1, &kernelCompBuffIdx, sizeof(TInt) );
+				break;
+				
+        case RDisplayChannel::EReqPostUserBuffer:
+        		__DEBUG_PRINT2("EReqPostUserBuffer: kernelCount returned = %d",kernelCount);
+				umemput32(userConfigData2, &kernelCount, sizeof(RDisplayChannel::TPostCount) );	
+				break;							
+		}		 	
+	return r;
+	}
+
+
+/**
+Validate, pre-process, send and post-process data for a synchronous client request, so that data can be safely
+accessed from kernel threads without the possibility of taking page faults. 
+
+This function is called in the context of the client thread.
+
+@param aMsg  The message to process.
+             The iValue member of this distinguishes the message type:
+			 iValue==ECloseMsg, channel close message
+			 iValue==KMaxTInt, a 'DoCancel' message
+			 iValue>=0, a 'DoControl' message with function number equal to iValue
+			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
+						 
+@return KErrNone if the message was send successfully, otherwise one of the other system-wide error
+        codes.
+ */ 
+
+TInt DDisplayLdd::SendControl(TMessageBase* aMsg)
+	{	
+	TThreadMessage& m	= *(TThreadMessage*)aMsg;
+    TInt aReqNumber 	= m.iValue;
+	
+
+	//Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
+		
+	RDisplayChannel::TPostCount  			kernelPostCount;
+	RDisplayChannel::TDisplayRotation 		kernelRotation;
+	
+	TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);
+
+	TInt  kernelpack[2];	
+	TInt  kernelBufferId;
+	TBool kernelRotChanged;
+	TInt  kernelIndex;
+	
+	TAny* userConfigData0 = m.Ptr0();
+	TAny* userConfigData1 = m.Ptr1();
+		
+			
+	switch (aReqNumber)
+		{
+		//iDisplayInfo doesn't change after the driver initialisation so copy in client thread context
+		case RDisplayChannel::ECtrlGetDisplayInfo:
+			umemput32(userConfigData0, &pckgInfo, sizeof(TPckgBuf<RDisplayChannel::TDisplayInfo>) );	
+			return KErrNone;
+
+		case RDisplayChannel::ECtrlPostCompositionBuffer:  		//Client should read data updated in the DFC thread.
+			m.iArg[1] = &kernelPostCount;
+			break;
+		
+		case RDisplayChannel::ECtrlPostLegacyBuffer:			//Client should read data updated in the DFC thread.
+			m.iArg[1] = &kernelPostCount;			
+			break;	
+		
+		case RDisplayChannel::ECtrlRegisterUserBuffer:			//Both the client and DFC thread need to read data.
+			umemget32(&kernelpack, userConfigData0, (sizeof(TInt)*2) );
+			m.iArg[0] = &kernelpack;			
+			m.iArg[1] = &kernelBufferId;	
+			break;
+		
+		case RDisplayChannel::ECtrlDeregisterUserBuffer:		//Client data should be passed to the DFC thread.	
+			umemget32(&kernelBufferId, userConfigData0, sizeof(TInt) );
+			m.iArg[0] = &kernelBufferId;				
+			break;	
+				
+	 	case RDisplayChannel::ECtrlSetRotation:					//Both the client and DFC thread need to read data.
+			umemget32(&kernelRotation, userConfigData0, sizeof(RDisplayChannel::TDisplayRotation) );
+			m.iArg[0] = &kernelRotation;
+			m.iArg[1] = &kernelRotChanged;
+			break;
+			
+		case RDisplayChannel::ECtrlCurrentRotation:				//Client should read data updated in the DFC thread.
+			m.iArg[0] = &kernelRotation;
+			break;
+			
+		case RDisplayChannel::ECtrlGetCompositionBufferInfo:	//Both the client and DFC thread need to read data.		
+			umemget32(&kernelIndex, userConfigData0, sizeof(TInt) );
+			m.iArg[0] = &kernelIndex;
+			m.iArg[1] = &kernelpack;		
+			break;
+
+#ifdef _DEBUG
+		case RDisplayChannel::ECtrlCreateUserBuffer:
+		    m.iArg[0] = userConfigData0;
+            m.iArg[1] = userConfigData1;
+            break;
+#endif // _DEBUG
+
+		default:
+			return KErrNotSupported; 
+				
+		}
+	
+	TInt r = DLogicalChannel::SendMsg(aMsg);	
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	 //Copy config data from local copies to client, in context of client thread
+    switch (aReqNumber)
+		{					
+	    case RDisplayChannel::ECtrlPostCompositionBuffer:  				
+			__DEBUG_PRINT2("ECtrlPostCompositionBuffer =%d", kernelPostCount );
+			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );	
+			break;
+		
+		case RDisplayChannel::ECtrlPostLegacyBuffer:
+			__DEBUG_PRINT2("ECtrlPostLegacyBuffer=%d", kernelPostCount );	
+			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );			
+			break;	
+		
+		case RDisplayChannel::ECtrlRegisterUserBuffer:
+			__DEBUG_PRINT2("ECtrlRegisterUserBuffer kernelBufferId=%d", kernelBufferId );	
+			umemput32(userConfigData1, &kernelBufferId, sizeof(TInt) );
+			break;
+		
+		case RDisplayChannel::ECtrlSetRotation:
+			__DEBUG_PRINT2("ECtrlSetRotation  kernelRotChanged=%d", kernelRotChanged );
+			umemput32(userConfigData1, &kernelRotChanged, sizeof(TBool) );
+			break;	
+		
+		case RDisplayChannel::ECtrlCurrentRotation:
+			__DEBUG_PRINT2("ECtrlCurrentRotation kernelRotation=%d",  kernelRotation );
+			umemput32(userConfigData0, &kernelRotation, sizeof(RDisplayChannel::TDisplayRotation) );
+			break;
+		
+		case RDisplayChannel::ECtrlGetCompositionBufferInfo:				
+			__DEBUG_PRINT3("ECtrlGetCompositionBufferInfo kernelpack[0] =%d and kernelpack[1] =%d",  kernelpack[0], kernelpack[1]);
+			umemput32(userConfigData1, &kernelpack, (sizeof(TInt)*2) );
+			break;					
+		}			
+	return r;
+	}
+	
+	
+/**
+  All driver's client requests (synchronous and asynchronous) are sent as
+  kernel messages by generic kernel to logical channel. This function
+  catches messages sent by the generic kernel.
+ 
+  @param aMsg Kernel side thread message to process.
+
+	The iValue member of this distinguishes the message type:
+	iValue==ECloseMsg, channel close message
+	iValue==KMaxTInt, a 'DoCancel' message
+	iValue>=0, a 'DoControl' message with function number equal to iValue
+	iValue<0, a 'DoRequest' message with function number equal to ~iValue
  */ 
 void DDisplayLdd::HandleMsg(TMessageBase* aMsg)
 	{
@@ -170,12 +541,18 @@
     	Pdd()->CloseMsg();
     	
         // cancel outstanding requests
-        for(int k = 0; k < KPendingReqArraySize; k++)
-        	{
-            if(iPendingReq[k].iStatus) 
-            	{
-            	CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);
-            	}
+        for(TInt k = 0; k < KPendingReqArraySize; k++)
+        	{ 
+			for(TInt i = 0; i < KMaxQueuedRequests; i++)
+				{
+	        	if( iPendingReq[k][i].iTClientReq) 
+	            	{
+	            	if(iPendingReq[k][i].iTClientReq->IsReady() )
+	            		{
+	            		CompleteRequest(iPendingReq[k][i].iOwningThread,iPendingReq[k][i].iTClientReq,KErrCancel);
+	            		}            	            		
+	            	}
+				}
         	}
         Pdd()->SetLegacyMode();
 		m.Complete(KErrNone, EFalse);
@@ -193,8 +570,8 @@
     // asynchronous request
 	else if (id < 0)
 		{
-		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
-		TInt r = DoRequest(~id,pS,m.Ptr1(),m.Ptr2(), client);
+		//m.Int3() is the index, in the array of pending requests, to be used.
+		TInt r = DoRequest(~id,m.Ptr1(),m.Ptr2(),m.Int3(), client);
 		m.Complete(r, ETrue);
 		}
     // synchronous request
@@ -219,13 +596,14 @@
 		 {
 		 case RDisplayChannel::ECtrlCancelGetCompositionBuffer:
 		 case RDisplayChannel::ECtrlCancelPostUserBuffer:
-		 case RDisplayChannel::ECtrlCancelWaitForPost:
-	        if(iPendingReq[aReqNumber].iStatus)
+		 case RDisplayChannel::ECtrlCancelWaitForPost:		 
+			TInt pendingIndex = iPendingIndex[aReqNumber];
+	        if(iPendingReq[aReqNumber][pendingIndex].iTClientReq)
 	        	{
-        		CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
-        		
-        		iPendingReq[aReqNumber].iStatus 	  = 0;
-        		iPendingReq[aReqNumber].iOwningThread = 0;
+	        	if( iPendingReq[aReqNumber][pendingIndex].iTClientReq->IsReady() )
+	        		{
+	        		CompleteRequest(iPendingReq[aReqNumber][pendingIndex].iOwningThread,iPendingReq[aReqNumber][pendingIndex].iTClientReq,KErrCancel);
+	        		}
             	}
 			break;
 		}	
@@ -235,146 +613,156 @@
 /**
 	Asynchronous request processing.
 	
-	@param aFunction    request function number
-    @param apRqStat     pointer to the user's request status object.
-    @param apArg1       pointer to the 1st parameter
-    @param apArg2       pointer to the 2nd parameter
+    @param aFunction    	Request function number
+    @param apArg1       	Pointer to kernel message argument 1.
+    @param apArg2       	Pointer to kernel message argument 2.
+    @param aPendingIndex    Index pointing to the appropriate TClientRequest object to use.
+	@param aClient			Pointer to the client thread that issued the asynchronous request.
 	
-	@return request scheduling result, system-wide error code.
+    @return request scheduling result, system-wide error code.
 */
-TInt DDisplayLdd::DoRequest(TInt aReqNumber, TRequestStatus* aRqStat, TAny* aArg1, TAny* aArg2, DThread* aClient)
+TInt DDisplayLdd::DoRequest(TInt aReqNumber, TAny* aArg1, TAny* aArg2, TInt aPendingIndex, DThread* aClient)
 	{	
-    TUint count;
+
     TInt pack[2];
     TInt r 				= KErrNone;
     TBufferNode* node 	= 0;
-    TInt buffer_id  	= 0;
-        
+    TInt buffer_id  	= 0;   
+    
+    TInt* configBufferIdx  ;
+    RDisplayChannel::TPostCount* postCount;	
+    TInt* configPack; 
+		
+	__DEBUG_PRINT5("DoRequest: iClientRequest[aReqNumber=%d][aPendingIndex=%d] is %08x  and aClient=%08x\n",aReqNumber, aPendingIndex,iClientRequest[aReqNumber][aPendingIndex], aClient);    
+    
     // Open a reference on the client thread while the request is pending so it's control block can't disappear until this driver has finished with it.
 	r=aClient->Open();
 	__ASSERT_ALWAYS(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));
 #ifdef _DEBUG
 	__e32_atomic_add_ord32(&iThreadOpenCount, 1);
 #endif	
-    
-    // check if this request is valid
-    if(aReqNumber >= 0 && aReqNumber <= RDisplayChannel::EReqWaitForPost)
-    	{
+    	
+	for(TInt i = 0; i < KMaxQueuedRequests; i++)
+		{
+		//Don't cancel the asyncrhonous request we currently process.
+		if (i == aPendingIndex)
+			{
+			continue;
+			}
         // cancel outstanding request
-        if(iPendingReq[aReqNumber].iStatus)
+        if(iPendingReq[aReqNumber][i].iTClientReq)        
 			{
-            CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
-            iPendingReq[aReqNumber].iStatus 	  = 0;
-            iPendingReq[aReqNumber].iOwningThread = 0;
+			//If IsReady() returns true, setStatus has been called for that TCientRequest but QueueRequestComplete hasn't. 
+			//In that case we want to cancel this outstanding request. Given that all QueueRequestComplete calls execute 
+			// in the same DFC thread we currently run, there is no need to synchronise request completion calls. 
+			if(iPendingReq[aReqNumber][i].iTClientReq->IsReady() )
+				{
+				CompleteRequest(iPendingReq[aReqNumber][i].iOwningThread,iPendingReq[aReqNumber][i].iTClientReq,KErrCancel);
+				break;				
+				}
         	}
-        	
-    	// store request and client
-    	iPendingReq[aReqNumber].iStatus = aRqStat;
-    	iPendingReq[aReqNumber].iOwningThread = aClient;
     	}
-
+	// store  index, request  and client
+	iPendingIndex[aReqNumber] 								= aPendingIndex;
+	iPendingReq[aReqNumber][aPendingIndex].iTClientReq 		= iClientRequest[aReqNumber][aPendingIndex];
+	iPendingReq[aReqNumber][aPendingIndex].iOwningThread 	= aClient;
+	
+	#ifdef _DEBUG
+		__e32_atomic_add_ord32(&iAsyncReqCount, 1);
+	#endif   	    	    	    	    	    	  
+  
     switch (aReqNumber)
 		{
-	     case RDisplayChannel::EReqGetCompositionBuffer:
+	     case RDisplayChannel::EReqGetCompositionBuffer:		//DFC thread updates a value the client thread should read.
+			 { 
+			 configBufferIdx = (TInt*) aArg1;
+		 
+	          TInt  index;
+			  TBool found = EFalse;
+			  
+			  for(index = 0; index < (TInt) iDisplayInfo.iNumCompositionBuffers; index++)
+					{
+					if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
+						{
+						__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
 
-			if(aArg1 == 0 )
-	              {
-	               r = KErrGeneral;
-	               CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
-	               iPendingReq[aReqNumber].iStatus 		 = 0;
-	               iPendingReq[aReqNumber].iOwningThread = 0;
-	              }			
-			else
-            	  {	 	
-	              TInt  index;
-	              TBool found = EFalse;
-	              
-	              for(index =0; index< KDisplayCBMax; index++)
-		              	{
-		              	if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
-							{
-							__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
-
-			                 iCompositionBuffIdx = index;
-			                 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
-							 if ( r == KErrNone)
-								{   
-								 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
-								 CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
-								 iPendingReq[aReqNumber].iStatus 	   = 0;
-								 iPendingReq[aReqNumber].iOwningThread = 0;
-								 found = ETrue;
-								 break;
-								}
+						 iCompositionBuffIdx = index;
+						 *configBufferIdx = iCompositionBuffIdx;
+						 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
+						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread,iPendingReq[aReqNumber][aPendingIndex].iTClientReq,r);
+						 found = ETrue;
+						 break;
+						 }
+					}				
+			  if(!found)  	//There are no free buffers schedule request for completion
+					{	
+					//Case of a single composition buffer. 
+					if (iDisplayInfo.iNumCompositionBuffers == 1)
+						{
+						iCompositionBuffIdx = 0;
+						 *configBufferIdx = iCompositionBuffIdx;							 
+						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread, iPendingReq[aReqNumber][aPendingIndex].iTClientReq, r);
+						 __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
+						 break;													
+						}
+							
+				 
+					for( index=0; index< KDisplayCBMax; index++)
+						 {
+						 if(iCompositionBuffer[index].iState == EBufferActive)
+							 {	
+							 iCompositionBuffIdx = index;
+							 *configBufferIdx = iCompositionBuffIdx;								 
+							 __DEBUG_PRINT2("EReqGetCompositionBuffer  No composition buffer available. Next available is iCompositionBuffIdx  %d.\n",iCompositionBuffIdx );
+							 break;
 							 }
-		              	}				
-				  if(!found)  	//There are no free buffers schedule request for completion
-					 	{	
-						//Case of a single composition buffer. 
-						if (iDisplayInfo.iNumCompositionBuffers == 1)
-							{
-							iCompositionBuffIdx = 0;
-			             	 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
-		                     __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
-		                     break;													
-							}
-								
-				 	 
-		              	for( index=0; index< KDisplayCBMax; index++)
-			                 {
-			                 if(iCompositionBuffer[index].iState == EBufferActive)
-								 {	
-		                         iCompositionBuffIdx = index;
-			                  	 r = Kern::ThreadRawWrite(aClient, aArg1,&iCompositionBuffIdx, sizeof(TInt), aClient);
-			                     __DEBUG_PRINT2("EReqGetCompositionBuffer  No composition buffer available. Next available is iCompositionBuffIdx  %d.\n",iCompositionBuffIdx );
-			                     break;
-								 }
-			                 }
-				 	 	}			 	 		
-	            }
-          	break;
+						 }
+					}			 	 			            
+          	
+			  break;
+			  }
 
-         case RDisplayChannel::EReqPostUserBuffer:			
-            r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
-			if ( r == KErrNone)
-				{
-				r = KErrArgument;
-	            buffer_id = pack[0];
-	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
-	             	{
-	                node = FindUserBufferNode(buffer_id);
-	                if(node  && (!(node->iFree) && node->iChunk ) ) 
-	                	{
-	                  	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
-	                  	r = Pdd()->PostUserBuffer(node);
-	                  	if(r == KErrNone)
-		                  	 {
-		     		    	 ++iCurrentPostCount;
-		                	 r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);	           		     
-		           		     break;
-		                  	 }
-	                	}
-	             	}
-	            RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
-				}
+         case RDisplayChannel::EReqPostUserBuffer:		//DFC thread should read client message data and update a value the client will read.	                                            
+            configPack = (TInt*) aArg1;
+            pack[0] = *configPack; 
+            configPack++;           
+            pack[1] = *configPack;
+			
+			r = KErrArgument;
+            buffer_id = pack[0];
+            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
+             	{
+                node = FindUserBufferNode(buffer_id);
+                if(node  && (!(node->iFree) && node->iChunk ) ) 
+                	{
+                  	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
+                  	r = Pdd()->PostUserBuffer(node);
+                  	if(r == KErrNone)
+	                  	 {
+	                  	 postCount = (RDisplayChannel::TPostCount*) aArg2;
+	     		    	 ++iCurrentPostCount;
+	                	 *postCount= iCurrentPostCount;	                	 
+	           		     break;
+	                  	 }
+                	}
+             	}
+            RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
+
             break; 	        
 
-         case RDisplayChannel::EReqWaitForPost:
-            r= Kern::ThreadRawRead(aClient, aArg1,  &count, sizeof(RDisplayChannel::TPostCount));
-			if ( r == KErrNone)
-				{   
-			    iRequestedPostCount = count;
-	    	    //Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
-	    	    if( ! Pdd()->PostPending() )
-	    	    	 {
-	    	    	 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
-	    	    	 } 
-				}	 
+         case RDisplayChannel::EReqWaitForPost:			 	//DFC thread should read client message data.
+			postCount = (RDisplayChannel::TPostCount*) aArg1;
+			iRequestedPostCount = *postCount;
+									
+			//Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
+			if( ! Pdd()->PostPending() )
+				 {
+				 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
+				 } 					 
          	break;
 
         default:
-			r = KErrNotSupported;
-			break;
+			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
 		}
     return r;	
 	}
@@ -383,69 +771,75 @@
 /**
 	Synchronous requests processing.
 	
-	@param aFunction    request function number,
-	@param apArg1       pointer to the 1st parameter
-	@param apArg2       pointer to the 2n parameter
+	@param aFunction    Request function number,
+	@param apArg1       Pointer to kernel message argument 0.
+	@param apArg2       Pointer to kernel message argument 1.
+	@param aClient		Pointer to the client thread that issued the synchronous request.
     
     @return request processing result
 */
 TInt DDisplayLdd::DoControl(TInt aFunction, TAny* aArg1, TAny* aArg2, DThread* aClient)
  {
-	TInt r 			  = KErrNotSupported;
+	TInt r 			  = KErrNone;
     TBool changedRot  = ETrue;
     TBufferNode* node = 0;
 	TInt buffer_id;
     TInt pack[2]      = {0,0};
     TInt handle, offset;
     TInt index        = 0;
-
-    TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);
-
+	
+	RDisplayChannel::TPostCount 		*postCount ;
+	RDisplayChannel::TDisplayRotation   *rotation; 
+	
+	TInt	*configPack; 
+	TInt	*bufferId; 	
+	
+	TBool   *rotationChanged;
+	TInt    *idx;
+	
     switch (aFunction)
 		{
-	    case RDisplayChannel::ECtrlGetDisplayInfo:
-            r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&pckgInfo, sizeof(pckgInfo), aClient);
-    	    break;
-
-	    case RDisplayChannel::ECtrlPostCompositionBuffer:
+	    case RDisplayChannel::ECtrlPostCompositionBuffer: 	//DFC thread updates a value the client thread should read.
+			postCount = (RDisplayChannel::TPostCount*) aArg2;		
+					
 	        node =  &iCompositionBuffer[iCompositionBuffIdx];
             r = Pdd()->PostCompositionBuffer(node);
 		    if(r == KErrNone)
 		    	{
     		    ++iCurrentPostCount;
-                r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);
-    			}
+    			*postCount = iCurrentPostCount;
+				}
             else 
             	{
             	r = KErrGeneral;	
             	}            	    	            	
 			break;
 
-        case RDisplayChannel::ECtrlPostLegacyBuffer:
+        case RDisplayChannel::ECtrlPostLegacyBuffer:		//DFC thread updates a value the client thread should read.
+			postCount = (RDisplayChannel::TPostCount*) aArg2;
             r= Pdd()->PostLegacyBuffer();
             if ( r == KErrNone)
             	{
-             	++iCurrentPostCount;
-            	r = Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);           	
-            	}            
+             	++iCurrentPostCount;         	
+            	*postCount = iCurrentPostCount;
+				}            
 			break;
 
-	    case RDisplayChannel::ECtrlRegisterUserBuffer:
+	    case RDisplayChannel::ECtrlRegisterUserBuffer:	//DFC thread should read client message data and update a value the client will read.
             node = FindUserBufferNode(0);
 			if(node)
-				{
-                r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
-				if(r == KErrNone)
-					{
-	                handle  = pack[0]; 
-	                offset  = pack[1];
-	                r 		= CheckAndOpenUserBuffer(node, handle, offset, aClient);
-	                
-	                if(r == KErrNone)
-	                	{
-	                     r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&node->iBufferId, sizeof(TInt), aClient);
-	                	}
-					}
+				{					                         
+                configPack = (TInt*) aArg1;
+                handle 	   = *configPack;
+                configPack++;
+                offset     = *configPack;                               
+                r 	       = CheckAndOpenUserBuffer(node, handle, offset, aClient);
+                
+                if(r == KErrNone)
+                	{
+                	bufferId  = (TInt*) aArg2;
+                	*bufferId = node->iBufferId;
+                	}					
 				}
             else
             	{
@@ -453,79 +847,124 @@
             	}
 			break;
 
-	    case RDisplayChannel::ECtrlDeregisterUserBuffer:
-            r= Kern::ThreadRawRead(aClient, aArg1, &buffer_id, sizeof(TInt));
-            if ( r == KErrNone)
-				{
-				r = KErrArgument;          
-	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
-	            	{
-		            node = FindUserBufferNode(buffer_id);	            
-		            if(node  && (!(node->iFree) && node->iChunk ) ) 
-		            	{	                
-		                if(node->iState==EBufferFree  || node->iState==EBufferCompose )
-		                	{
-		                	r = FreeUserBufferNode(node);	                	
-		                	}
-		                else
-		                	{
-		                	r = KErrInUse;
-		                	}
-		            	}               	                                    
-	            	}
-				}
+	    case RDisplayChannel::ECtrlDeregisterUserBuffer:	//DFC thread should read client message data.
+            bufferId  = (TInt*) aArg1;
+            buffer_id = *bufferId;
+            
+            
+			r = KErrArgument;          
+            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
+            	{
+	            node = FindUserBufferNode(buffer_id);	            
+	            if(node  && (!(node->iFree) && node->iChunk ) ) 
+	            	{	                
+	                if(node->iState==EBufferFree  || node->iState==EBufferCompose )
+	                	{
+	                	r = FreeUserBufferNode(node);	                	
+	                	}
+	                else
+	                	{
+	                	r = KErrInUse;
+	                	}
+	            	}               	                                    
+            	}
 			break;
 
-	    case RDisplayChannel::ECtrlPostCount:
-            r= Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentPostCount, sizeof(TUint), aClient);
+	    case RDisplayChannel::ECtrlSetRotation:	    //DFC thread should read client message data and update a value the client will read.	    			    
+            {            	         
+            RDisplayChannel::TDisplayRotation rot;
+            RDisplayChannel::TDisplayRotation previousRot = iCurrentRotation;
+                        
+            rotation  = (RDisplayChannel::TDisplayRotation*) aArg1;
+           	rot 	  = *rotation;
+            
+            __DEBUG_PRINT3("ECtrlSetRotation previousRot= %d and rot =%d \n",previousRot, rot );
+             	
+            r = Pdd()->SetRotation(rot);                  
+            changedRot = (previousRot != iCurrentRotation);          
+            if( r == KErrNone)
+    	        {                  
+           	    rotationChanged  = (TBool*) aArg2;
+           	    *rotationChanged = changedRot ;         	    
+           	    }					    	
+    	    break;
+            }
+            
+	    case RDisplayChannel::ECtrlCurrentRotation:				//DFC thread updates a value the client thread should read.
+			rotation  = (RDisplayChannel::TDisplayRotation*) aArg1;
+			*rotation = iCurrentRotation; 
 			break;
 
-	    case RDisplayChannel::ECtrlSetRotation:	    
-	    	{	    			    
-            RDisplayChannel::TDisplayRotation rot;
-            TInt previousRot = iCurrentRotation;
-            r= Kern::ThreadRawRead(aClient, aArg1, &rot, sizeof(RDisplayChannel::TDisplayRotation));
-            if ( r == KErrNone)
-				{               	
-                r = Pdd()->SetRotation((TInt)rot);                  
-                changedRot=(previousRot!=iCurrentRotation);              
-                if( r == KErrNone)
-        	        {
-                   	 r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&changedRot, sizeof(TBool), aClient);                       
-               	    }
-				}
-	    	}
-    	    break;
+	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:	//DFC thread should read client message data and update a value the client will read.
+            idx   = ( TInt * ) aArg1;
+            index = *idx;
+	  
+			if( (index >= (TInt) iDisplayInfo.iNumCompositionBuffers ) || (index < 0 ) )
+            	{
+            	r = KErrArgument;
+            	break;	
+            	}
+			r = Kern::MakeHandleAndOpen(aClient, iCompositionBuffer[index].iChunk);
 
-	    case RDisplayChannel::ECtrlCurrentRotation:
-			r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentRotation, sizeof(RDisplayChannel::TDisplayRotation), aClient);
-			break;
+			if(r >= KErrNone)
+				{
+				pack[0] 	= r;
+				pack[1] 	= iCompositionBuffer[index].iOffset;	
+				
+				configPack  = (TInt * ) aArg2;
+				*configPack = pack[0];
+				configPack++;
+				*configPack = pack[1];				 
+				
+				r = KErrNone;
+				}					
+		 	break;
+
+#ifdef _DEBUG
+	    case RDisplayChannel::ECtrlCreateUserBuffer:
+	        {
+	        TUint32 chunkMapAttr;
+	        TLinAddr chunkBase;
+	        TPhysAddr physicalAddr;
+	        RDisplayChannel::TBufferFormat bufferFormat;
 
-	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:
-    	    {
-            r= Kern::ThreadRawRead(aClient, aArg1, &index, sizeof(TInt));                     
-            if ( r == KErrNone)
-				{   
-				if( (index >= KDisplayCBMax ) || (index < 0 ) )
-	            	{
-	            	r = KErrArgument;
-	            	break;	
-	            	}
-				r = Kern::MakeHandleAndOpen(aClient, iCompositionBuffer[index].iChunk);
+	        // Read the information from the user thread pertaining to the buffer to be allocated
+	        Kern::ThreadRawRead(aClient, aArg1, &bufferFormat, sizeof(bufferFormat));
+
+	        // Allocate a chunk that can be used as a user buffer.  Don't worry about the # of bytes
+	        // per pixel as this is UDEB only test code - just set it to 4 and that will ensure that
+	        // it is large enough
+	        TChunkCreateInfo chunkCreateInfo;
+	        chunkCreateInfo.iType = TChunkCreateInfo::ESharedKernelSingle;
+#ifndef __WINS__
+	        chunkCreateInfo.iMapAttr = EMapAttrFullyBlocking;
+#endif // ! __WINS__
+	        chunkCreateInfo.iOwnsMemory = ETrue;
+	        chunkCreateInfo.iDestroyedDfc = NULL;
+	        chunkCreateInfo.iMaxSize = (bufferFormat.iSize.iWidth * bufferFormat.iSize.iHeight * 4);
 
-				if(r >= KErrNone)
-					{
-					pack[0] = r;
-					pack[1] = iCompositionBuffer[index].iOffset;
-					r=Kern::ThreadRawWrite(aClient, aArg2, &pack, (sizeof(TInt)*2), aClient);
-					}
-				}	
-		 	break;
-			}
-    	   
-        default:
-			r = KErrNotSupported;
-			break;
+	        if ((r = Kern::ChunkCreate(chunkCreateInfo, iChunk, chunkBase, chunkMapAttr)) == KErrNone)
+	            {
+	            // Commit some contiguous physical RAM for use in the chunk 
+	            r = Kern::ChunkCommitContiguous(iChunk, 0, chunkCreateInfo.iMaxSize, physicalAddr);
+
+	            // And open a handle to the chunk that will be returned to user side for use in the user
+	            // side's RChunk object
+	            if (r == KErrNone)
+	                r = Kern::MakeHandleAndOpen(aClient, iChunk);
+	            else
+	            	{
+	                Kern::ChunkClose(iChunk);
+	                iChunk = NULL;
+	            	}
+	            }
+
+	        break;
+	        }
+#endif // _DEBUG
+
+	    default:
+			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
 		};
     return r;	
 	}
@@ -551,7 +990,8 @@
   chunk = Kern::OpenSharedChunk(aClient, aHandle, EFalse);
   NKern::ThreadLeaveCS();
   if(chunk)
-		{
+    	{                            
+		
 		// Using iOffsetBetweenLines rather than iWidth as the controller may be using stride
 		size = iDisplayInfo.iNormal.iOffsetBetweenLines * iDisplayInfo.iNormal.iHeight;
                 
@@ -637,25 +1077,28 @@
 
 
 /**    
-   Calls CompleteRequest( which internally sends a Kern::RequestComplete message )for the specified request and with the reason passed, 
-   in case such an asynchronous request is pending. Also resets the pending queue fields for that request if it was actually pending. 
-   Called by both the LDD and PDD.
+   Calls CompleteRequest( which internally calls Kern::QueueRequestComplete )for the specified request and with the reason passed, 
+   in case such an asynchronous request is pending.  Called by both the LDD and PDD.
    
 */ 
 TInt DDisplayLdd::RequestComplete(TInt aRequest, TInt aReason)
 	{
-	TBool flag = EFalse;
-			
+	TBool flag 		  = EFalse;
+	
+	TInt pendingIndex =   iPendingIndex[aRequest] ;	
+	
 	switch (aRequest)
-		{
+		{		
 	    case RDisplayChannel::EReqGetCompositionBuffer:	
 			{
 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqGetCompositionBuffer request and reason %d\n",aReason );
 			
-	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus)
+	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq )
 				{
-				__DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqGetCompositionBuffer \n");
-	            flag = ETrue;
+				if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq->IsReady() )
+					{
+		            flag = ETrue;					
+					}
 	        	}
 	        break;											
 			}
@@ -664,10 +1107,12 @@
 			{
 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqWaitForPost request and reason %d\n",aReason );
 			
-	 		if((iPendingReq[RDisplayChannel::EReqWaitForPost].iStatus != 0) && (iCurrentPostCount >= iRequestedPostCount) )
+	 		if(iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq) 
 	    	    {
-	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqWaitForPost \n");
-				flag = ETrue;
+	    	    if( iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq->IsReady()  && (iCurrentPostCount >= iRequestedPostCount) )
+	    	    	{
+					flag = ETrue;	    	    	
+	    	    	}
 	            }
 	        break;    												
 			}
@@ -676,10 +1121,12 @@
 			{
 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqPostUserBuffer request and reason %d\n",aReason );
 				
-			if((iPendingReq[RDisplayChannel::EReqPostUserBuffer].iStatus != 0) )
+			if(iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq)
 	    		{
-	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqPostUserBuffer \n");
-				flag = ETrue;
+	    		if( iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq->IsReady() )
+	    			{
+					flag = ETrue;	    			
+	    			}
 	            }
 	        break;			
 			}
@@ -691,9 +1138,7 @@
 		
 	if (flag)
 		{
-		CompleteRequest(iPendingReq[aRequest].iOwningThread,iPendingReq[aRequest].iStatus,aReason);
-		iPendingReq[aRequest].iStatus 		= 0;
-		iPendingReq[aRequest].iOwningThread = 0;			
+		CompleteRequest(iPendingReq[aRequest][pendingIndex].iOwningThread,iPendingReq[aRequest][pendingIndex].iTClientReq,aReason);		
 		}
 				
 	return KErrNone;	
@@ -702,19 +1147,27 @@
 
 /** 
 Complete an asynchronous request back to the client.
-@param aThread The client thread which issued the request.
-@param aStatus The TRequestStatus instance that will receive the request status code. 
-@param aReason The request status code.  
+
+@param aThread     The client thread which issued the request.
+@param aTClientReq Pointer reference to the TClientRequest object  
+@param aReason     The request status code.  
+
 @pre The thread must be in a critical section. 
 */
-void DDisplayLdd::CompleteRequest(DThread* aThread, TRequestStatus*& aStatus, TInt aReason)
-	{		
-	Kern::RequestComplete(aThread,aStatus,aReason);		// Complete the request back to the client.
+void DDisplayLdd::CompleteRequest(DThread* aThread, TClientRequest*& aTClientReq, TInt aReason)
+	{			
+	__DEBUG_PRINT4("Complete aTClientReq %08x with reason %d for aThread = %08x\n", aTClientReq, aReason,aThread );		
 	
+	Kern::QueueRequestComplete(aThread,aTClientReq,aReason);
+		
 	aThread->AsyncClose();	// Asynchronously close our reference on the client thread - don't want to be blocked if this is final reference. 
-
+				
+	aThread		  =0;
+	aTClientReq   =0;
+	
 #ifdef _DEBUG	
 	__e32_atomic_add_ord32(&iThreadOpenCount, TUint32(-1));
+	__e32_atomic_add_ord32(&iAsyncReqCount,   TUint32(-1));
 #endif	
 			
 	}