kernel/eka/drivers/display/display.cpp
changeset 4 56f325a607ea
parent 0 a41df078684a
equal deleted inserted replaced
2:4122176ea935 4:56f325a607ea
     9 // Nokia Corporation - initial contribution.
     9 // Nokia Corporation - initial contribution.
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 // e32\drivers\display\display.cpp  
    14 // os\kernelhwsrv\kernel\eka\drivers\display\display.cpp  
    15 // LDD for a Display driver with GCE support
       
    16 // LDD for a Display driver with GCE support
    15 // LDD for a Display driver with GCE support
    17 // 
    16 // 
    18 //
    17 //
    19 
    18 
    20 /**
    19 /**
    26 
    25 
    27 #include <drivers/display.h>
    26 #include <drivers/display.h>
    28 #include <kernel/kern_priv.h>
    27 #include <kernel/kern_priv.h>
    29 
    28 
    30 
    29 
    31 
    30 const TUint8  KMutexOrder             = 0x3f;
    32 static const char KDisplayLddPanic[]="DISPLAY/GCE LDD";
    31 
       
    32 static const char KDisplayLddPanic[]  ="DISPLAY/GCE LDD";
       
    33 
       
    34 _LIT(KClientRequestMutex, "ClientRequestMutex");
    33 
    35 
    34 
    36 
    35 /************************************************************************************
    37 /************************************************************************************
    36  *            DDisplayLdd LDD class implementation
    38  *            DDisplayLdd LDD class implementation
    37  ************************************************************************************/
    39  ************************************************************************************/
    45     iClient->Open();
    47     iClient->Open();
    46     iCurrentPostCount   = 0;
    48     iCurrentPostCount   = 0;
    47     iRequestedPostCount = 0;
    49     iRequestedPostCount = 0;
    48     iCompositionBuffIdx = 0;
    50     iCompositionBuffIdx = 0;
    49     iUnit				= -1;
    51     iUnit				= -1;
    50     iThreadOpenCount    = 0;	
    52     iThreadOpenCount    = 0;
       
    53     iAsyncReqCount		= 0;
       
    54     iClientRequestMutex = 0;	
    51 	}
    55 	}
    52 
    56 
    53 
    57 
    54 DDisplayLdd::~DDisplayLdd()
    58 DDisplayLdd::~DDisplayLdd()
    55 	{
    59 	{
    56 	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
    60 	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
    57      // cancel outstanding requests
    61      // cancel outstanding requests and destroy the queue of TClientRequest objects
    58     for(TInt k = 0; k < KPendingReqArraySize ; k++)
    62     for(TInt k = 0; k < KPendingReqArraySize ; k++)
    59     	{
    63     	{
    60         if(iPendingReq[k].iStatus)
    64 		for(TInt i = 0; i < KMaxQueuedRequests; i++)
    61         	{
    65 			{
    62      		CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);        	
    66 			//Method IsReady() returns true if the client’s request SetStatus method has been called but the 
    63         	}
    67 			//coresponding QueueRequestComplete method hasn't.			
    64     	}
    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 		}
    65     
    78     
    66     //Close User Buffer chunks not yet destroyed.
    79     //Close User Buffer chunks not yet destroyed.
    67 	for(TInt i = 0; i < KDisplayUBMax; i++)
    80 	for(TInt i = 0; i < KDisplayUBMax; i++)
    68 		{
    81 		{
    69 		if(iUserBuffer[i].iChunk != 0)
    82 		if(iUserBuffer[i].iChunk != 0)
    73 			}
    86 			}
    74 		}
    87 		}
    75     	
    88     	
    76     Kern::SafeClose((DObject*&)iClient, NULL);  
    89     Kern::SafeClose((DObject*&)iClient, NULL);  
    77     
    90     
    78     __ASSERT_DEBUG(iThreadOpenCount==0,Kern::Fault(KDisplayLddPanic,__LINE__)); 
    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__));  
    79     	
    99     	
    80     // Clear the 'units open mask' in the LDD factory.
   100     // Clear the 'units open mask' in the LDD factory.
    81 	if (iUnit>=0)
   101 	if (iUnit>=0)
    82 		((DDisplayLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);	 	
   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
    83 	}
   109 	}
    84  
   110  
    85 
   111 
    86 /**
   112 /**
    87 	LDD second stage constructor
   113 	LDD second stage constructor
    90 	{ 
   116 	{ 
    91 	
   117 	
    92 	__DEBUG_PRINT("DDisplayLdd::DoCreate()\n"); 
   118 	__DEBUG_PRINT("DDisplayLdd::DoCreate()\n"); 
    93 
   119 
    94 	if(    !Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,      __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   120 	if(    !Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,      __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
    95 		&& !Kern::CurrentThreadHasCapability(ECapabilityReadDeviceData, __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   121 		|| !Kern::CurrentThreadHasCapability(ECapabilityReadDeviceData, __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
    96 		&& !Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
   122 		|| !Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
    97 		&& !Kern::CurrentThreadHasCapability(ECapabilityProtServ,       __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") ) )
   123 		|| !Kern::CurrentThreadHasCapability(ECapabilityProtServ,       __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") ) )
    98 		{
   124 		{
    99 		return KErrPermissionDenied;
   125 		return KErrPermissionDenied;
   100 		}
   126 		}
   101 		  
   127 		  
   102 	// Check that the display driver version specified by the client is compatible.
   128 	// Check that the display driver version specified by the client is compatible.
   106 		}
   132 		}
   107 				
   133 				
   108 	// Check that a channel hasn't already been opened on this unit.
   134 	// Check that a channel hasn't already been opened on this unit.
   109 	TInt r=((DDisplayLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
   135 	TInt r=((DDisplayLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
   110 	if (r!=KErrNone)
   136 	if (r!=KErrNone)
   111 		{
       
   112 		return r;
   137 		return r;
   113 		}
   138 	iUnit=aUnit;
   114 				   	       
   139 
   115  	Pdd()->iLdd	= this;
   140  	Pdd()->iLdd	= this;
   116  	
   141  	
   117  	r		= Pdd()->CreateChannelSetup(aUnit); 	
   142  	r		= Pdd()->CreateChannelSetup(aUnit); 	
   118  	if ( r!= KErrNone)
   143  	if ( r!= KErrNone)
   119  		{
   144  		{
   133         iUserBuffer[node].iChunk  	= 0;
   158         iUserBuffer[node].iChunk  	= 0;
   134         iUserBuffer[node].iOffset 	= 0;
   159         iUserBuffer[node].iOffset 	= 0;
   135         iUserBuffer[node].iPendingRequest = 0;
   160         iUserBuffer[node].iPendingRequest = 0;
   136     	}
   161     	}
   137 
   162 
   138     //Initialise pending queue for asynchronous requests
   163     //Initialise pending queue for asynchronous requests and queue of TClientRequests
   139     for(int k = 0; k < KPendingReqArraySize; k++) 
   164     for(TInt k = 0; k < KPendingReqArraySize; k++) 
   140     	{
   165     	{
   141       	iPendingReq[k].iStatus = 0;
   166     	
   142       	iPendingReq[k].iOwningThread = 0;
   167     	iPendingIndex[k]=0;
   143     	}
   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     
   144           
   189           
   145     Pdd()->SetGceMode();	
   190     Pdd()->SetGceMode();	
   146 	SetDfcQ(Pdd()->DfcQ(aUnit));	   
   191 	SetDfcQ(Pdd()->DfcQ(aUnit));	   
   147     iMsgQ.Receive();
   192     iMsgQ.Receive();
   148     
   193     
   149     return KErrNone;		
   194     return KErrNone;		
   150 }
   195 }
   151 
   196 
   152 
   197 
   153 /**
   198 /**
   154  * All driver's client requests (synchronous and asynchronous) are sent as
   199 Override DLogicalChannel::SendMsg to process a client message before and after sending the message 
   155  * kernel messages by generic kernel to logical channel. This function
   200 to the DFC thread for processing by HandleMsg().
   156  * catches messages sent by the generic kernel
   201  
   157  *
   202 This function is called in the context of the client thread.
   158  * @param aMsg KErnel side thread messaging
   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
   159  */ 
   530  */ 
   160 void DDisplayLdd::HandleMsg(TMessageBase* aMsg)
   531 void DDisplayLdd::HandleMsg(TMessageBase* aMsg)
   161 	{
   532 	{
   162     TThreadMessage& m	= *(TThreadMessage*)aMsg ;
   533     TThreadMessage& m	= *(TThreadMessage*)aMsg ;
   163 	TInt id 			= m.iValue ;
   534 	TInt id 			= m.iValue ;
   168     	{
   539     	{
   169     	//Device specific cleanup operations
   540     	//Device specific cleanup operations
   170     	Pdd()->CloseMsg();
   541     	Pdd()->CloseMsg();
   171     	
   542     	
   172         // cancel outstanding requests
   543         // cancel outstanding requests
   173         for(int k = 0; k < KPendingReqArraySize; k++)
   544         for(TInt k = 0; k < KPendingReqArraySize; k++)
   174         	{
   545         	{ 
   175             if(iPendingReq[k].iStatus) 
   546 			for(TInt i = 0; i < KMaxQueuedRequests; i++)
   176             	{
   547 				{
   177             	CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);
   548 	        	if( iPendingReq[k][i].iTClientReq) 
   178             	}
   549 	            	{
       
   550 	            	if(iPendingReq[k][i].iTClientReq->IsReady() )
       
   551 	            		{
       
   552 	            		CompleteRequest(iPendingReq[k][i].iOwningThread,iPendingReq[k][i].iTClientReq,KErrCancel);
       
   553 	            		}            	            		
       
   554 	            	}
       
   555 				}
   179         	}
   556         	}
   180         Pdd()->SetLegacyMode();
   557         Pdd()->SetLegacyMode();
   181 		m.Complete(KErrNone, EFalse);
   558 		m.Complete(KErrNone, EFalse);
   182 		return;
   559 		return;
   183 		}
   560 		}
   191     	return;
   568     	return;
   192 		}
   569 		}
   193     // asynchronous request
   570     // asynchronous request
   194 	else if (id < 0)
   571 	else if (id < 0)
   195 		{
   572 		{
   196 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   573 		//m.Int3() is the index, in the array of pending requests, to be used.
   197 		TInt r = DoRequest(~id,pS,m.Ptr1(),m.Ptr2(), client);
   574 		TInt r = DoRequest(~id,m.Ptr1(),m.Ptr2(),m.Int3(), client);
   198 		m.Complete(r, ETrue);
   575 		m.Complete(r, ETrue);
   199 		}
   576 		}
   200     // synchronous request
   577     // synchronous request
   201 	else
   578 	else
   202 		{
   579 		{
   217 
   594 
   218        switch (aReqNumber)
   595        switch (aReqNumber)
   219 		 {
   596 		 {
   220 		 case RDisplayChannel::ECtrlCancelGetCompositionBuffer:
   597 		 case RDisplayChannel::ECtrlCancelGetCompositionBuffer:
   221 		 case RDisplayChannel::ECtrlCancelPostUserBuffer:
   598 		 case RDisplayChannel::ECtrlCancelPostUserBuffer:
   222 		 case RDisplayChannel::ECtrlCancelWaitForPost:
   599 		 case RDisplayChannel::ECtrlCancelWaitForPost:		 
   223 	        if(iPendingReq[aReqNumber].iStatus)
   600 			TInt pendingIndex = iPendingIndex[aReqNumber];
       
   601 	        if(iPendingReq[aReqNumber][pendingIndex].iTClientReq)
   224 	        	{
   602 	        	{
   225         		CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
   603 	        	if( iPendingReq[aReqNumber][pendingIndex].iTClientReq->IsReady() )
   226         		
   604 	        		{
   227         		iPendingReq[aReqNumber].iStatus 	  = 0;
   605 	        		CompleteRequest(iPendingReq[aReqNumber][pendingIndex].iOwningThread,iPendingReq[aReqNumber][pendingIndex].iTClientReq,KErrCancel);
   228         		iPendingReq[aReqNumber].iOwningThread = 0;
   606 	        		}
   229             	}
   607             	}
   230 			break;
   608 			break;
   231 		}	
   609 		}	
   232 	
   610 	
   233 	}
   611 	}
   234 
   612 
   235 /**
   613 /**
   236 	Asynchronous request processing.
   614 	Asynchronous request processing.
   237 	
   615 	
   238 	@param aFunction    request function number
   616     @param aFunction    	Request function number
   239     @param apRqStat     pointer to the user's request status object.
   617     @param apArg1       	Pointer to kernel message argument 1.
   240     @param apArg1       pointer to the 1st parameter
   618     @param apArg2       	Pointer to kernel message argument 2.
   241     @param apArg2       pointer to the 2nd parameter
   619     @param aPendingIndex    Index pointing to the appropriate TClientRequest object to use.
   242 	
   620 	@param aClient			Pointer to the client thread that issued the asynchronous request.
   243 	@return request scheduling result, system-wide error code.
   621 	
   244 */
   622     @return request scheduling result, system-wide error code.
   245 TInt DDisplayLdd::DoRequest(TInt aReqNumber, TRequestStatus* aRqStat, TAny* aArg1, TAny* aArg2, DThread* aClient)
   623 */
       
   624 TInt DDisplayLdd::DoRequest(TInt aReqNumber, TAny* aArg1, TAny* aArg2, TInt aPendingIndex, DThread* aClient)
   246 	{	
   625 	{	
   247     TUint count;
   626 
   248     TInt pack[2];
   627     TInt pack[2];
   249     TInt r 				= KErrNone;
   628     TInt r 				= KErrNone;
   250     TBufferNode* node 	= 0;
   629     TBufferNode* node 	= 0;
   251     TInt buffer_id  	= 0;
   630     TInt buffer_id  	= 0;   
   252         
   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     
   253     // 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.
   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.
   254 	r=aClient->Open();
   639 	r=aClient->Open();
   255 	__ASSERT_ALWAYS(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));
   640 	__ASSERT_ALWAYS(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));
   256 #ifdef _DEBUG
   641 #ifdef _DEBUG
   257 	__e32_atomic_add_ord32(&iThreadOpenCount, 1);
   642 	__e32_atomic_add_ord32(&iThreadOpenCount, 1);
   258 #endif	
   643 #endif	
   259     
   644     	
   260     // check if this request is valid
   645 	for(TInt i = 0; i < KMaxQueuedRequests; i++)
   261     if(aReqNumber >= 0 && aReqNumber <= RDisplayChannel::EReqWaitForPost)
   646 		{
   262     	{
   647 		//Don't cancel the asyncrhonous request we currently process.
       
   648 		if (i == aPendingIndex)
       
   649 			{
       
   650 			continue;
       
   651 			}
   263         // cancel outstanding request
   652         // cancel outstanding request
   264         if(iPendingReq[aReqNumber].iStatus)
   653         if(iPendingReq[aReqNumber][i].iTClientReq)        
   265 			{
   654 			{
   266             CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
   655 			//If IsReady() returns true, setStatus has been called for that TCientRequest but QueueRequestComplete hasn't. 
   267             iPendingReq[aReqNumber].iStatus 	  = 0;
   656 			//In that case we want to cancel this outstanding request. Given that all QueueRequestComplete calls execute 
   268             iPendingReq[aReqNumber].iOwningThread = 0;
   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 				}
   269         	}
   663         	}
   270         	
       
   271     	// store request and client
       
   272     	iPendingReq[aReqNumber].iStatus = aRqStat;
       
   273     	iPendingReq[aReqNumber].iOwningThread = aClient;
       
   274     	}
   664     	}
   275 
   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   
   276     switch (aReqNumber)
   674     switch (aReqNumber)
   277 		{
   675 		{
   278 	     case RDisplayChannel::EReqGetCompositionBuffer:
   676 	     case RDisplayChannel::EReqGetCompositionBuffer:		//DFC thread updates a value the client thread should read.
   279 
   677 			 { 
   280 			if(aArg1 == 0 )
   678 			 configBufferIdx = (TInt*) aArg1;
   281 	              {
   679 		 
   282 	               r = KErrGeneral;
   680 	          TInt  index;
   283 	               CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
   681 			  TBool found = EFalse;
   284 	               iPendingReq[aReqNumber].iStatus 		 = 0;
   682 			  
   285 	               iPendingReq[aReqNumber].iOwningThread = 0;
   683 			  for(index = 0; index < (TInt) iDisplayInfo.iNumCompositionBuffers; index++)
   286 	              }			
   684 					{
   287 			else
   685 					if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
   288             	  {	 	
   686 						{
   289 	              TInt  index;
   687 						__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
   290 	              TBool found = EFalse;
   688 
   291 	              
   689 						 iCompositionBuffIdx = index;
   292 	              for(index =0; index< KDisplayCBMax; index++)
   690 						 *configBufferIdx = iCompositionBuffIdx;
   293 		              	{
   691 						 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
   294 		              	if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
   692 						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread,iPendingReq[aReqNumber][aPendingIndex].iTClientReq,r);
   295 							{
   693 						 found = ETrue;
   296 							__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
   694 						 break;
   297 
   695 						 }
   298 			                 iCompositionBuffIdx = index;
   696 					}				
   299 			                 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
   697 			  if(!found)  	//There are no free buffers schedule request for completion
   300 							 if ( r == KErrNone)
   698 					{	
   301 								{   
   699 					//Case of a single composition buffer. 
   302 								 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
   700 					if (iDisplayInfo.iNumCompositionBuffers == 1)
   303 								 CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
   701 						{
   304 								 iPendingReq[aReqNumber].iStatus 	   = 0;
   702 						iCompositionBuffIdx = 0;
   305 								 iPendingReq[aReqNumber].iOwningThread = 0;
   703 						 *configBufferIdx = iCompositionBuffIdx;							 
   306 								 found = ETrue;
   704 						 CompleteRequest(iPendingReq[aReqNumber][aPendingIndex].iOwningThread, iPendingReq[aReqNumber][aPendingIndex].iTClientReq, r);
   307 								 break;
   705 						 __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
   308 								}
   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;
   309 							 }
   718 							 }
   310 		              	}				
   719 						 }
   311 				  if(!found)  	//There are no free buffers schedule request for completion
   720 					}			 	 			            
   312 					 	{	
   721           	
   313 						//Case of a single composition buffer. 
   722 			  break;
   314 						if (iDisplayInfo.iNumCompositionBuffers == 1)
   723 			  }
   315 							{
   724 
   316 							iCompositionBuffIdx = 0;
   725          case RDisplayChannel::EReqPostUserBuffer:		//DFC thread should read client message data and update a value the client will read.	                                            
   317 			             	 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
   726             configPack = (TInt*) aArg1;
   318 		                     __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
   727             pack[0] = *configPack; 
   319 		                     break;													
   728             configPack++;           
   320 							}
   729             pack[1] = *configPack;
   321 								
   730 			
   322 				 	 
   731 			r = KErrArgument;
   323 		              	for( index=0; index< KDisplayCBMax; index++)
   732             buffer_id = pack[0];
   324 			                 {
   733             if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
   325 			                 if(iCompositionBuffer[index].iState == EBufferActive)
   734              	{
   326 								 {	
   735                 node = FindUserBufferNode(buffer_id);
   327 		                         iCompositionBuffIdx = index;
   736                 if(node  && (!(node->iFree) && node->iChunk ) ) 
   328 			                  	 r = Kern::ThreadRawWrite(aClient, aArg1,&iCompositionBuffIdx, sizeof(TInt), aClient);
   737                 	{
   329 			                     __DEBUG_PRINT2("EReqGetCompositionBuffer  No composition buffer available. Next available is iCompositionBuffIdx  %d.\n",iCompositionBuffIdx );
   738                   	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
   330 			                     break;
   739                   	r = Pdd()->PostUserBuffer(node);
   331 								 }
   740                   	if(r == KErrNone)
   332 			                 }
   741 	                  	 {
   333 				 	 	}			 	 		
   742 	                  	 postCount = (RDisplayChannel::TPostCount*) aArg2;
   334 	            }
   743 	     		    	 ++iCurrentPostCount;
   335           	break;
   744 	                	 *postCount= iCurrentPostCount;	                	 
   336 
   745 	           		     break;
   337          case RDisplayChannel::EReqPostUserBuffer:			
   746 	                  	 }
   338             r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
   747                 	}
   339 			if ( r == KErrNone)
   748              	}
   340 				{
   749             RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
   341 				r = KErrArgument;
   750 
   342 	            buffer_id = pack[0];
       
   343 	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
       
   344 	             	{
       
   345 	                node = FindUserBufferNode(buffer_id);
       
   346 	                if(node  && (!(node->iFree) && node->iChunk ) ) 
       
   347 	                	{
       
   348 	                  	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
       
   349 	                  	r = Pdd()->PostUserBuffer(node);
       
   350 	                  	if(r == KErrNone)
       
   351 		                  	 {
       
   352 		     		    	 ++iCurrentPostCount;
       
   353 		                	 r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);	           		     
       
   354 		           		     break;
       
   355 		                  	 }
       
   356 	                	}
       
   357 	             	}
       
   358 	            RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
       
   359 				}
       
   360             break; 	        
   751             break; 	        
   361 
   752 
   362          case RDisplayChannel::EReqWaitForPost:
   753          case RDisplayChannel::EReqWaitForPost:			 	//DFC thread should read client message data.
   363             r= Kern::ThreadRawRead(aClient, aArg1,  &count, sizeof(RDisplayChannel::TPostCount));
   754 			postCount = (RDisplayChannel::TPostCount*) aArg1;
   364 			if ( r == KErrNone)
   755 			iRequestedPostCount = *postCount;
   365 				{   
   756 									
   366 			    iRequestedPostCount = count;
   757 			//Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
   367 	    	    //Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
   758 			if( ! Pdd()->PostPending() )
   368 	    	    if( ! Pdd()->PostPending() )
   759 				 {
   369 	    	    	 {
   760 				 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
   370 	    	    	 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
   761 				 } 					 
   371 	    	    	 } 
       
   372 				}	 
       
   373          	break;
   762          	break;
   374 
   763 
   375         default:
   764         default:
   376 			r = KErrNotSupported;
   765 			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
   377 			break;
       
   378 		}
   766 		}
   379     return r;	
   767     return r;	
   380 	}
   768 	}
   381 
   769 
   382 
   770 
   383 /**
   771 /**
   384 	Synchronous requests processing.
   772 	Synchronous requests processing.
   385 	
   773 	
   386 	@param aFunction    request function number,
   774 	@param aFunction    Request function number,
   387 	@param apArg1       pointer to the 1st parameter
   775 	@param apArg1       Pointer to kernel message argument 0.
   388 	@param apArg2       pointer to the 2n parameter
   776 	@param apArg2       Pointer to kernel message argument 1.
       
   777 	@param aClient		Pointer to the client thread that issued the synchronous request.
   389     
   778     
   390     @return request processing result
   779     @return request processing result
   391 */
   780 */
   392 TInt DDisplayLdd::DoControl(TInt aFunction, TAny* aArg1, TAny* aArg2, DThread* aClient)
   781 TInt DDisplayLdd::DoControl(TInt aFunction, TAny* aArg1, TAny* aArg2, DThread* aClient)
   393  {
   782  {
   394 	TInt r 			  = KErrNotSupported;
   783 	TInt r 			  = KErrNone;
   395     TBool changedRot  = ETrue;
   784     TBool changedRot  = ETrue;
   396     TBufferNode* node = 0;
   785     TBufferNode* node = 0;
   397 	TInt buffer_id;
   786 	TInt buffer_id;
   398     TInt pack[2]      = {0,0};
   787     TInt pack[2]      = {0,0};
   399     TInt handle, offset;
   788     TInt handle, offset;
   400     TInt index        = 0;
   789     TInt index        = 0;
   401 
   790 	
   402     TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);
   791 	RDisplayChannel::TPostCount 		*postCount ;
   403 
   792 	RDisplayChannel::TDisplayRotation   *rotation; 
       
   793 	
       
   794 	TInt	*configPack; 
       
   795 	TInt	*bufferId; 	
       
   796 	
       
   797 	TBool   *rotationChanged;
       
   798 	TInt    *idx;
       
   799 	
   404     switch (aFunction)
   800     switch (aFunction)
   405 		{
   801 		{
   406 	    case RDisplayChannel::ECtrlGetDisplayInfo:
   802 	    case RDisplayChannel::ECtrlPostCompositionBuffer: 	//DFC thread updates a value the client thread should read.
   407             r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&pckgInfo, sizeof(pckgInfo), aClient);
   803 			postCount = (RDisplayChannel::TPostCount*) aArg2;		
   408     	    break;
   804 					
   409 
       
   410 	    case RDisplayChannel::ECtrlPostCompositionBuffer:
       
   411 	        node =  &iCompositionBuffer[iCompositionBuffIdx];
   805 	        node =  &iCompositionBuffer[iCompositionBuffIdx];
   412             r = Pdd()->PostCompositionBuffer(node);
   806             r = Pdd()->PostCompositionBuffer(node);
   413 		    if(r == KErrNone)
   807 		    if(r == KErrNone)
   414 		    	{
   808 		    	{
   415     		    ++iCurrentPostCount;
   809     		    ++iCurrentPostCount;
   416                 r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);
   810     			*postCount = iCurrentPostCount;
   417     			}
   811 				}
   418             else 
   812             else 
   419             	{
   813             	{
   420             	r = KErrGeneral;	
   814             	r = KErrGeneral;	
   421             	}            	    	            	
   815             	}            	    	            	
   422 			break;
   816 			break;
   423 
   817 
   424         case RDisplayChannel::ECtrlPostLegacyBuffer:
   818         case RDisplayChannel::ECtrlPostLegacyBuffer:		//DFC thread updates a value the client thread should read.
       
   819 			postCount = (RDisplayChannel::TPostCount*) aArg2;
   425             r= Pdd()->PostLegacyBuffer();
   820             r= Pdd()->PostLegacyBuffer();
   426             if ( r == KErrNone)
   821             if ( r == KErrNone)
   427             	{
   822             	{
   428              	++iCurrentPostCount;
   823              	++iCurrentPostCount;         	
   429             	r = Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);           	
   824             	*postCount = iCurrentPostCount;
   430             	}            
   825 				}            
   431 			break;
   826 			break;
   432 
   827 
   433 	    case RDisplayChannel::ECtrlRegisterUserBuffer:
   828 	    case RDisplayChannel::ECtrlRegisterUserBuffer:	//DFC thread should read client message data and update a value the client will read.
   434             node = FindUserBufferNode(0);
   829             node = FindUserBufferNode(0);
   435 			if(node)
   830 			if(node)
   436 				{
   831 				{					                         
   437                 r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
   832                 configPack = (TInt*) aArg1;
   438 				if(r == KErrNone)
   833                 handle 	   = *configPack;
   439 					{
   834                 configPack++;
   440 	                handle  = pack[0]; 
   835                 offset     = *configPack;                               
   441 	                offset  = pack[1];
   836                 r 	       = CheckAndOpenUserBuffer(node, handle, offset, aClient);
   442 	                r 		= CheckAndOpenUserBuffer(node, handle, offset, aClient);
   837                 
   443 	                
   838                 if(r == KErrNone)
   444 	                if(r == KErrNone)
   839                 	{
   445 	                	{
   840                 	bufferId  = (TInt*) aArg2;
   446 	                     r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&node->iBufferId, sizeof(TInt), aClient);
   841                 	*bufferId = node->iBufferId;
   447 	                	}
   842                 	}					
   448 					}
       
   449 				}
   843 				}
   450             else
   844             else
   451             	{
   845             	{
   452     			r = KErrTooBig;
   846     			r = KErrTooBig;
   453             	}
   847             	}
   454 			break;
   848 			break;
   455 
   849 
   456 	    case RDisplayChannel::ECtrlDeregisterUserBuffer:
   850 	    case RDisplayChannel::ECtrlDeregisterUserBuffer:	//DFC thread should read client message data.
   457             r= Kern::ThreadRawRead(aClient, aArg1, &buffer_id, sizeof(TInt));
   851             bufferId  = (TInt*) aArg1;
   458             if ( r == KErrNone)
   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)
   459 				{
   910 				{
   460 				r = KErrArgument;          
   911 				pack[0] 	= r;
   461 	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
   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
   462 	            	{
   956 	            	{
   463 		            node = FindUserBufferNode(buffer_id);	            
   957 	                Kern::ChunkClose(iChunk);
   464 		            if(node  && (!(node->iFree) && node->iChunk ) ) 
   958 	                iChunk = NULL;
   465 		            	{	                
       
   466 		                if(node->iState==EBufferFree  || node->iState==EBufferCompose )
       
   467 		                	{
       
   468 		                	r = FreeUserBufferNode(node);	                	
       
   469 		                	}
       
   470 		                else
       
   471 		                	{
       
   472 		                	r = KErrInUse;
       
   473 		                	}
       
   474 		            	}               	                                    
       
   475 	            	}
   959 	            	}
   476 				}
   960 	            }
   477 			break;
   961 
   478 
   962 	        break;
   479 	    case RDisplayChannel::ECtrlPostCount:
   963 	        }
   480             r= Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentPostCount, sizeof(TUint), aClient);
   964 #endif // _DEBUG
   481 			break;
   965 
   482 
   966 	    default:
   483 	    case RDisplayChannel::ECtrlSetRotation:	    
   967 			__NK_ASSERT_ALWAYS(EFalse);  // we already validated the request number
   484 	    	{	    			    
       
   485             RDisplayChannel::TDisplayRotation rot;
       
   486             TInt previousRot = iCurrentRotation;
       
   487             r= Kern::ThreadRawRead(aClient, aArg1, &rot, sizeof(RDisplayChannel::TDisplayRotation));
       
   488             if ( r == KErrNone)
       
   489 				{               	
       
   490                 r = Pdd()->SetRotation((TInt)rot);                  
       
   491                 changedRot=(previousRot!=iCurrentRotation);              
       
   492                 if( r == KErrNone)
       
   493         	        {
       
   494                    	 r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&changedRot, sizeof(TBool), aClient);                       
       
   495                	    }
       
   496 				}
       
   497 	    	}
       
   498     	    break;
       
   499 
       
   500 	    case RDisplayChannel::ECtrlCurrentRotation:
       
   501 			r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentRotation, sizeof(RDisplayChannel::TDisplayRotation), aClient);
       
   502 			break;
       
   503 
       
   504 	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:
       
   505     	    {
       
   506             r= Kern::ThreadRawRead(aClient, aArg1, &index, sizeof(TInt));                     
       
   507             if ( r == KErrNone)
       
   508 				{   
       
   509 				if( (index >= KDisplayCBMax ) || (index < 0 ) )
       
   510 	            	{
       
   511 	            	r = KErrArgument;
       
   512 	            	break;	
       
   513 	            	}
       
   514 				r = Kern::MakeHandleAndOpen(aClient, iCompositionBuffer[index].iChunk);
       
   515 
       
   516 				if(r >= KErrNone)
       
   517 					{
       
   518 					pack[0] = r;
       
   519 					pack[1] = iCompositionBuffer[index].iOffset;
       
   520 					r=Kern::ThreadRawWrite(aClient, aArg2, &pack, (sizeof(TInt)*2), aClient);
       
   521 					}
       
   522 				}	
       
   523 		 	break;
       
   524 			}
       
   525     	   
       
   526         default:
       
   527 			r = KErrNotSupported;
       
   528 			break;
       
   529 		};
   968 		};
   530     return r;	
   969     return r;	
   531 	}
   970 	}
   532 
   971 
   533 
   972 
   549 	
   988 	
   550   NKern::ThreadEnterCS();
   989   NKern::ThreadEnterCS();
   551   chunk = Kern::OpenSharedChunk(aClient, aHandle, EFalse);
   990   chunk = Kern::OpenSharedChunk(aClient, aHandle, EFalse);
   552   NKern::ThreadLeaveCS();
   991   NKern::ThreadLeaveCS();
   553   if(chunk)
   992   if(chunk)
   554 		{
   993     	{                            
       
   994 		
   555 		// Using iOffsetBetweenLines rather than iWidth as the controller may be using stride
   995 		// Using iOffsetBetweenLines rather than iWidth as the controller may be using stride
   556 		size = iDisplayInfo.iNormal.iOffsetBetweenLines * iDisplayInfo.iNormal.iHeight;
   996 		size = iDisplayInfo.iNormal.iOffsetBetweenLines * iDisplayInfo.iNormal.iHeight;
   557                 
   997                 
   558         r = Kern::ChunkPhysicalAddress(chunk, aOffset, size, kernelAddress, mapAttr, physicalAddress, physicalPageList);
   998         r = Kern::ChunkPhysicalAddress(chunk, aOffset, size, kernelAddress, mapAttr, physicalAddress, physicalPageList);
   559         if( r == KErrNone )
   999         if( r == KErrNone )
   635     return r;
  1075     return r;
   636 	}	
  1076 	}	
   637 
  1077 
   638 
  1078 
   639 /**    
  1079 /**    
   640    Calls CompleteRequest( which internally sends a Kern::RequestComplete message )for the specified request and with the reason passed, 
  1080    Calls CompleteRequest( which internally calls Kern::QueueRequestComplete )for the specified request and with the reason passed, 
   641    in case such an asynchronous request is pending. Also resets the pending queue fields for that request if it was actually pending. 
  1081    in case such an asynchronous request is pending.  Called by both the LDD and PDD.
   642    Called by both the LDD and PDD.
       
   643    
  1082    
   644 */ 
  1083 */ 
   645 TInt DDisplayLdd::RequestComplete(TInt aRequest, TInt aReason)
  1084 TInt DDisplayLdd::RequestComplete(TInt aRequest, TInt aReason)
   646 	{
  1085 	{
   647 	TBool flag = EFalse;
  1086 	TBool flag 		  = EFalse;
   648 			
  1087 	
       
  1088 	TInt pendingIndex =   iPendingIndex[aRequest] ;	
       
  1089 	
   649 	switch (aRequest)
  1090 	switch (aRequest)
   650 		{
  1091 		{		
   651 	    case RDisplayChannel::EReqGetCompositionBuffer:	
  1092 	    case RDisplayChannel::EReqGetCompositionBuffer:	
   652 			{
  1093 			{
   653 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqGetCompositionBuffer request and reason %d\n",aReason );
  1094 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqGetCompositionBuffer request and reason %d\n",aReason );
   654 			
  1095 			
   655 	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus)
  1096 	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq )
   656 				{
  1097 				{
   657 				__DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqGetCompositionBuffer \n");
  1098 				if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer][pendingIndex].iTClientReq->IsReady() )
   658 	            flag = ETrue;
  1099 					{
       
  1100 		            flag = ETrue;					
       
  1101 					}
   659 	        	}
  1102 	        	}
   660 	        break;											
  1103 	        break;											
   661 			}
  1104 			}
   662 
  1105 
   663 		 case RDisplayChannel::EReqWaitForPost:		        
  1106 		 case RDisplayChannel::EReqWaitForPost:		        
   664 			{
  1107 			{
   665 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqWaitForPost request and reason %d\n",aReason );
  1108 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqWaitForPost request and reason %d\n",aReason );
   666 			
  1109 			
   667 	 		if((iPendingReq[RDisplayChannel::EReqWaitForPost].iStatus != 0) && (iCurrentPostCount >= iRequestedPostCount) )
  1110 	 		if(iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq) 
   668 	    	    {
  1111 	    	    {
   669 	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqWaitForPost \n");
  1112 	    	    if( iPendingReq[RDisplayChannel::EReqWaitForPost][pendingIndex].iTClientReq->IsReady()  && (iCurrentPostCount >= iRequestedPostCount) )
   670 				flag = ETrue;
  1113 	    	    	{
       
  1114 					flag = ETrue;	    	    	
       
  1115 	    	    	}
   671 	            }
  1116 	            }
   672 	        break;    												
  1117 	        break;    												
   673 			}
  1118 			}
   674  		
  1119  		
   675 		case RDisplayChannel::EReqPostUserBuffer:	
  1120 		case RDisplayChannel::EReqPostUserBuffer:	
   676 			{
  1121 			{
   677 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqPostUserBuffer request and reason %d\n",aReason );
  1122 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqPostUserBuffer request and reason %d\n",aReason );
   678 				
  1123 				
   679 			if((iPendingReq[RDisplayChannel::EReqPostUserBuffer].iStatus != 0) )
  1124 			if(iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq)
   680 	    		{
  1125 	    		{
   681 	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqPostUserBuffer \n");
  1126 	    		if( iPendingReq[RDisplayChannel::EReqPostUserBuffer][pendingIndex].iTClientReq->IsReady() )
   682 				flag = ETrue;
  1127 	    			{
       
  1128 					flag = ETrue;	    			
       
  1129 	    			}
   683 	            }
  1130 	            }
   684 	        break;			
  1131 	        break;			
   685 			}
  1132 			}
   686 		default:
  1133 		default:
   687 			__DEBUG_PRINT("RequestComplete() called for an unknown request\n");
  1134 			__DEBUG_PRINT("RequestComplete() called for an unknown request\n");
   689 		
  1136 		
   690 		}
  1137 		}
   691 		
  1138 		
   692 	if (flag)
  1139 	if (flag)
   693 		{
  1140 		{
   694 		CompleteRequest(iPendingReq[aRequest].iOwningThread,iPendingReq[aRequest].iStatus,aReason);
  1141 		CompleteRequest(iPendingReq[aRequest][pendingIndex].iOwningThread,iPendingReq[aRequest][pendingIndex].iTClientReq,aReason);		
   695 		iPendingReq[aRequest].iStatus 		= 0;
       
   696 		iPendingReq[aRequest].iOwningThread = 0;			
       
   697 		}
  1142 		}
   698 				
  1143 				
   699 	return KErrNone;	
  1144 	return KErrNone;	
   700 	}
  1145 	}
   701 
  1146 
   702 
  1147 
   703 /** 
  1148 /** 
   704 Complete an asynchronous request back to the client.
  1149 Complete an asynchronous request back to the client.
   705 @param aThread The client thread which issued the request.
  1150 
   706 @param aStatus The TRequestStatus instance that will receive the request status code. 
  1151 @param aThread     The client thread which issued the request.
   707 @param aReason The request status code.  
  1152 @param aTClientReq Pointer reference to the TClientRequest object  
       
  1153 @param aReason     The request status code.  
       
  1154 
   708 @pre The thread must be in a critical section. 
  1155 @pre The thread must be in a critical section. 
   709 */
  1156 */
   710 void DDisplayLdd::CompleteRequest(DThread* aThread, TRequestStatus*& aStatus, TInt aReason)
  1157 void DDisplayLdd::CompleteRequest(DThread* aThread, TClientRequest*& aTClientReq, TInt aReason)
   711 	{		
  1158 	{			
   712 	Kern::RequestComplete(aThread,aStatus,aReason);		// Complete the request back to the client.
  1159 	__DEBUG_PRINT4("Complete aTClientReq %08x with reason %d for aThread = %08x\n", aTClientReq, aReason,aThread );		
   713 	
  1160 	
       
  1161 	Kern::QueueRequestComplete(aThread,aTClientReq,aReason);
       
  1162 		
   714 	aThread->AsyncClose();	// Asynchronously close our reference on the client thread - don't want to be blocked if this is final reference. 
  1163 	aThread->AsyncClose();	// Asynchronously close our reference on the client thread - don't want to be blocked if this is final reference. 
   715 
  1164 				
       
  1165 	aThread		  =0;
       
  1166 	aTClientReq   =0;
       
  1167 	
   716 #ifdef _DEBUG	
  1168 #ifdef _DEBUG	
   717 	__e32_atomic_add_ord32(&iThreadOpenCount, TUint32(-1));
  1169 	__e32_atomic_add_ord32(&iThreadOpenCount, TUint32(-1));
       
  1170 	__e32_atomic_add_ord32(&iAsyncReqCount,   TUint32(-1));
   718 #endif	
  1171 #endif	
   719 			
  1172 			
   720 	}
  1173 	}
   721 
  1174 
   722 
  1175