os/kernelhwsrv/kernel/eka/drivers/display/display.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // os\kernelhwsrv\kernel\eka\drivers\display\display.cpp  
    15 // LDD for a Display driver with GCE support
    16 // 
    17 //
    18 
    19 /**
    20  @file
    21  @internalTechnology
    22  @prototype
    23 */
    24 
    25 
    26 #include <drivers/display.h>
    27 #include <kernel/kern_priv.h>
    28 
    29 
    30 const TUint8  KMutexOrder             = 0x3f;
    31 
    32 static const char KDisplayLddPanic[]  ="DISPLAY/GCE LDD";
    33 
    34 _LIT(KClientRequestMutex, "ClientRequestMutex");
    35 
    36 
    37 /************************************************************************************
    38  *            DDisplayLdd LDD class implementation
    39  ************************************************************************************/
    40 DDisplayLdd::DDisplayLdd()		
    41 	{	
    42 	__DEBUG_PRINT("DDisplayLdd::DDisplayLdd()\n");
    43 	// store the pointer to the current thread for request completion
    44   	iClient = &Kern::CurrentThread();
    45     __NK_ASSERT_DEBUG(iClient);
    46 	// Open a reference on the client thread so it's control block can't disappear until the driver has finished with it.
    47     iClient->Open();
    48     iCurrentPostCount   = 0;
    49     iRequestedPostCount = 0;
    50     iCompositionBuffIdx = 0;
    51     iUnit				= -1;
    52     iThreadOpenCount    = 0;
    53     iAsyncReqCount		= 0;
    54     iClientRequestMutex = 0;	
    55 	}
    56 
    57 
    58 DDisplayLdd::~DDisplayLdd()
    59 	{
    60 	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
    61      // cancel outstanding requests and destroy the queue of TClientRequest objects
    62     for(TInt k = 0; k < KPendingReqArraySize ; k++)
    63     	{
    64 		for(TInt i = 0; i < KMaxQueuedRequests; i++)
    65 			{
    66 			//Method IsReady() returns true if the client’s request SetStatus method has been called but the 
    67 			//coresponding QueueRequestComplete method hasn't.			
    68 			if(iPendingReq[k][i].iTClientReq)        
    69 				{
    70 				if(iPendingReq[k][i].iTClientReq->IsReady() )
    71 					{
    72 					CompleteRequest(iPendingReq[k][i].iOwningThread,iPendingReq[k][i].iTClientReq,KErrCancel);        	
    73 					}     		
    74 				}			
    75 			Kern::DestroyClientRequest(iClientRequest[k][i]);
    76 			}
    77 		}
    78     
    79     //Close User Buffer chunks not yet destroyed.
    80 	for(TInt i = 0; i < KDisplayUBMax; i++)
    81 		{
    82 		if(iUserBuffer[i].iChunk != 0)
    83 			{
    84     		Kern::ChunkClose(iUserBuffer[i].iChunk);
    85     		iUserBuffer[i].iChunk= NULL;
    86 			}
    87 		}
    88     	
    89     Kern::SafeClose((DObject*&)iClient, NULL);  
    90     
    91     
    92     if (iClientRequestMutex != NULL)
    93          {
    94          iClientRequestMutex->Close(NULL);
    95          }
    96     
    97     __ASSERT_DEBUG(iThreadOpenCount == 0,Kern::Fault(KDisplayLddPanic,__LINE__));
    98     __ASSERT_DEBUG(iAsyncReqCount   == 0,Kern::Fault(KDisplayLddPanic,__LINE__));  
    99     	
   100     // Clear the 'units open mask' in the LDD factory.
   101 	if (iUnit>=0)
   102 		((DDisplayLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);	 	
   103 
   104 #ifdef _DEBUG
   105 	// Close the UDEB user mode chunk, if it exists
   106 	if (iChunk)
   107 		Kern::ChunkClose(iChunk);
   108 #endif // _DEBUG
   109 	}
   110  
   111 
   112 /**
   113 	LDD second stage constructor
   114 */
   115 TInt DDisplayLdd::DoCreate(TInt aUnit, const TDesC8* /* anInfo*/, const TVersion& aVer)
   116 	{ 
   117 	
   118 	__DEBUG_PRINT("DDisplayLdd::DoCreate()\n"); 
   119 
   120 	if(    !Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,      __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   121 		|| !Kern::CurrentThreadHasCapability(ECapabilityReadDeviceData, __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   122 		|| !Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   123 		|| !Kern::CurrentThreadHasCapability(ECapabilityProtServ,       __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") ) )
   124 		{
   125 		return KErrPermissionDenied;
   126 		}
   127 		  
   128 	// Check that the display driver version specified by the client is compatible.
   129 	if (!Kern::QueryVersionSupported(RDisplayChannel::VersionRequired(),aVer))
   130 		{
   131 		return(KErrNotSupported);		
   132 		}
   133 				
   134 	// Check that a channel hasn't already been opened on this unit.
   135 	TInt r=((DDisplayLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
   136 	if (r!=KErrNone)
   137 		return r;
   138 	iUnit=aUnit;
   139 
   140  	Pdd()->iLdd	= this;
   141  	
   142  	r		= Pdd()->CreateChannelSetup(aUnit); 	
   143  	if ( r!= KErrNone)
   144  		{
   145  		return r; 		
   146  		}
   147  
   148      // set up user buffer nodes
   149     for (TInt node = 0; node < KDisplayUBMax; node++)
   150     	{
   151         iUserBuffer[node].iType 	= EBufferTypeUser;
   152         iUserBuffer[node].iBufferId = (node + 1);
   153         iUserBuffer[node].iFree 	= ETrue;
   154         iUserBuffer[node].iState 	= EBufferFree;
   155         iUserBuffer[node].iAddress  = 0;
   156         iUserBuffer[node].iSize  	= 0;
   157         iUserBuffer[node].iHandle  	= 0;
   158         iUserBuffer[node].iChunk  	= 0;
   159         iUserBuffer[node].iOffset 	= 0;
   160         iUserBuffer[node].iPendingRequest = 0;
   161     	}
   162 
   163     //Initialise pending queue for asynchronous requests and queue of TClientRequests
   164     for(TInt k = 0; k < KPendingReqArraySize; k++) 
   165     	{
   166     	
   167     	iPendingIndex[k]=0;
   168     	
   169 		for(TInt i = 0; i < KMaxQueuedRequests; i++)
   170 			{
   171 			iPendingReq[k][i].iTClientReq   = 0;
   172 			iPendingReq[k][i].iOwningThread = 0;
   173 			
   174 			
   175 			r = Kern::CreateClientRequest(iClientRequest[k][i]);
   176 			if (r != KErrNone)
   177 				{
   178 				return r;      	
   179 				}
   180 			}	
   181     	} 
   182     
   183     r = Kern::MutexCreate(iClientRequestMutex, KClientRequestMutex, KMutexOrder);	
   184 	if (r != KErrNone)
   185 		{
   186 		return r;
   187 		}	
   188     
   189           
   190     Pdd()->SetGceMode();	
   191 	SetDfcQ(Pdd()->DfcQ(aUnit));	   
   192     iMsgQ.Receive();
   193     
   194     return KErrNone;		
   195 }
   196 
   197 
   198 /**
   199 Override DLogicalChannel::SendMsg to process a client message before and after sending the message 
   200 to the DFC thread for processing by HandleMsg().
   201  
   202 This function is called in the context of the client thread.
   203 
   204 The function is used to pin client data in the context of the client thread, so that data can be safely
   205 accessed from kernel threads without the possibility of taking page faults.
   206  
   207 @param aMsg  The message to process.
   208              The iValue member of this distinguishes the message type:
   209 			 iValue==ECloseMsg, channel close message
   210 			 iValue==KMaxTInt, a 'DoCancel' message
   211 			 iValue>=0, a 'DoControl' message with function number equal to iValue
   212 			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
   213   
   214  @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
   215         codes.
   216  
   217  */ 
   218 
   219 TInt DDisplayLdd::SendMsg(TMessageBase* aMsg)
   220 	{
   221 	TThreadMessage& m=*(TThreadMessage*)aMsg;
   222     TInt id = m.iValue;
   223 	
   224 	TInt r = KErrNone;	
   225 	 // close msg or cancel
   226 	if (id == (TInt)ECloseMsg || id == KMaxTInt)
   227 		{
   228 		r = DLogicalChannel::SendMsg(aMsg);
   229 		}
   230 	//asynchronous request
   231 	else if (id < 0)
   232 		{
   233 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   234 		r = SendRequest(aMsg);
   235 		if (r != KErrNone)
   236 			Kern::RequestComplete(pS,r);
   237 		}
   238 	 // synchronous request
   239 	else{
   240 		r = SendControl(aMsg);
   241 		}
   242 	
   243 	return r;
   244 	}
   245 
   246 
   247 /**
   248 Validate, pre-process, send and post-process data for an asynchronous client request, so that data can be safely
   249 accessed from kernel threads without the possibility of taking page faults. 
   250 
   251 This function is called in the context of the client thread.
   252  
   253 @param aMsg  The message to process.
   254              The iValue member of this distinguishes the message type:
   255 			 iValue==ECloseMsg, channel close message
   256 			 iValue==KMaxTInt, a 'DoCancel' message
   257 			 iValue>=0, a 'DoControl' message with function number equal to iValue
   258 			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
   259  
   260  @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
   261         codes.
   262  */ 
   263 TInt DDisplayLdd::SendRequest(TMessageBase* aMsg)
   264 	{
   265 	TThreadMessage& m	=*(TThreadMessage*)aMsg;
   266     TInt aReqNumber 	= ~m.iValue;
   267 	TRequestStatus* pS	=(TRequestStatus*)m.Ptr0();
   268 	
   269 	#ifdef _GCE_DISPLAY_DEBUG
   270 	DThread* client 	= m.Client();
   271 	#endif		
   272 			
   273 	TInt r 				= KErrNotSupported;
   274 	TInt pendingIndex;
   275 
   276 	/*Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
   277 	Using thread local copies is possible even for asynchronous requests, since the values to be returned are known 
   278 	when processing the request( inside DoRequest ) and not at a later stage.*/
   279 	
   280 	TInt kernelCompBuffIdx;
   281 	TInt kernelpack[2];	
   282 	RDisplayChannel::TPostCount  kernelCount;
   283 	
   284 	
   285 	//In asynchronous requests m.Ptr0 is used for the TRequestStatus object.
   286 	TAny* userConfigData1 = m.Ptr1();
   287 	TAny* userConfigData2 = m.Ptr2();
   288 	
   289 	/*
   290 	If the client request needs to pass some data to the DFC thread then we copy these to a thread local
   291 	copy(created in the thread supervisor stack) and then update the message to point to that local copy. 
   292 	If the client will have to read a value updated in the DFC thread, then the message should just be 
   293 	updated and point to the local copy. After the request has completed the updated data will be copied
   294 	from the local copy to the client, in the context of the client thread. 
   295 	*/
   296     
   297     switch (aReqNumber)
   298 		{
   299 	    case RDisplayChannel::EReqGetCompositionBuffer:	//Client should read data updated in the DFC thread.
   300 				m.iArg[1] = &kernelCompBuffIdx;				
   301 				break;
   302 
   303         case RDisplayChannel::EReqPostUserBuffer:    	//Both the client and DFC thread need to read data.
   304 				umemget32(&kernelpack, userConfigData1, (sizeof(TInt)*2) );
   305 				m.iArg[1] = &kernelpack;
   306 				m.iArg[2] = &kernelCount;
   307 				break;		
   308 		
   309 		case RDisplayChannel::EReqWaitForPost:			//Client data should be passed to the DFC thread.	
   310 				umemget32(&kernelCount, userConfigData1, sizeof(RDisplayChannel::TPostCount) );
   311 				m.iArg[1] = &kernelCount;							
   312 				break;
   313 		default:
   314 				return KErrNotSupported; 
   315 		
   316 		}
   317 		
   318 	/* 		
   319 	The TClientRequest objects associated with each asynchronous request need to be accessed by both the client and DFC
   320 	threads. To resolve the potential synchronization problem we maintain two seperate pointers(iClientRequest and 
   321 	iPendingReq.iClientReq )to the same TClientRequest object. iClientRequestMutex is used to synchronise access to 
   322 	iClientRequest from different client threads. The first client thread that acquires the mutex will set the status
   323 	of an available TClientRequest object and send the message(call SendMsg). Consequently method DoRequest is queued for 
   324 	execution by the DFC thread. DoRequest initialy saves iClientRequest to iPendingReq.iClientReq and queues the request. 
   325 	Only then, the mutex is signaled. Another client thread trying to access iClientRequest will block in the mutex until
   326 	DoRequest has updated iPendingReq.iClientReq. Even more the DFC thread only accesses iClientRequest in DoRequest and 
   327 	then iPendingReq.iClientReq is only used, so synchronizing access to iPendingReq.iClientReq is handled by the DFC queue.
   328 	*/
   329 	
   330 	// Need to be in critical section whilst holding a DMutex
   331 	NKern::ThreadEnterCS();
   332 	
   333 	Kern::MutexWait(*iClientRequestMutex);	
   334 	//Save the TRequestStatus in any available TClientRequest object for that asynchronous request.
   335 	
   336 	for( TInt k=0; k< KMaxQueuedRequests; k++) 
   337 		{
   338 		//setStatus will return KErrInUse if a previous client request hasn't completed yet.
   339 		r = iClientRequest[aReqNumber][k]->SetStatus(pS);
   340 		if( r == KErrNone)
   341 			{
   342 			pendingIndex = k;
   343 			//The current available index for this pending request will be passed as 
   344 			//another message argument to the DFC thread.
   345 			m.iArg[3] =  (TAny*) pendingIndex; 
   346 			break;
   347 			}		 			
   348 		}
   349 					 						
   350 	if (r == KErrNone)
   351 		{
   352 		r = DLogicalChannel::SendMsg(aMsg);
   353 		}
   354 	else
   355 		{
   356 		__DEBUG_PRINT3("Client %08x trying to issue asynchronous request %d", client, aReqNumber);
   357 		//Fail if there aren't any available TClientRequest object
   358 		__ASSERT_DEBUG(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));				
   359 		}
   360 	
   361 	Kern::MutexSignal(*iClientRequestMutex);
   362 
   363     NKern::ThreadLeaveCS();
   364     
   365     //Copy config data from local copies to client, in context of client thread
   366     switch (aReqNumber)
   367 		{
   368 	    case RDisplayChannel::EReqGetCompositionBuffer:
   369 	    		__DEBUG_PRINT2("EReqGetCompositionBuffer: kernelCompBuffIdx returned =%d",kernelCompBuffIdx);						
   370 				umemput32(userConfigData1, &kernelCompBuffIdx, sizeof(TInt) );
   371 				break;
   372 				
   373         case RDisplayChannel::EReqPostUserBuffer:
   374         		__DEBUG_PRINT2("EReqPostUserBuffer: kernelCount returned = %d",kernelCount);
   375 				umemput32(userConfigData2, &kernelCount, sizeof(RDisplayChannel::TPostCount) );	
   376 				break;							
   377 		}		 	
   378 	return r;
   379 	}
   380 
   381 
   382 /**
   383 Validate, pre-process, send and post-process data for a synchronous client request, so that data can be safely
   384 accessed from kernel threads without the possibility of taking page faults. 
   385 
   386 This function is called in the context of the client thread.
   387 
   388 @param aMsg  The message to process.
   389              The iValue member of this distinguishes the message type:
   390 			 iValue==ECloseMsg, channel close message
   391 			 iValue==KMaxTInt, a 'DoCancel' message
   392 			 iValue>=0, a 'DoControl' message with function number equal to iValue
   393 			 iValue<0, a 'DoRequest' message with function number equal to ~iValue
   394 						 
   395 @return KErrNone if the message was send successfully, otherwise one of the other system-wide error
   396         codes.
   397  */ 
   398 
   399 TInt DDisplayLdd::SendControl(TMessageBase* aMsg)
   400 	{	
   401 	TThreadMessage& m	= *(TThreadMessage*)aMsg;
   402     TInt aReqNumber 	= m.iValue;
   403 	
   404 
   405 	//Use thread local copies of the configuration data that need to be exchanged between the client and DFC thread. 
   406 		
   407 	RDisplayChannel::TPostCount  			kernelPostCount;
   408 	RDisplayChannel::TDisplayRotation 		kernelRotation;
   409 	
   410 	TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);
   411 
   412 	TInt  kernelpack[2];	
   413 	TInt  kernelBufferId;
   414 	TBool kernelRotChanged;
   415 	TInt  kernelIndex;
   416 	
   417 	TAny* userConfigData0 = m.Ptr0();
   418 	TAny* userConfigData1 = m.Ptr1();
   419 		
   420 			
   421 	switch (aReqNumber)
   422 		{
   423 		//iDisplayInfo doesn't change after the driver initialisation so copy in client thread context
   424 		case RDisplayChannel::ECtrlGetDisplayInfo:
   425 			umemput32(userConfigData0, &pckgInfo, sizeof(TPckgBuf<RDisplayChannel::TDisplayInfo>) );	
   426 			return KErrNone;
   427 
   428 		case RDisplayChannel::ECtrlPostCompositionBuffer:  		//Client should read data updated in the DFC thread.
   429 			m.iArg[1] = &kernelPostCount;
   430 			break;
   431 		
   432 		case RDisplayChannel::ECtrlPostLegacyBuffer:			//Client should read data updated in the DFC thread.
   433 			m.iArg[1] = &kernelPostCount;			
   434 			break;	
   435 		
   436 		case RDisplayChannel::ECtrlRegisterUserBuffer:			//Both the client and DFC thread need to read data.
   437 			umemget32(&kernelpack, userConfigData0, (sizeof(TInt)*2) );
   438 			m.iArg[0] = &kernelpack;			
   439 			m.iArg[1] = &kernelBufferId;	
   440 			break;
   441 		
   442 		case RDisplayChannel::ECtrlDeregisterUserBuffer:		//Client data should be passed to the DFC thread.	
   443 			umemget32(&kernelBufferId, userConfigData0, sizeof(TInt) );
   444 			m.iArg[0] = &kernelBufferId;				
   445 			break;	
   446 				
   447 	 	case RDisplayChannel::ECtrlSetRotation:					//Both the client and DFC thread need to read data.
   448 			umemget32(&kernelRotation, userConfigData0, sizeof(RDisplayChannel::TDisplayRotation) );
   449 			m.iArg[0] = &kernelRotation;
   450 			m.iArg[1] = &kernelRotChanged;
   451 			break;
   452 			
   453 		case RDisplayChannel::ECtrlCurrentRotation:				//Client should read data updated in the DFC thread.
   454 			m.iArg[0] = &kernelRotation;
   455 			break;
   456 			
   457 		case RDisplayChannel::ECtrlGetCompositionBufferInfo:	//Both the client and DFC thread need to read data.		
   458 			umemget32(&kernelIndex, userConfigData0, sizeof(TInt) );
   459 			m.iArg[0] = &kernelIndex;
   460 			m.iArg[1] = &kernelpack;		
   461 			break;
   462 
   463 #ifdef _DEBUG
   464 		case RDisplayChannel::ECtrlCreateUserBuffer:
   465 		    m.iArg[0] = userConfigData0;
   466             m.iArg[1] = userConfigData1;
   467             break;
   468 #endif // _DEBUG
   469 
   470 		default:
   471 			return KErrNotSupported; 
   472 				
   473 		}
   474 	
   475 	TInt r = DLogicalChannel::SendMsg(aMsg);	
   476 	if (r != KErrNone)
   477 		{
   478 		return r;
   479 		}
   480 
   481 	 //Copy config data from local copies to client, in context of client thread
   482     switch (aReqNumber)
   483 		{					
   484 	    case RDisplayChannel::ECtrlPostCompositionBuffer:  				
   485 			__DEBUG_PRINT2("ECtrlPostCompositionBuffer =%d", kernelPostCount );
   486 			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );	
   487 			break;
   488 		
   489 		case RDisplayChannel::ECtrlPostLegacyBuffer:
   490 			__DEBUG_PRINT2("ECtrlPostLegacyBuffer=%d", kernelPostCount );	
   491 			umemput32(userConfigData1, &kernelPostCount, sizeof(RDisplayChannel::TPostCount) );			
   492 			break;	
   493 		
   494 		case RDisplayChannel::ECtrlRegisterUserBuffer:
   495 			__DEBUG_PRINT2("ECtrlRegisterUserBuffer kernelBufferId=%d", kernelBufferId );	
   496 			umemput32(userConfigData1, &kernelBufferId, sizeof(TInt) );
   497 			break;
   498 		
   499 		case RDisplayChannel::ECtrlSetRotation:
   500 			__DEBUG_PRINT2("ECtrlSetRotation  kernelRotChanged=%d", kernelRotChanged );
   501 			umemput32(userConfigData1, &kernelRotChanged, sizeof(TBool) );
   502 			break;	
   503 		
   504 		case RDisplayChannel::ECtrlCurrentRotation:
   505 			__DEBUG_PRINT2("ECtrlCurrentRotation kernelRotation=%d",  kernelRotation );
   506 			umemput32(userConfigData0, &kernelRotation, sizeof(RDisplayChannel::TDisplayRotation) );
   507 			break;
   508 		
   509 		case RDisplayChannel::ECtrlGetCompositionBufferInfo:				
   510 			__DEBUG_PRINT3("ECtrlGetCompositionBufferInfo kernelpack[0] =%d and kernelpack[1] =%d",  kernelpack[0], kernelpack[1]);
   511 			umemput32(userConfigData1, &kernelpack, (sizeof(TInt)*2) );
   512 			break;					
   513 		}			
   514 	return r;
   515 	}
   516 	
   517 	
   518 /**
   519   All driver's client requests (synchronous and asynchronous) are sent as
   520   kernel messages by generic kernel to logical channel. This function
   521   catches messages sent by the generic kernel.
   522  
   523   @param aMsg Kernel side thread message to process.
   524 
   525 	The iValue member of this distinguishes the message type:
   526 	iValue==ECloseMsg, channel close message
   527 	iValue==KMaxTInt, a 'DoCancel' message
   528 	iValue>=0, a 'DoControl' message with function number equal to iValue
   529 	iValue<0, a 'DoRequest' message with function number equal to ~iValue
   530  */ 
   531 void DDisplayLdd::HandleMsg(TMessageBase* aMsg)
   532 	{
   533     TThreadMessage& m	= *(TThreadMessage*)aMsg ;
   534 	TInt id 			= m.iValue ;
   535     DThread* client 	= m.Client();
   536 
   537     // close message
   538     if (id == (TInt)ECloseMsg)
   539     	{
   540     	//Device specific cleanup operations
   541     	Pdd()->CloseMsg();
   542     	
   543         // cancel outstanding requests
   544         for(TInt k = 0; k < KPendingReqArraySize; k++)
   545         	{ 
   546 			for(TInt i = 0; i < KMaxQueuedRequests; i++)
   547 				{
   548 	        	if( iPendingReq[k][i].iTClientReq) 
   549 	            	{
   550 	            	if(iPendingReq[k][i].iTClientReq->IsReady() )
   551 	            		{
   552 	            		CompleteRequest(iPendingReq[k][i].iOwningThread,iPendingReq[k][i].iTClientReq,KErrCancel);
   553 	            		}            	            		
   554 	            	}
   555 				}
   556         	}
   557         Pdd()->SetLegacyMode();
   558 		m.Complete(KErrNone, EFalse);
   559 		return;
   560 		}
   561     // cancel
   562     if (id == KMaxTInt)
   563 		{
   564 		// DoCancel
   565 		TInt req = m.Int0() >> 1;
   566 		DoCancel(req);
   567 		m.Complete(KErrNone,ETrue);
   568     	return;
   569 		}
   570     // asynchronous request
   571 	else if (id < 0)
   572 		{
   573 		//m.Int3() is the index, in the array of pending requests, to be used.
   574 		TInt r = DoRequest(~id,m.Ptr1(),m.Ptr2(),m.Int3(), client);
   575 		m.Complete(r, ETrue);
   576 		}
   577     // synchronous request
   578 	else
   579 		{
   580 	   	TInt r = DoControl(id,m.Ptr0(),m.Ptr1(), client);
   581 		m.Complete(r,ETrue);
   582 		}
   583 	} 
   584 
   585 
   586 /**
   587 	Cancel outstanding request.
   588 	
   589 	@param  aReqNumber	Any value from the RDisplayChannel::TRequest enumeration.
   590 */
   591 void DDisplayLdd::DoCancel(TUint aReqNumber)
   592 	{
   593       __DEBUG_PRINT2("DDisplayLdd::DoCancel %d\n",aReqNumber);
   594 
   595        switch (aReqNumber)
   596 		 {
   597 		 case RDisplayChannel::ECtrlCancelGetCompositionBuffer:
   598 		 case RDisplayChannel::ECtrlCancelPostUserBuffer:
   599 		 case RDisplayChannel::ECtrlCancelWaitForPost:		 
   600 			TInt pendingIndex = iPendingIndex[aReqNumber];
   601 	        if(iPendingReq[aReqNumber][pendingIndex].iTClientReq)
   602 	        	{
   603 	        	if( iPendingReq[aReqNumber][pendingIndex].iTClientReq->IsReady() )
   604 	        		{
   605 	        		CompleteRequest(iPendingReq[aReqNumber][pendingIndex].iOwningThread,iPendingReq[aReqNumber][pendingIndex].iTClientReq,KErrCancel);
   606 	        		}
   607             	}
   608 			break;
   609 		}	
   610 	
   611 	}
   612 
   613 /**
   614 	Asynchronous request processing.
   615 	
   616     @param aFunction    	Request function number
   617     @param apArg1       	Pointer to kernel message argument 1.
   618     @param apArg2       	Pointer to kernel message argument 2.
   619     @param aPendingIndex    Index pointing to the appropriate TClientRequest object to use.
   620 	@param aClient			Pointer to the client thread that issued the asynchronous request.
   621 	
   622     @return request scheduling result, system-wide error code.
   623 */
   624 TInt DDisplayLdd::DoRequest(TInt aReqNumber, TAny* aArg1, TAny* aArg2, TInt aPendingIndex, DThread* aClient)
   625 	{	
   626 
   627     TInt pack[2];
   628     TInt r 				= KErrNone;
   629     TBufferNode* node 	= 0;
   630     TInt buffer_id  	= 0;   
   631     
   632     TInt* configBufferIdx  ;
   633     RDisplayChannel::TPostCount* postCount;	
   634     TInt* configPack; 
   635 		
   636 	__DEBUG_PRINT5("DoRequest: iClientRequest[aReqNumber=%d][aPendingIndex=%d] is %08x  and aClient=%08x\n",aReqNumber, aPendingIndex,iClientRequest[aReqNumber][aPendingIndex], aClient);    
   637     
   638     // 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.
   639 	r=aClient->Open();
   640 	__ASSERT_ALWAYS(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));
   641 #ifdef _DEBUG
   642 	__e32_atomic_add_ord32(&iThreadOpenCount, 1);
   643 #endif	
   644     	
   645 	for(TInt i = 0; i < KMaxQueuedRequests; i++)
   646 		{
   647 		//Don't cancel the asyncrhonous request we currently process.
   648 		if (i == aPendingIndex)
   649 			{
   650 			continue;
   651 			}
   652         // cancel outstanding request
   653         if(iPendingReq[aReqNumber][i].iTClientReq)        
   654 			{
   655 			//If IsReady() returns true, setStatus has been called for that TCientRequest but QueueRequestComplete hasn't. 
   656 			//In that case we want to cancel this outstanding request. Given that all QueueRequestComplete calls execute 
   657 			// in the same DFC thread we currently run, there is no need to synchronise request completion calls. 
   658 			if(iPendingReq[aReqNumber][i].iTClientReq->IsReady() )
   659 				{
   660 				CompleteRequest(iPendingReq[aReqNumber][i].iOwningThread,iPendingReq[aReqNumber][i].iTClientReq,KErrCancel);
   661 				break;				
   662 				}
   663         	}
   664     	}
   665 	// store  index, request  and client
   666 	iPendingIndex[aReqNumber] 								= aPendingIndex;
   667 	iPendingReq[aReqNumber][aPendingIndex].iTClientReq 		= iClientRequest[aReqNumber][aPendingIndex];
   668 	iPendingReq[aReqNumber][aPendingIndex].iOwningThread 	= aClient;
   669 	
   670 	#ifdef _DEBUG
   671 		__e32_atomic_add_ord32(&iAsyncReqCount, 1);
   672 	#endif   	    	    	    	    	    	  
   673   
   674     switch (aReqNumber)
   675 		{
   676 	     case RDisplayChannel::EReqGetCompositionBuffer:		//DFC thread updates a value the client thread should read.
   677 			 { 
   678 			 configBufferIdx = (TInt*) aArg1;
   679 		 
   680 	          TInt  index;
   681 			  TBool found = EFalse;
   682 			  
   683 			  for(index = 0; index < (TInt) iDisplayInfo.iNumCompositionBuffers; index++)
   684 					{
   685 					if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
   686 						{
   687 						__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
   688 
   689 						 iCompositionBuffIdx = index;
   690 						 *configBufferIdx = iCompositionBuffIdx;
   691 						 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
   692 						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread,iPendingReq[aReqNumber][aPendingIndex].iTClientReq,r);
   693 						 found = ETrue;
   694 						 break;
   695 						 }
   696 					}				
   697 			  if(!found)  	//There are no free buffers schedule request for completion
   698 					{	
   699 					//Case of a single composition buffer. 
   700 					if (iDisplayInfo.iNumCompositionBuffers == 1)
   701 						{
   702 						iCompositionBuffIdx = 0;
   703 						 *configBufferIdx = iCompositionBuffIdx;							 
   704 						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread, iPendingReq[aReqNumber][aPendingIndex].iTClientReq, r);
   705 						 __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
   706 						 break;													
   707 						}
   708 							
   709 				 
   710 					for( index=0; index< KDisplayCBMax; index++)
   711 						 {
   712 						 if(iCompositionBuffer[index].iState == EBufferActive)
   713 							 {	
   714 							 iCompositionBuffIdx = index;
   715 							 *configBufferIdx = iCompositionBuffIdx;								 
   716 							 __DEBUG_PRINT2("EReqGetCompositionBuffer  No composition buffer available. Next available is iCompositionBuffIdx  %d.\n",iCompositionBuffIdx );
   717 							 break;
   718 							 }
   719 						 }
   720 					}			 	 			            
   721           	
   722 			  break;
   723 			  }
   724 
   725          case RDisplayChannel::EReqPostUserBuffer:		//DFC thread should read client message data and update a value the client will read.	                                            
   726             configPack = (TInt*) aArg1;
   727             pack[0] = *configPack; 
   728             configPack++;           
   729             pack[1] = *configPack;
   730 			
   731 			r = KErrArgument;
   732             buffer_id = pack[0];
   733             if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
   734              	{
   735                 node = FindUserBufferNode(buffer_id);
   736                 if(node  && (!(node->iFree) && node->iChunk ) ) 
   737                 	{
   738                   	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
   739                   	r = Pdd()->PostUserBuffer(node);
   740                   	if(r == KErrNone)
   741 	                  	 {
   742 	                  	 postCount = (RDisplayChannel::TPostCount*) aArg2;
   743 	     		    	 ++iCurrentPostCount;
   744 	                	 *postCount= iCurrentPostCount;	                	 
   745 	           		     break;
   746 	                  	 }
   747                 	}
   748              	}
   749             RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
   750 
   751             break; 	        
   752 
   753          case RDisplayChannel::EReqWaitForPost:			 	//DFC thread should read client message data.
   754 			postCount = (RDisplayChannel::TPostCount*) aArg1;
   755 			iRequestedPostCount = *postCount;
   756 									
   757 			//Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
   758 			if( ! Pdd()->PostPending() )
   759 				 {
   760 				 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
   761 				 } 					 
   762          	break;
   763 
   764         default:
   765 			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
   766 		}
   767     return r;	
   768 	}
   769 
   770 
   771 /**
   772 	Synchronous requests processing.
   773 	
   774 	@param aFunction    Request function number,
   775 	@param apArg1       Pointer to kernel message argument 0.
   776 	@param apArg2       Pointer to kernel message argument 1.
   777 	@param aClient		Pointer to the client thread that issued the synchronous request.
   778     
   779     @return request processing result
   780 */
   781 TInt DDisplayLdd::DoControl(TInt aFunction, TAny* aArg1, TAny* aArg2, DThread* aClient)
   782  {
   783 	TInt r 			  = KErrNone;
   784     TBool changedRot  = ETrue;
   785     TBufferNode* node = 0;
   786 	TInt buffer_id;
   787     TInt pack[2]      = {0,0};
   788     TInt handle, offset;
   789     TInt index        = 0;
   790 	
   791 	RDisplayChannel::TPostCount 		*postCount ;
   792 	RDisplayChannel::TDisplayRotation   *rotation; 
   793 	
   794 	TInt	*configPack; 
   795 	TInt	*bufferId; 	
   796 	
   797 	TBool   *rotationChanged;
   798 	TInt    *idx;
   799 	
   800     switch (aFunction)
   801 		{
   802 	    case RDisplayChannel::ECtrlPostCompositionBuffer: 	//DFC thread updates a value the client thread should read.
   803 			postCount = (RDisplayChannel::TPostCount*) aArg2;		
   804 					
   805 	        node =  &iCompositionBuffer[iCompositionBuffIdx];
   806             r = Pdd()->PostCompositionBuffer(node);
   807 		    if(r == KErrNone)
   808 		    	{
   809     		    ++iCurrentPostCount;
   810     			*postCount = iCurrentPostCount;
   811 				}
   812             else 
   813             	{
   814             	r = KErrGeneral;	
   815             	}            	    	            	
   816 			break;
   817 
   818         case RDisplayChannel::ECtrlPostLegacyBuffer:		//DFC thread updates a value the client thread should read.
   819 			postCount = (RDisplayChannel::TPostCount*) aArg2;
   820             r= Pdd()->PostLegacyBuffer();
   821             if ( r == KErrNone)
   822             	{
   823              	++iCurrentPostCount;         	
   824             	*postCount = iCurrentPostCount;
   825 				}            
   826 			break;
   827 
   828 	    case RDisplayChannel::ECtrlRegisterUserBuffer:	//DFC thread should read client message data and update a value the client will read.
   829             node = FindUserBufferNode(0);
   830 			if(node)
   831 				{					                         
   832                 configPack = (TInt*) aArg1;
   833                 handle 	   = *configPack;
   834                 configPack++;
   835                 offset     = *configPack;                               
   836                 r 	       = CheckAndOpenUserBuffer(node, handle, offset, aClient);
   837                 
   838                 if(r == KErrNone)
   839                 	{
   840                 	bufferId  = (TInt*) aArg2;
   841                 	*bufferId = node->iBufferId;
   842                 	}					
   843 				}
   844             else
   845             	{
   846     			r = KErrTooBig;
   847             	}
   848 			break;
   849 
   850 	    case RDisplayChannel::ECtrlDeregisterUserBuffer:	//DFC thread should read client message data.
   851             bufferId  = (TInt*) aArg1;
   852             buffer_id = *bufferId;
   853             
   854             
   855 			r = KErrArgument;          
   856             if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
   857             	{
   858 	            node = FindUserBufferNode(buffer_id);	            
   859 	            if(node  && (!(node->iFree) && node->iChunk ) ) 
   860 	            	{	                
   861 	                if(node->iState==EBufferFree  || node->iState==EBufferCompose )
   862 	                	{
   863 	                	r = FreeUserBufferNode(node);	                	
   864 	                	}
   865 	                else
   866 	                	{
   867 	                	r = KErrInUse;
   868 	                	}
   869 	            	}               	                                    
   870             	}
   871 			break;
   872 
   873 	    case RDisplayChannel::ECtrlSetRotation:	    //DFC thread should read client message data and update a value the client will read.	    			    
   874             {            	         
   875             RDisplayChannel::TDisplayRotation rot;
   876             RDisplayChannel::TDisplayRotation previousRot = iCurrentRotation;
   877                         
   878             rotation  = (RDisplayChannel::TDisplayRotation*) aArg1;
   879            	rot 	  = *rotation;
   880             
   881             __DEBUG_PRINT3("ECtrlSetRotation previousRot= %d and rot =%d \n",previousRot, rot );
   882              	
   883             r = Pdd()->SetRotation(rot);                  
   884             changedRot = (previousRot != iCurrentRotation);          
   885             if( r == KErrNone)
   886     	        {                  
   887            	    rotationChanged  = (TBool*) aArg2;
   888            	    *rotationChanged = changedRot ;         	    
   889            	    }					    	
   890     	    break;
   891             }
   892             
   893 	    case RDisplayChannel::ECtrlCurrentRotation:				//DFC thread updates a value the client thread should read.
   894 			rotation  = (RDisplayChannel::TDisplayRotation*) aArg1;
   895 			*rotation = iCurrentRotation; 
   896 			break;
   897 
   898 	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:	//DFC thread should read client message data and update a value the client will read.
   899             idx   = ( TInt * ) aArg1;
   900             index = *idx;
   901 	  
   902 			if( (index >= (TInt) iDisplayInfo.iNumCompositionBuffers ) || (index < 0 ) )
   903             	{
   904             	r = KErrArgument;
   905             	break;	
   906             	}
   907 			r = Kern::MakeHandleAndOpen(aClient, iCompositionBuffer[index].iChunk);
   908 
   909 			if(r >= KErrNone)
   910 				{
   911 				pack[0] 	= r;
   912 				pack[1] 	= iCompositionBuffer[index].iOffset;	
   913 				
   914 				configPack  = (TInt * ) aArg2;
   915 				*configPack = pack[0];
   916 				configPack++;
   917 				*configPack = pack[1];				 
   918 				
   919 				r = KErrNone;
   920 				}					
   921 		 	break;
   922 
   923 #ifdef _DEBUG
   924 	    case RDisplayChannel::ECtrlCreateUserBuffer:
   925 	        {
   926 	        TUint32 chunkMapAttr;
   927 	        TLinAddr chunkBase;
   928 	        TPhysAddr physicalAddr;
   929 	        RDisplayChannel::TBufferFormat bufferFormat;
   930 
   931 	        // Read the information from the user thread pertaining to the buffer to be allocated
   932 	        Kern::ThreadRawRead(aClient, aArg1, &bufferFormat, sizeof(bufferFormat));
   933 
   934 	        // Allocate a chunk that can be used as a user buffer.  Don't worry about the # of bytes
   935 	        // per pixel as this is UDEB only test code - just set it to 4 and that will ensure that
   936 	        // it is large enough
   937 	        TChunkCreateInfo chunkCreateInfo;
   938 	        chunkCreateInfo.iType = TChunkCreateInfo::ESharedKernelSingle;
   939 #ifndef __WINS__
   940 	        chunkCreateInfo.iMapAttr = EMapAttrFullyBlocking;
   941 #endif // ! __WINS__
   942 	        chunkCreateInfo.iOwnsMemory = ETrue;
   943 	        chunkCreateInfo.iDestroyedDfc = NULL;
   944 	        chunkCreateInfo.iMaxSize = (bufferFormat.iSize.iWidth * bufferFormat.iSize.iHeight * 4);
   945 
   946 	        if ((r = Kern::ChunkCreate(chunkCreateInfo, iChunk, chunkBase, chunkMapAttr)) == KErrNone)
   947 	            {
   948 	            // Commit some contiguous physical RAM for use in the chunk 
   949 	            r = Kern::ChunkCommitContiguous(iChunk, 0, chunkCreateInfo.iMaxSize, physicalAddr);
   950 
   951 	            // And open a handle to the chunk that will be returned to user side for use in the user
   952 	            // side's RChunk object
   953 	            if (r == KErrNone)
   954 	                r = Kern::MakeHandleAndOpen(aClient, iChunk);
   955 	            else
   956 	            	{
   957 	                Kern::ChunkClose(iChunk);
   958 	                iChunk = NULL;
   959 	            	}
   960 	            }
   961 
   962 	        break;
   963 	        }
   964 #endif // _DEBUG
   965 
   966 	    default:
   967 			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
   968 		};
   969     return r;	
   970 	}
   971 
   972 
   973 /**
   974     Open a shared Chunk for the User buffer and then set the appropriate values for the
   975     User buffer node attributes.
   976 	
   977 */
   978 TInt DDisplayLdd::CheckAndOpenUserBuffer(TBufferNode* aNode, TInt aHandle, TInt aOffset, DThread* aClient)
   979  {
   980  
   981   TInt     	size 				= 0;
   982   DChunk*  	chunk 				= 0;
   983   TLinAddr 	kernelAddress 		= 0;
   984   TUint32  	mapAttr 			= 0;
   985   TUint32  	physicalAddress 	= 0;
   986   TUint32  	*physicalPageList 	= 0;
   987   TInt 		r 					= KErrBadHandle;
   988 	
   989   NKern::ThreadEnterCS();
   990   chunk = Kern::OpenSharedChunk(aClient, aHandle, EFalse);
   991   NKern::ThreadLeaveCS();
   992   if(chunk)
   993     	{                            
   994 		
   995 		// Using iOffsetBetweenLines rather than iWidth as the controller may be using stride
   996 		size = iDisplayInfo.iNormal.iOffsetBetweenLines * iDisplayInfo.iNormal.iHeight;
   997                 
   998         r = Kern::ChunkPhysicalAddress(chunk, aOffset, size, kernelAddress, mapAttr, physicalAddress, physicalPageList);
   999         if( r == KErrNone )
  1000         	{
  1001             aNode->iChunk 			= chunk;
  1002             aNode->iFree  			= EFalse;
  1003             aNode->iState 			= EBufferCompose;
  1004             aNode->iAddress 		= (TUint32)kernelAddress;
  1005             aNode->iHandle 			= aHandle;
  1006             aNode->iPhysicalAddress = physicalAddress;
  1007         	}
  1008         else
  1009         	{ // we have an error here, close the chunk
  1010         	r = KErrArgument;  
  1011             Kern::ChunkClose(chunk);
  1012         	}
  1013     }
  1014   return (r);
  1015   }
  1016 
  1017 
  1018 /**
  1019     Return any free buffer when trying to register a User buffer( aBufferId ==0 )
  1020     or return the specified User buffer( used by Deregister and PostUserBuffer).
  1021     In the second case checks about the state of the user buffer are specific to 
  1022     each case. 
  1023     
  1024 */
  1025 TBufferNode* DDisplayLdd::FindUserBufferNode(TInt aBufferId)
  1026 	{
  1027     TBufferNode* node = 0;
  1028 
  1029     if(aBufferId == 0)
  1030 		{
  1031 		for(TInt i = 0; i < KDisplayUBMax; i++)
  1032 			{
  1033 			if(iUserBuffer[i].iFree)
  1034 				{
  1035 				node = &iUserBuffer[i];
  1036 				break;
  1037 				}
  1038 			}
  1039 		}
  1040 	else
  1041 		{		 
  1042 		 node = &iUserBuffer[aBufferId-1];
  1043 		}
  1044     return (node);
  1045 	}
  1046 
  1047 
  1048 /**
  1049     Free user buffer by reseting all the appropriate fields and closing the corresponding chunk.
  1050 */ 
  1051 TInt DDisplayLdd::FreeUserBufferNode(TBufferNode* aNode)
  1052 	{
  1053 	__DEBUG_PRINT2("FreeUserBufferNode with aNode->iAddress %08x.\n",aNode->iAddress );
  1054 	TInt r = KErrNone;
  1055 	NKern::ThreadEnterCS();
  1056     if(aNode->iChunk != 0)
  1057     	{
  1058     	r= Kern::ChunkClose(aNode->iChunk);
  1059     	}    	
  1060     if( r== KErrNone)
  1061     	{
  1062     	aNode->iState 	= EBufferFree;
  1063     	aNode->iFree 	= ETrue;
  1064     	aNode->iAddress = 0;
  1065     	aNode->iSize 	= 0;
  1066     	aNode->iHandle 	= 0;
  1067     	aNode->iChunk 	= 0;
  1068     	}
  1069     else
  1070     	{
  1071     	__DEBUG_PRINT("Failed to close chunk\n");    	
  1072     	}
  1073 	NKern::ThreadLeaveCS();	
  1074     
  1075     return r;
  1076 	}	
  1077 
  1078 
  1079 /**    
  1080    Calls CompleteRequest( which internally calls Kern::QueueRequestComplete )for the specified request and with the reason passed, 
  1081    in case such an asynchronous request is pending.  Called by both the LDD and PDD.
  1082    
  1083 */ 
  1084 TInt DDisplayLdd::RequestComplete(TInt aRequest, TInt aReason)
  1085 	{
  1086 	TBool flag 		  = EFalse;
  1087 	
  1088 	TInt pendingIndex =   iPendingIndex[aRequest] ;	
  1089 	
  1090 	switch (aRequest)
  1091 		{		
  1092 	    case RDisplayChannel::EReqGetCompositionBuffer:	
  1093 			{
  1094 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqGetCompositionBuffer request and reason %d\n",aReason );
  1095 			
  1096 	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq )
  1097 				{
  1098 				if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq->IsReady() )
  1099 					{
  1100 		            flag = ETrue;					
  1101 					}
  1102 	        	}
  1103 	        break;											
  1104 			}
  1105 
  1106 		 case RDisplayChannel::EReqWaitForPost:		        
  1107 			{
  1108 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqWaitForPost request and reason %d\n",aReason );
  1109 			
  1110 	 		if(iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq) 
  1111 	    	    {
  1112 	    	    if( iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq->IsReady()  && (iCurrentPostCount >= iRequestedPostCount) )
  1113 	    	    	{
  1114 					flag = ETrue;	    	    	
  1115 	    	    	}
  1116 	            }
  1117 	        break;    												
  1118 			}
  1119  		
  1120 		case RDisplayChannel::EReqPostUserBuffer:	
  1121 			{
  1122 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqPostUserBuffer request and reason %d\n",aReason );
  1123 				
  1124 			if(iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq)
  1125 	    		{
  1126 	    		if( iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq->IsReady() )
  1127 	    			{
  1128 					flag = ETrue;	    			
  1129 	    			}
  1130 	            }
  1131 	        break;			
  1132 			}
  1133 		default:
  1134 			__DEBUG_PRINT("RequestComplete() called for an unknown request\n");
  1135 			return KErrGeneral;
  1136 		
  1137 		}
  1138 		
  1139 	if (flag)
  1140 		{
  1141 		CompleteRequest(iPendingReq[aRequest][pendingIndex].iOwningThread,iPendingReq[aRequest][pendingIndex].iTClientReq,aReason);		
  1142 		}
  1143 				
  1144 	return KErrNone;	
  1145 	}
  1146 
  1147 
  1148 /** 
  1149 Complete an asynchronous request back to the client.
  1150 
  1151 @param aThread     The client thread which issued the request.
  1152 @param aTClientReq Pointer reference to the TClientRequest object  
  1153 @param aReason     The request status code.  
  1154 
  1155 @pre The thread must be in a critical section. 
  1156 */
  1157 void DDisplayLdd::CompleteRequest(DThread* aThread, TClientRequest*& aTClientReq, TInt aReason)
  1158 	{			
  1159 	__DEBUG_PRINT4("Complete aTClientReq %08x with reason %d for aThread = %08x\n", aTClientReq, aReason,aThread );		
  1160 	
  1161 	Kern::QueueRequestComplete(aThread,aTClientReq,aReason);
  1162 		
  1163 	aThread->AsyncClose();	// Asynchronously close our reference on the client thread - don't want to be blocked if this is final reference. 
  1164 				
  1165 	aThread		  =0;
  1166 	aTClientReq   =0;
  1167 	
  1168 #ifdef _DEBUG	
  1169 	__e32_atomic_add_ord32(&iThreadOpenCount, TUint32(-1));
  1170 	__e32_atomic_add_ord32(&iAsyncReqCount,   TUint32(-1));
  1171 #endif	
  1172 			
  1173 	}
  1174 
  1175 
  1176 
  1177 /**
  1178 	static factory function for the LDD.
  1179 	
  1180 	@return pointer to the created (or existing) instance of the class
  1181 */
  1182 DDisplayLdd* DDisplayLdd::CreateInstance()
  1183 	{
  1184 	__DEBUG_PRINT("DDisplayLdd::CreateInstance()\n");
  1185 	 // create LDD channel instance
  1186     DDisplayLdd* obj = new DDisplayLdd();
  1187     return obj;
  1188 	
  1189 	}
  1190 
  1191 
  1192 /************************************************************************************
  1193  *            LDD factory, DDisplayLddFactory class implementation
  1194  ************************************************************************************/
  1195  
  1196 /**
  1197 	Constructor
  1198 */  
  1199 DDisplayLddFactory::DDisplayLddFactory()
  1200 	{
  1201 	__DEBUG_PRINT("DDisplayLddFactory::DDisplayLddFactory() \n");
  1202 	
  1203 	iParseMask 	= KDeviceAllowPhysicalDevice | KDeviceAllowUnit ;
  1204 	
  1205     iVersion	= TVersion( KDisplayChMajorVersionNumber,
  1206                       	    KDisplayChMinorVersionNumber,
  1207                       	    KDisplayChBuildVersionNumber);
  1208                       	    
  1209 	iUnitsOpenMask =0;                      	    
  1210 	}
  1211 
  1212 
  1213 /**
  1214     Destructor
  1215 */
  1216 DDisplayLddFactory::~DDisplayLddFactory()
  1217 	{
  1218 	}
  1219 
  1220 
  1221 /**
  1222 	static factory function for the LDD factory.
  1223 	
  1224 	@return pointer to the created instance of the class
  1225 */
  1226 DDisplayLddFactory* DDisplayLddFactory::CreateInstance()
  1227 
  1228 	{
  1229 	__DEBUG_PRINT("DDisplayLddFactory::CreateInstance() \n");
  1230 	 
  1231 	 DDisplayLddFactory* obj = new DDisplayLddFactory;
  1232     return obj;
  1233 	}
  1234 
  1235 
  1236 /**
  1237     Set our name and return error code
  1238 */
  1239 TInt DDisplayLddFactory::Install()
  1240 
  1241 	{
  1242 	__DEBUG_PRINT("DDisplayLddFactory::Install() \n");
  1243     return SetName(&RDisplayChannel::Name());
  1244 	}
  1245 
  1246 
  1247 void DDisplayLddFactory::GetCaps(TDes8& /*aDes*/) const
  1248 
  1249 	{
  1250 	//No action.
  1251 	}
  1252 
  1253 
  1254 /**
  1255 	LDD factory function. Creates LDD object.
  1256 	
  1257 	@param  aChannel  A pointer to an LDD channel object which will be initialised on return.
  1258 	
  1259 	@return KErrNone  if object successfully allocated, KErrNoMemory if not.			
  1260 */
  1261 TInt DDisplayLddFactory::Create(DLogicalChannelBase*& aChannel)
  1262 	{
  1263 	__DEBUG_PRINT("DDisplayLddFactory::Create \n");
  1264     aChannel = DDisplayLdd::CreateInstance();
  1265     return (!aChannel)? KErrNoMemory : KErrNone;
  1266 	}
  1267 
  1268 
  1269 
  1270 /**
  1271 Check whether a channel is currently open on the specified unit.
  1272 @param aUnit The number of the unit to be checked.
  1273 @return ETrue if a channel is open on the specified channel, EFalse otherwise.
  1274 @pre The unit info. mutex must be held.
  1275 */
  1276 TBool DDisplayLddFactory::IsUnitOpen(TInt aUnit)
  1277 	{
  1278 	return(iUnitsOpenMask&(1<<aUnit));
  1279 	}
  1280 
  1281 
  1282 /**
  1283 Attempt to change the state of the channel open status for a particular channel.
  1284 @param aUnit The number of the unit to be updated.
  1285 @param aIsOpenSetting The required new state for the channel open status: either ETrue to set the status to open or 
  1286 	EFalse to set the status to closed.
  1287 @return KErrNone if the status was updated successfully, KErrInUse if an attempt has been made to set the channnel status
  1288 	to open while it is already open.
  1289 */		
  1290 TInt DDisplayLddFactory::SetUnitOpen(TInt aUnit,TBool aIsOpenSetting)
  1291 	{
  1292 		
  1293 	NKern::FMWait(&iUnitInfoMutex); // Acquire the unit info. mutex.
  1294 		
  1295 	// Fail a request to open an channel that is already open
  1296 	if (aIsOpenSetting && IsUnitOpen(aUnit))
  1297 		{
  1298 		NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
  1299 		return(KErrInUse);
  1300 		}
  1301 	
  1302 	// Update the open status as requested
  1303 	if (aIsOpenSetting)
  1304 		iUnitsOpenMask|=(1<<aUnit);
  1305 	else
  1306 		iUnitsOpenMask&=~(1<<aUnit);
  1307 	
  1308 	NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.	
  1309 	return(KErrNone);
  1310 	}
  1311 
  1312 
  1313 /**
  1314 	"Standard LDD" entrypoint.
  1315 	
  1316 	Is called on CreateLogicalDevice() if the user calls LoadLogicalDevice(). Creates LDD factory.
  1317 	
  1318 	@return pointer to the LDD factory object.
  1319 */
  1320 DECLARE_STANDARD_LDD()
  1321 	{
  1322 	__DEBUG_PRINT("DECLARE_STANDARD_LDD() \n");
  1323      DDisplayLddFactory* pLDDFactory = DDisplayLddFactory::CreateInstance();
  1324     return  pLDDFactory;
  1325 	}
  1326 
  1327 
  1328 
  1329