os/kernelhwsrv/kernel/eka/drivers/resourceman/rescontrol_export.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\drivers\resourceman\rescontrol_export.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <drivers/resourcecontrol.h>
sl@0
    19
sl@0
    20
#ifdef DEBUG_VERSION
sl@0
    21
#define GET_CRITICAL_SECTION_COUNT(thread)				\
sl@0
    22
	TInt CsCount = thread.iNThread.iCsCount;
sl@0
    23
sl@0
    24
#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)			\
sl@0
    25
	if(thread.iNThread.iCsCount != CsCount)						\
sl@0
    26
		Kern::Fault("PowerResourceController", __LINE__);		\
sl@0
    27
	if(pRC->iResourceMutex->iHoldCount != 0)					\
sl@0
    28
		Kern::Fault("PowerResourceController", __LINE__);	
sl@0
    29
#else
sl@0
    30
#define GET_CRITICAL_SECTION_COUNT(thread)
sl@0
    31
#define LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
sl@0
    32
#endif
sl@0
    33
sl@0
    34
/**
sl@0
    35
	@publishedPartner
sl@0
    36
	@prototype 9.5
sl@0
    37
	Kernel extension or variants can call this API to set the post bool value without registering
sl@0
    38
	as client with the resource controller. This can be used by the resource controller PSL to set the
sl@0
    39
	specified static resources to appropriate value before resource controller is fully initialized.
sl@0
    40
	@param aResId ID of the resource whose level should be set after initialisation
sl@0
    41
	@param aLevel Resource level to set
sl@0
    42
	@return KErrNone, if operation is success
sl@0
    43
			KErrNotFound, if resource ID could not be found in the static resource array.
sl@0
    44
			KErrNotSupported, if this API is called after resource controller is fully initialized
sl@0
    45
	*/
sl@0
    46
EXPORT_C TInt DPowerResourceController::PostBootLevel(TUint aResId, TInt aLevel)
sl@0
    47
	{
sl@0
    48
#ifdef DEBUG_VERSION
sl@0
    49
	DThread& thread = Kern::CurrentThread();
sl@0
    50
	GET_CRITICAL_SECTION_COUNT(thread)
sl@0
    51
#endif
sl@0
    52
    __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::PostBootLevel, aResId = 0x%x, aLevel = %d", 
sl@0
    53
	                                                                          aResId, aLevel));
sl@0
    54
    DPowerResourceController* pRC = TInterface::GetPowerResourceController();
sl@0
    55
	if(!pRC)
sl@0
    56
		return KErrNotFound;
sl@0
    57
	pRC->Lock();
sl@0
    58
    CHECK_CONTEXT(thread)
sl@0
    59
	//Accept the postboot level only if issued before controller is fully initialised.
sl@0
    60
	if(pRC->iInitialised == EResConStartupCompleted)
sl@0
    61
		{
sl@0
    62
		pRC->UnLock();
sl@0
    63
		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
sl@0
    64
		return KErrNotSupported;
sl@0
    65
		}	
sl@0
    66
#ifndef PRM_ENABLE_EXTENDED_VERSION
sl@0
    67
    // coverity[deref_ptr]
sl@0
    68
    // aResId is checked to be more than the array entries before dereferencing pRC->iStaticResourceArray
sl@0
    69
	if((!aResId) || (aResId > pRC->iStaticResourceArrayEntries) || (!pRC->iStaticResourceArray[aResId-1]))
sl@0
    70
		{
sl@0
    71
		pRC->UnLock();
sl@0
    72
		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
sl@0
    73
		return KErrNotFound;
sl@0
    74
		}
sl@0
    75
#else
sl@0
    76
	if(!aResId || ((aResId & KIdMaskResourceWithDependencies) && ((aResId & ID_INDEX_BIT_MASK) > pRC->iStaticResDependencyCount)) 
sl@0
    77
				|| (!(aResId & KIdMaskResourceWithDependencies) && ((aResId > pRC->iStaticResourceArrayEntries)
sl@0
    78
				|| (!pRC->iStaticResourceArray[aResId-1]))))
sl@0
    79
		{
sl@0
    80
		pRC->UnLock();
sl@0
    81
		LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
sl@0
    82
		return KErrNotFound;
sl@0
    83
		}
sl@0
    84
	if(aResId & KIdMaskResourceWithDependencies)
sl@0
    85
		{
sl@0
    86
		aResId &= ID_INDEX_BIT_MASK;
sl@0
    87
		DStaticPowerResource* pR = pRC->iStaticResDependencyArray[--aResId];
sl@0
    88
		pR->iPostBootLevel=aLevel;
sl@0
    89
		pR->iFlags |= SET_VALID_POST_BOOT_LEVEL;
sl@0
    90
		}
sl@0
    91
	else
sl@0
    92
#endif
sl@0
    93
    if(pRC->iStaticResourceArray) 
sl@0
    94
		{
sl@0
    95
		DStaticPowerResource* pR=pRC->iStaticResourceArray[--aResId];
sl@0
    96
		pR->iPostBootLevel=aLevel;
sl@0
    97
		pR->iFlags |= SET_VALID_POST_BOOT_LEVEL; // To indicate valid post boot level is set.
sl@0
    98
		}
sl@0
    99
	pRC->UnLock();
sl@0
   100
	LOCK_AND_CRITICAL_SECTION_COUNT_CHECK(thread)
sl@0
   101
	return KErrNone;
sl@0
   102
    }
sl@0
   103
sl@0
   104
/** 
sl@0
   105
	@publishedPartner
sl@0
   106
	@prototype 9.5
sl@0
   107
	Kernel extensions or variants can call this API to register the static resources before resource controller
sl@0
   108
	is fully initialised.
sl@0
   109
	@Param aClientId             ID of the client that is requesting resource registration
sl@0
   110
	@Param aStaticResourceArray  Static resources to register with RC. 
sl@0
   111
	@Param aResCount             Number of static resources to register with RC. This equals the size of the passed array.
sl@0
   112
	@return KErrNone, if operation is success
sl@0
   113
	        KErrAccessDenied if clientId could not be found in the current list of registered clients or if this
sl@0
   114
			                 client was registered as thread relative and was not called from the same thread.
sl@0
   115
			KErrNotSupported if called after resource controller is fully initialised or if called from user side proxy
sl@0
   116
			                 or if the resource is dynamic or dependency resource.
sl@0
   117
			KErrNoMemory     if there is insufficient memory.
sl@0
   118
			KErrArgument     if passed array is null or passed number of resources count is 0.
sl@0
   119
	*/
sl@0
   120
EXPORT_C TInt DPowerResourceController::RegisterArrayOfStaticResources(TUint aClientId, DStaticPowerResource**& aStaticResourceArray, TUint aResCount)
sl@0
   121
	{
sl@0
   122
	DThread& thread = Kern::CurrentThread();
sl@0
   123
	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterStaticResource"));
sl@0
   124
    DPowerResourceController* pRC = TInterface::GetPowerResourceController();
sl@0
   125
	if(!pRC)
sl@0
   126
		return KErrNotFound;
sl@0
   127
sl@0
   128
	if(!aStaticResourceArray || (aResCount == 0))
sl@0
   129
		return KErrArgument;
sl@0
   130
    CHECK_CONTEXT(thread)
sl@0
   131
	//Accept the registration of static resource only if issued before controller is fully initialised.
sl@0
   132
	if(pRC->iInitialised == EResConStartupCompleted)
sl@0
   133
		{
sl@0
   134
		return KErrNotSupported;
sl@0
   135
		}
sl@0
   136
	//User side clients and resource with dependency are not supported.
sl@0
   137
	if(aClientId & USER_SIDE_CLIENT_BIT_MASK)
sl@0
   138
		{
sl@0
   139
		return KErrNotSupported;
sl@0
   140
		}
sl@0
   141
#ifdef PRM_ENABLE_EXTENDED_VERSION
sl@0
   142
	if(aResCount == 1)
sl@0
   143
		{
sl@0
   144
		if((((DStaticPowerResource*)aStaticResourceArray)->iResourceId & KIdMaskResourceWithDependencies) ||
sl@0
   145
										(((DStaticPowerResource*)aStaticResourceArray)->iResourceId & KIdMaskDynamic))
sl@0
   146
			{
sl@0
   147
			return KErrNotSupported;
sl@0
   148
			}
sl@0
   149
		}
sl@0
   150
	else
sl@0
   151
		{
sl@0
   152
		for(TUint rescount = 0; rescount < aResCount; rescount++)
sl@0
   153
			{
sl@0
   154
			if(aStaticResourceArray[rescount] && ((aStaticResourceArray[rescount]->iResourceId & KIdMaskResourceWithDependencies) || 
sl@0
   155
				                          (aStaticResourceArray[rescount]->iResourceId & KIdMaskDynamic)))
sl@0
   156
				{
sl@0
   157
				return KErrNotSupported;
sl@0
   158
				}
sl@0
   159
			}
sl@0
   160
		}
sl@0
   161
#endif
sl@0
   162
	SPowerResourceClient* pC = pRC->iClientList[(TUint16)(aClientId & ID_INDEX_BIT_MASK)];								
sl@0
   163
	if(!pC)																										
sl@0
   164
		{																										
sl@0
   165
		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID not Found"));											
sl@0
   166
		return KErrAccessDenied;																		
sl@0
   167
		}																										
sl@0
   168
	if(pC->iClientId != aClientId)				
sl@0
   169
		{																										
sl@0
   170
		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client ID instance count does not match"));						
sl@0
   171
		return KErrAccessDenied;																		
sl@0
   172
		}																										
sl@0
   173
	if(pC->iClientId & CLIENT_THREAD_RELATIVE_BIT_MASK)															
sl@0
   174
		{																										
sl@0
   175
		if(pC->iThreadId != thread.iId)																				
sl@0
   176
			{																									
sl@0
   177
			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client not called from thread context(Thread Relative)"));	
sl@0
   178
			return KErrAccessDenied;																	
sl@0
   179
			}																									
sl@0
   180
		}
sl@0
   181
 
sl@0
   182
    TInt r = Kern::SafeReAlloc((TAny*&)pRC->iStaticResourceArray, pRC->iStaticResourceArrayEntries*sizeof(DStaticPowerResource*), 
sl@0
   183
		                                         (pRC->iStaticResourceArrayEntries + aResCount)*sizeof(DStaticPowerResource*));
sl@0
   184
    if(r != KErrNone)
sl@0
   185
		{
sl@0
   186
        return r;
sl@0
   187
		}
sl@0
   188
	if(aResCount == 1)
sl@0
   189
		{
sl@0
   190
		pRC->iStaticResourceArray[pRC->iStaticResourceArrayEntries++] = (DStaticPowerResource*)aStaticResourceArray;
sl@0
   191
		if((DStaticPowerResource*)aStaticResourceArray)
sl@0
   192
			pRC->iStaticResourceCount++;
sl@0
   193
		}
sl@0
   194
	else
sl@0
   195
		{
sl@0
   196
		for(TUint count = 0; count < aResCount; count++)
sl@0
   197
			{
sl@0
   198
			pRC->iStaticResourceArray[pRC->iStaticResourceArrayEntries++] = aStaticResourceArray[count];
sl@0
   199
			if(aStaticResourceArray[count])
sl@0
   200
				pRC->iStaticResourceCount++;
sl@0
   201
			}
sl@0
   202
		}
sl@0
   203
    return KErrNone;
sl@0
   204
	}
sl@0
   205
sl@0
   206
/**
sl@0
   207
	@publishedPartner
sl@0
   208
	@prototype 9.5
sl@0
   209
	Kernel extensions or variants can call this API to register the static resources before resource controller
sl@0
   210
	is fully initialized. 
sl@0
   211
	@Param aClientId ID of the client that is requesting resource registration
sl@0
   212
	@Param pR        Static resource to register with RC. 
sl@0
   213
	@return KErrNone, if operation is success
sl@0
   214
			KErrAccessDenied if clientId could not be found in the current list of registered clients or if this 
sl@0
   215
							 client was registered as thread relative and was not called from the same thread. 
sl@0
   216
			KErrNotSupported if called after resource controller is fully initialized or if called from user side proxy
sl@0
   217
							 or if the resource is dynamic or dependency resource
sl@0
   218
			KErrNoMemory if there is insufficient memory.
sl@0
   219
			KErrArgument if passed array is null
sl@0
   220
	*/
sl@0
   221
EXPORT_C TInt DPowerResourceController::RegisterStaticResource(TUint aClientId, DStaticPowerResource* pR)
sl@0
   222
	{
sl@0
   223
	return RegisterArrayOfStaticResources(aClientId, (DStaticPowerResource**&)pR, 1);
sl@0
   224
    }
sl@0
   225
sl@0
   226
/**
sl@0
   227
	@publishedPartner
sl@0
   228
	@prototype 9.5
sl@0
   229
	This function initialises the controller. 
sl@0
   230
	@return KErrNone, if operation is success or one of the system wide errors.
sl@0
   231
	*/
sl@0
   232
EXPORT_C TInt DPowerResourceController::InitController()
sl@0
   233
	{
sl@0
   234
    __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::InitController()"));
sl@0
   235
	DPowerResourceController* pRC = TInterface::GetPowerResourceController();
sl@0
   236
	if(!pRC)
sl@0
   237
		return KErrNotFound;
sl@0
   238
	if(pRC->iInitialised >= EResConInitialised)
sl@0
   239
		{
sl@0
   240
		__KTRACE_OPT(KRESMANAGER, Kern::Printf("InitController already initialised %d\n", pRC->iInitialised));
sl@0
   241
		return KErrNone;
sl@0
   242
		}
sl@0
   243
    _LIT(KResMutexName, "RESCTRL");
sl@0
   244
    TInt r=KErrNone;
sl@0
   245
	//Create the message queue
sl@0
   246
	pRC->iMsgQ = new TMessageQue(DPowerResourceController::MsgQFunc, pRC, NULL, 2);
sl@0
   247
	if(!pRC->iMsgQ)
sl@0
   248
		return KErrNoMemory;
sl@0
   249
#ifdef PRM_ENABLE_EXTENDED_VERSION
sl@0
   250
	//Create the message queue for dependency resource processing.
sl@0
   251
	pRC->iMsgQDependency = new TMessageQue(DPowerResourceController::MsgQDependencyFunc, pRC, NULL, 1);
sl@0
   252
	if(!pRC->iMsgQDependency)
sl@0
   253
		return KErrNoMemory;
sl@0
   254
#endif
sl@0
   255
	// Call PSL to create all static resources and populate the iStaticResourceArray with pointers to resources and
sl@0
   256
	// update static resource count
sl@0
   257
    r=pRC->DoRegisterStaticResources(pRC->iStaticResourceArray, pRC->iStaticResourceArrayEntries);
sl@0
   258
    if(r!=KErrNone)
sl@0
   259
		return r;
sl@0
   260
	//Get the actual number of static resource registered count
sl@0
   261
	for(TInt resCnt = 0; resCnt < pRC->iStaticResourceArrayEntries; resCnt++)
sl@0
   262
		{
sl@0
   263
		if(pRC->iStaticResourceArray[resCnt])
sl@0
   264
			pRC->iStaticResourceCount++;
sl@0
   265
		}
sl@0
   266
	__KTRACE_OPT(KRESMANAGER, Kern::Printf("Actual number of static resource registered = %d\n", pRC->iStaticResourceCount));
sl@0
   267
#ifdef PRM_INSTRUMENTATION_MACRO
sl@0
   268
	// Btrace output of resource information of each resource.
sl@0
   269
	DStaticPowerResource* pR = NULL;
sl@0
   270
	TPowerResourceInfoBuf01 resInfo;
sl@0
   271
	TPowerResourceInfoV01 *pResInfo;
sl@0
   272
	for(TInt resCount = 0; resCount < pRC->iStaticResourceArrayEntries; resCount++)
sl@0
   273
		{
sl@0
   274
		pR = pRC->iStaticResourceArray[resCount];
sl@0
   275
		if(!pR)
sl@0
   276
			continue;
sl@0
   277
		pR->GetInfo((TDes8*)resInfo.Ptr());
sl@0
   278
		pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
sl@0
   279
		PRM_REGISTER_RESOURCE_TRACE
sl@0
   280
		}
sl@0
   281
#endif
sl@0
   282
sl@0
   283
#ifdef PRM_ENABLE_EXTENDED_VERSION
sl@0
   284
	//Call PSL to register static resources with dependency if any exists
sl@0
   285
	r = pRC->DoRegisterStaticResourcesDependency(pRC->iStaticResDependencyArray, pRC->iStaticResDependencyCount);
sl@0
   286
	if(r != KErrNone)
sl@0
   287
		return r;
sl@0
   288
	if(pRC->iStaticResDependencyCount)
sl@0
   289
		{
sl@0
   290
		DStaticPowerResourceD* pRD = NULL;
sl@0
   291
		TUint count;
sl@0
   292
		//Assign resource index in resource id
sl@0
   293
		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
sl@0
   294
			{
sl@0
   295
			pRD = pRC->iStaticResDependencyArray[count];
sl@0
   296
			if(!pRD)
sl@0
   297
				Panic(DPowerResourceController::ERegisteringDependentStaticResourceWithHoles);
sl@0
   298
			pRD->iResourceId |= ((count + 1) & ID_INDEX_BIT_MASK);
sl@0
   299
			}
sl@0
   300
		//Check for dependency closed loops
sl@0
   301
		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
sl@0
   302
			{
sl@0
   303
			pRD = pRC->iStaticResDependencyArray[count];
sl@0
   304
			if(!(pRD->iResourceId & KIdMaskStaticWithDependencies))
sl@0
   305
				Panic(DPowerResourceController::ERegisteringNonDependentStaticResource);
sl@0
   306
			//Upgrade latency state change from instantaneous to long latency 
sl@0
   307
			if(!pRD->LatencySet()) 
sl@0
   308
				pRD->iFlags |= KLongLatencySet;
sl@0
   309
			pRC->CheckForDependencyLoop(pRD, pRD->iResourceId, pRD->iResourceId);
sl@0
   310
			}
sl@0
   311
#ifdef PRM_INSTRUMENTATION_MACRO
sl@0
   312
		for(count = 0; count < pRC->iStaticResDependencyCount; count++)
sl@0
   313
			{
sl@0
   314
			pR = pRC->iStaticResDependencyArray[count];
sl@0
   315
			pR->GetInfo((TDes8*)resInfo.Ptr());
sl@0
   316
			pResInfo = (TPowerResourceInfoV01*)resInfo.Ptr();
sl@0
   317
			PRM_REGISTER_STATIC_RESOURCE_WITH_DEPENDENCY_TRACE
sl@0
   318
			}
sl@0
   319
#endif
sl@0
   320
		}
sl@0
   321
#endif // PRM_ENABLE_EXTENDED_VERSION
sl@0
   322
	// Create mutex object
sl@0
   323
	r=Kern::MutexCreate(pRC->iResourceMutex, KResMutexName, KMutexOrdResourceManager);
sl@0
   324
	if(r==KErrNone) // Call PSL to create DFC queue and creation of pools with the help API's provided by generic layer.
sl@0
   325
		r=pRC->DoInitController();
sl@0
   326
	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::InitController()"));
sl@0
   327
	if(r == KErrNone)
sl@0
   328
		{
sl@0
   329
		pRC->iInitialised = EResConInitialised;
sl@0
   330
	    if(pRC->iDfcQ)
sl@0
   331
			pRC->iMsgQ->Receive();
sl@0
   332
#ifdef PRM_ENABLE_EXTENDED_VERSION
sl@0
   333
	    if(pRC->iDfcQDependency)
sl@0
   334
			pRC->iMsgQDependency->Receive();
sl@0
   335
#endif
sl@0
   336
		}
sl@0
   337
    return r;
sl@0
   338
	}