Adaptation/GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671" xml:lang="en"><title> Implement
the controllable power resources</title><shortdesc>This document describes how to write and use power resources. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<section id="GUID-7E91DB93-F9D6-4B93-8BAF-E25642F63C57"><title>Purpose</title> <p>Implement your power resource according
to the type of resource you wish to support. </p> <p><b>Introduction</b> </p> <p>Power
resources controlled by the PRM can be turned on, off and varied with software. </p> <p>See
the <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-4CC0C003-1952-5CAD-A7C5-163C5DDA52C8">Power
resources</xref> section for detailed information about resources. There are
five main types of resource that can be implemented: </p> <ul>
<li id="GUID-C67FB012-A1D6-5047-AD5A-18CF62971B2B"><p>static resources - derived
from the <xref href="GUID-DB7DDF4C-57EF-34FF-B3CD-13C5CD51A125.dita"><apiname>DStaticPowerResource</apiname></xref> base class, </p> </li>
<li id="GUID-6170B4D1-2AAD-52C7-88E0-D6BBE8CAFF63"><p>static resource that
support dependancy - derived from the <xref href="GUID-88C28976-67DF-3109-8D35-FA30A733C581.dita"><apiname>DStaticpowerResourceD</apiname></xref> base
class, </p> </li>
<li id="GUID-FAE7BFE3-7C2D-5DB7-A8FF-B7E4F37F5BAF"><p>dynamic resources -
derived from the <xref href="GUID-CA01041D-8FD6-3B5B-BB5D-A5159DF7C9AB.dita"><apiname>DDynamicPowerResource</apiname></xref> base class. Create
dynamic resources in the kernel data section or in the heap, </p> </li>
<li id="GUID-9586824D-FB68-5DC1-B743-9ED551FA286D"><p>dynamic resource that
support dependancy - derived from the <xref href="GUID-6B224A9F-D2B9-3289-922D-766EF093FCD6.dita"><apiname>DDynamicPowerResourceD</apiname></xref>. </p> </li>
<li id="GUID-AF8A571A-2AB6-5063-BFA5-3FF8509C95C7"><p>custom sense resources
- when shared the power level of this resource may be increased or decreased
freely by some privileged clients but not by others, which are bound by the
requirement of the privileged clients. </p> </li>
</ul> <p> <b>Note</b>: dynamic resources and resource dependancies are only
supported in the extended version of the PRM. See <xref href="GUID-2ECF13A1-9D56-5740-A09F-8267E6A45DD9.dita#GUID-2ECF13A1-9D56-5740-A09F-8267E6A45DD9/GUID-0F328055-DBCE-5B2B-A1EB-77F73BA1FC82">setup and configuration requirements</xref>. </p> </section>
<section id="GUID-D50E75DC-115E-42FD-9111-7A70E3087F33"><title> Implementing power resources </title> <p>The following tasks
are covered in this tutorial: </p> <ul>
<li id="GUID-2C4FDE84-401B-5520-B050-9FD475A63863">Create your resource by <p> <xref href="GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita#GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671/GUID-3021B2EA-9829-515C-9074-2D2D0D7A5510">Override
the pure virtual functions</xref>, </p> </li>
<li id="GUID-6492CDEF-524E-5A3A-82AB-1D0E0B8E9D28"><p> <xref href="GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita#GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671/GUID-A5D57D89-4499-5C85-80D5-5A7DC5644983">Create resource dependencies</xref>, </p> </li>
<li id="GUID-56A63835-D0B5-5C32-95D0-623A0D21AEF4"><p> <xref href="GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita#GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671/GUID-9526B472-00ED-583A-8BFC-C02363D4DFA2">Create custom resources</xref>. </p> </li>
</ul> <p id="GUID-3021B2EA-9829-515C-9074-2D2D0D7A5510"><b>Override the pure
virtual functions</b> </p> <p>The pure virtual functions of <xref href="GUID-DB7DDF4C-57EF-34FF-B3CD-13C5CD51A125.dita"><apiname>DStaticPowerResource</apiname></xref> or <xref href="GUID-CA01041D-8FD6-3B5B-BB5D-A5159DF7C9AB.dita"><apiname>DDynamicPowerResource</apiname></xref> must
be implemented. </p> <p><b>Constructor</b> </p> <p>Information about the resource
based on the resources category must be set in the <codeph>iFlags</codeph> bit
mask. Static variables that define a resources classification can be found
within <filepath>32\include\drivers\resource.h</filepath>. </p> <p>Each resource
is classified based on: </p> <ul>
<li id="GUID-08E6311D-6403-56CB-B91B-57C93F8CA208"><p>usage, </p> </li>
<li id="GUID-55F93FDB-137F-51D3-A1E3-F048B279425E"><p>operating levels, </p> </li>
<li id="GUID-4DD3D8E1-273A-5BFE-8A65-11B9DDE84E4D"><p>latency, </p> </li>
<li id="GUID-9B00B021-E620-50EA-B2D2-2F18111F5C1E"><p>resource sense. </p> </li>
</ul> <p>Below is the example implementation of derived class constructor </p> <codeblock id="GUID-1DE1E1CA-7212-5E30-85BF-C67578F9CEC8" xml:space="preserve">// multilevel, shared, long latency, read and write, positive resource. 
DMLSHLGLSPResource::DMLSHLGLSPResource() : DStaticPowerResource(KDBSHLGLSPResource, E_ON), 
                     iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(ETrue)
    {
    iFlags = EMultilevel | KShared | KLongLatencySet | KLongLatencyGet;
    . . .   
    }</codeblock> <p><b> GetInfo()</b> </p> <p>The PIL uses <xref href="GUID-66D96ADA-1C26-3293-9F92-FD65E08D6158.dita"><apiname>GetInfo()</apiname></xref> to
get resource information. The default implementation of this function provides
generic information about the resource by updating the passed descriptor that
contains an information structure <xref href="GUID-FA4D9A07-041C-303C-BF96-2E444DD47024.dita"><apiname>TPowerResourceInfoV01</apiname></xref>.
Derived implementations must fill in all the PSL specific fields and call
the base class implementation. Below is an example implementation. </p> <codeblock id="GUID-EB61E8FF-146C-5825-8F16-869FE4DD5B44" xml:space="preserve">TInt DH4SndFclkResource::GetInfo(TDes8* info) const
    {
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("&gt;DH4SndFclkResource::GetInfo\n"));

    /** Call base class implementation to fill generic details */
    DStaticPowerResource::GetInfo((TDes8*) info);
    TPowerResourceInfoV01 *buf1 = (TPowerResourceInfoV01*) info;
    buf1-&gt;iMinLevel = iMinLevel;
    buf1-&gt;iMaxLevel = iMaxLevel;
    __KTRACE_OPT(KRESMANAGER, Kern::Printf("&lt;DH4SndFclkResource::GetInfo\n"));
    return KErrNone;
    }</codeblock> <p>The member variables of the <codeph>TPowerResourceInfoV01</codeph> structure
are reserved for PSL information. These can be used to return resource specific
information to clients. </p> <p><b>DoRequest()</b> </p> <p> <xref href="GUID-9D910016-5611-30DD-A139-EE46705A4912.dita"><apiname>DoRequest()</apiname></xref> is
used by the PIL to control resources. For example, to change and read the
state of resources. <codeph>DoRequest()</codeph> takes a <xref href="GUID-D204F4A7-8CC8-3EB2-8371-1D1BFD903390.dita"><apiname>TPowerRequest</apiname></xref> object
that contains all the request information. <b>Note</b>: This function needs
to be implemented for all resources. </p> <p>Below is an example <xref href="GUID-9D910016-5611-30DD-A139-EE46705A4912.dita"><apiname>DoRequest()</apiname></xref> function
implementation for a binary, instantaneous resource. </p> <codeblock id="GUID-D5AE04C1-7A9D-5270-840F-6CD662FB46A2" xml:space="preserve">TInt DH4MmcCtrllerPwrResource::DoRequest(TPowerRequest&amp; aRequest)
    {
    TInt retVal = KErrNone;
    TUint16 config;
    /** Enable/disable the MMC controller by programming the MMC controller 'CON' register- 'POW' bit */
    if (aRequest.ReqType()==TPowerRequest::EGet) 
        {
        PRM_PSL_RESOURCE_GET_STATE_START_TRACE
        config = OMAPMMC_GET_REG(KHoMMC_Con_Reg);
        if(config &amp; KHtMMC_PowerUp)
            {
            aRequest.Level() = 1;
            iCurLevel = 1;
            }
        else
            {
            aRequest.Level() = 0;
            iCurLevel = 0;
            }
        PRM_PSL_RESOURCE_GET_STATE_END_TRACE
        }
    else if(aRequest.ReqType()==TPowerRequest::ESetDefaultLevel)
        {
        PRM_PSL_RESOURCE_CHANGE_STATE_START_TRACE
        OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KHtMMC_PowerUp, KClear32);
        iCurLevel = iDefaultLevel;
        aRequest.Level() = iDefaultLevel;
        PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE
        }
    else 
        {
        PRM_PSL_RESOURCE_CHANGE_STATE_START_TRACE
        if(aRequest.Level() == 1)
            {
            OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KClear32, KHtMMC_PowerUp);
            }
        else
            {
            OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KHtMMC_PowerUp, KClear32);
            }
        iCurLevel = aRequest.Level();
        PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE
        }
    return retVal;
    }</codeblock><p>The DoRequest function implementation should take care
of blocking the Resource Controller thread as operations on a long latency
resource take a significant amount of time to complete (in hardware). Usually
the request completion is notified either through an ISR (interrupt driven)
or through register setting (polling wait) by hardware. </p><p>Below is an
example <codeph>DoRequest()</codeph> implementation for a long latency resource. </p> <codeblock xml:space="preserve"> TInt DH4MmcPowerResource::DoRequest(TPowerRequest&amp; aRequest)
    {
    TUint8 iMenelausConf;
    TInt retVal = KErrNone;

    /** Access to Menelaus registers is over I2C bus. This is a long latency synchronous operation.
    Create a Menelaus Request structure and send it to Menelaus chip, Wait until a response is received */

    if (aRequest.ReqType()==TPowerRequest::EGet)
        {
        // Frame the request
        ... 
        }
				// Default level is off.
    else if (aRequest.ReqType() == TPowerRequest::ESetDefaultLevel)
        {
        // Frame request to move the resource to default state
        ... 
        }
				// EChange
    else 
       {
       // Frame request to set the requested resource state
       ...     
       }
    
    // Request the operation on the hardware
    retVal = Menelaus::AccessRegister(iMenelausReq);
    
    // Wait for the request to complete  
    __KTRACE_OPT(KPBUS1, Kern::Printf("Waiting for menelaus req to signal sem\n"));
    NKern::FSSetOwner(&amp;iSemaphore,NULL);
    iSemaphore.iCount = 0;	

    // This will be signalled in Menelaus access functions callback below
    NKern::FSWait(&amp;(iSemaphore)); 
	
    // Menelaus chip has responded
    if(iMenelausAccessErr == KErrNone)
        {
        switch(iMenelausState)
            {
            case EMenelausRead:
                // Return 0/1 depending on the value set
                iMenelausConf = (*(iRdBuffer.Ptr())) &amp; KHoMenelausVmmcModeMask;		                    
                if(iMenelausConf == 3)
                    {
                    iCurLevel=aRequest.Level()=1; 
                    }
                else 
                    {
                    iCurLevel=aRequest.Level()=0;
                    }
                PRM_PSL_RESOURCE_GET_STATE_END_TRACE
                break;

            case EMenelausSingleWrite:
                iCurLevel = aRequest.Level();
                PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE
                break;
            }
        }
        return iMenelausAccessErr;
    }

/** Below is the Menelaus access functions callback where the semaphore is signalled. */
void DH4MmcPowerResource::MenelausAccessDone(TAny* aPtr, TInt aResult)
    {
    DH4MmcPowerResource* ptr = reinterpret_cast&lt;DH4MmcPowerResource*&gt;(aPtr);
    ptr-&gt;iMenelausAccessErr = aResult;
    if(aResult != KErrNone)
        {
        __KTRACE_OPT(KRESMANAGER, 
        Kern::Printf("Menelaus::MenelausAccessRegister ERR(%d)\n", aResult));
        }
				// Signal the waiting thread
    NKern::FSSignal(&amp;(ptr-&gt;iSemaphore)); 
    return;
    }</codeblock><p id="GUID-A5D57D89-4499-5C85-80D5-5A7DC5644983"><b>Create
resource dependencies</b> </p> <p>A resource has a dependency if the state
of the resource depends on the state of one or more resources. For example,
a clock whose frequency is derived from another clock or voltage is a dependent
resource. The PSL usually handles resource dependencies transparently. However,
if the resources have public users (clients of the PRM), then these resources
should be registered with the PRM as <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-473BBE32-6831-52BE-8752-CB6DBBBABD2C">Resource
dependencies</xref> that are linked. </p> <p>Each dependency must be assigned
a priority value. The priority is used by the PIL when propagating the change
and propagating the request for notifications. Each link stemming from a resource
must have a unique priority value. </p> <p> <b>Note</b>: Resource dependencies
are only supported in the extended version of the PRM. Only long latency resources
are allowed to have dependents and no closed loop dependencies are allowed. </p> <p><b> Register
resource dependencies for dynamic and static resources</b> </p> <p>Static
resources that support dependencies are created and registered with the PRM
during resource controller creation time and are derived from <codeph>DStaticPowerResourceD</codeph>: </p> <codeblock id="GUID-1C7E2D5F-8C76-5D4D-84FA-259DE943742E" xml:space="preserve">DXXXStaticPowerResourceD : public DStaticPowerResourceD
    {
public:
    DXXXStaticPowerResourceD();
    TInt DoRequest(TPowerRequest &amp;req);
    TInt GetInfo(TDes8* aInfo) const;
    TChangePropagationStatus TranslateDependentState(TInt aDepId, TInt aDepState, TInt&amp; aResState);
private:
    TInt iMinLevel;
    TInt iMaxLevel;
    TInt iCurrentLevel;
    ...
    };</codeblock> <p>Dependencies between static resources should be established
by the PSL before registering these resources with the PIL. Use the <xref href="GUID-1CD49D40-1FF9-301C-8160-02A007485ADE.dita#GUID-1CD49D40-1FF9-301C-8160-02A007485ADE/GUID-806D0179-FC98-3106-BCBA-0D3634B43815"><apiname>DStaticPowerResourceD::AddNode()</apiname></xref> function
provided in the base class to establish a dependency link between static resources.
See <xref href="GUID-66FD040B-133E-57CF-80DD-9369F62709C6.dita#GUID-66FD040B-133E-57CF-80DD-9369F62709C6/GUID-A912A328-D646-5516-9731-FFA7F3B2EDDA">Creating
dependencies between static resources</xref>. </p> <p>Dynamic resources that
support dependency are derived from <xref href="GUID-6B224A9F-D2B9-3289-922D-766EF093FCD6.dita"><apiname>DDynamicPowerResourceD</apiname></xref>.
These can be registered and deregistered from the PRM at any time after the
PRM is fully initialised. Dependencies between resources are established by
the client using <xref href="GUID-40AB9EDA-16CB-371E-8759-1D7C99FF9C00.dita#GUID-40AB9EDA-16CB-371E-8759-1D7C99FF9C00/GUID-9C1BF3D5-6F5D-3BEF-9DF0-A5FED85CC718"><apiname>PowerResourceManager::RegisterResourceDependency()</apiname></xref>. </p> <codeblock id="GUID-30B2271B-FA2A-53FE-A1F1-0A3E36B95883" xml:space="preserve">DXXXDynamicPowerResourceD : public DDynamicPowerResourceD
    {
public:
    DXXXDynamicPowerResourceD();
    TInt DoRequest(TPowerRequest &amp;req);
    TInt GetInfo(TDes8* aInfo) const;
    TChangePropagationStatus TranslateDependentState(TInt aDepId, TInt aDepState, TInt&amp; aResState);
private:
    TInt iMinLevel;
    TInt iMaxLevel;
    TInt iCurrentLevel;
    ...
    };</codeblock> <p>Dependencies can be established between a dynamic resource
and a static (dependency enabled) resource using the same API. A client can
deregister dependencies between a pair of dynamic resource (or between a dynamic
and static resource) using <xref href="GUID-40AB9EDA-16CB-371E-8759-1D7C99FF9C00.dita#GUID-40AB9EDA-16CB-371E-8759-1D7C99FF9C00/GUID-127E979F-F540-36E2-A759-8ED408E89F38"><apiname>PowerResourceManager::DeRegisterResourceDependency()</apiname></xref>.
When a dynamic resource that supports dependency deregisters from the PRM,
dependencies are removed automatically by the PIL. </p> <p><b>Change the state
of dependent resources</b> </p> <p>When a state change is requested by a client
on any resource in a dependency tree before proceeding with the change the
PIL must check if the change is allowed by its dependents and the ones it
depends on. The PIL does this by calling the <xref href="GUID-E71F94F6-A4BB-3C85-8E2E-8E3ABAA85897.dita"><apiname>TranslateDependentState()</apiname></xref> function
on each resource. This is a pure virtual function in the base class and must
be implemented in the derived class. </p> <p>This function is called by the
PIL prior to a resource change on any of its dependents. The function returns
one of these values: </p> <ul>
<li id="GUID-CEABEBE0-34BB-5CD0-861E-CDB87A066C8B"><p> <codeph>EChange</codeph> -
If the resource accepts the state change of the dependent resource and, as
a result of the dependent resources state change this resource needs to change
its own state. The new state of this resource is updated in <codeph>aResState</codeph>, </p> </li>
<li id="GUID-A22403B9-38C9-571E-9E14-C7BD1CB032F2"><p> <codeph>ENoChange</codeph> -
if the resource accepts the dependent resources state change and this resource
does not need to change its state, </p> </li>
<li id="GUID-EE30E093-85A0-5205-B1C7-6C36A5410BB1"><p> <codeph>ENotAllowed</codeph> -
if the resource does not accept the dependent resources state change. </p> </li>
</ul> <codeblock id="GUID-453D7F61-4187-50DC-B641-34A06AEB722B" xml:space="preserve">TChangePropagationStatus DXXDependResource::TranslateDependentState(TInt /*aDepId*/, TInt aDepState,
   TInt&amp; aResState)
    {
    /* Switch ON if the dependent resource is ON */
    if((aDepState == 1) &amp;&amp; (iCurrentLevel == 0)
        {
        aResState = iMaxLevel;
           return EChange;
           }

    /* Don’t allow dependent to OFF, if this is still ON */
    else if (aDepState == 0) &amp;&amp; (iCurrentLevel == 1)
        {
        return ENotAllowed;
        }

    return ENoChange;
    }</codeblock> <p id="GUID-9526B472-00ED-583A-8BFC-C02363D4DFA2"><b>Create
custom resources</b> </p> <p>Clients on a shared resource may have different
requirements on the state of a shared resource. The resource sense is used
by the PIL to determine whose requirement prevails: </p> <ul>
<li id="GUID-495628CC-D257-598F-B420-2784749B1083"><p>positive sense resources
- when shared can have their value increased without prejudice to their clients, </p> </li>
<li id="GUID-D4D7CB6D-F99B-568E-9F38-429196599F4F"><p>negative sense resources
- when shared can have their value decreased without prejudice to their clients, </p> </li>
<li id="GUID-0BB26EA3-F22B-5C7D-8999-14DB75D066CA"><p>custom sense resources
- when shared may be increased or decreased freely by some privileged clients
but not by others, which are bound by the requirement of the privileged clients. </p> </li>
</ul> <p>A custom function must be supplied for every <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-4CC0C003-1952-5CAD-A7C5-163C5DDA52C8">Power resources</xref> resource. This function is called by the PIL every
time a change request is issued to determine if the change requested by the
client is allowed as a decision to allow the resource change is determined
solely by the PSL. The resource object contains a pointer that must be set
at construction for custom sense resources by calling this function: </p> <codeblock id="GUID-31716524-4902-5E87-A51F-2EF63DA6D500" xml:space="preserve">inline void SetCustomFunction(TCustomFunction aCustomFunction)</codeblock> <p>This
function sets the custom function for the resource. If a custom function is
not supplied for a custom sense resource the PIL panics during a resource
state change. An example of a custom sense resource is a shared domain clock
when a domain client uses it as a bit clock. </p> <p> <xref href="GUID-5FDBF9F8-9BC4-3E3B-9A28-5046C65788E2.dita"><apiname>TCustomFunction</apiname></xref> is
a function pointer: </p> <codeblock id="GUID-A0ECC7F5-A410-50DA-9723-09C1C080927C" xml:space="preserve">typedef TBool (*TCustomFunction) (TInt&amp; /*aClientId*/,
                                  TUint /*aResourceId*/,
                                  TInt&amp; /*aLevel*/,
                                  TAny* /*aLevelList*/);</codeblock> <p>The
values held in TCustomFunction are: </p> <ul>
<li id="GUID-5E1EF546-098D-5940-8BD0-4AF2B70861E4"><p>the Id of the client
requesting the change, </p> </li>
<li id="GUID-A8E1B48A-C36C-5D88-9388-BE40902832AE"><p>the Id of the resource
on which the change is requested (this allows a single function to handle
multiple resources), </p> </li>
<li id="GUID-CDC2D3F7-2E82-5E56-864B-E0901B57FE83"><p>the level the client
is requesting, </p> </li>
<li id="GUID-57C1C8CC-411D-54B7-9548-2D0C5DFB6B3F"><p>a pointer to the list
of the resource’s <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-F47D2098-16A7-5590-A68A-7AE4B2DAB462">client
levels</xref>. </p> </li>
</ul> <p>Custom functions can be set at any time before a resource state change
is requested on a resource. Ideally a custom function is set at resource creation
time in the resource's constructor. </p> <codeblock id="GUID-6B688BFC-8D7A-5D7C-B17D-B4D3579230F4" xml:space="preserve">DBSHLGLSCResource::DBSHLGLSCResource() : DStaticPowerResource(KDBSHLGLSCResource, E_ON), iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(EFalse)
    {
    iFlags = KMultiLevel | KShared | KLongLatencySet | KSenseCustom;
    SetCustomFunction(CustomFunction);
 ...
    }</codeblock> <p>The decision to allow the requested resource state change
is specified in the custom function return value. This is <codeph>ETrue</codeph> if
the change is allowed and <codeph>EFalse</codeph> if the change is not allowed. </p> <p>The
function can change the state of the resource to a level other than the one
requested and can choose a client other than the passed client to hold the <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-121C14E3-D446-565E-AAAE-C43C131ACD3C">Caching
the prevailing level</xref> of the resource. </p> <p><b>Supporting dependencies </b> </p> <p>If
the custom sense resource supports dependencies then use the function pointer <xref href="GUID-60A17842-3E3B-3748-8F91-F5ED912E642A.dita"><apiname>TDependencyCustomFunction</apiname></xref>.
This takes an additional parameter that specifies the resource <xref href="GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE.dita#GUID-6E1DE1E4-1B09-541C-8708-9126E69B42CE/GUID-F47D2098-16A7-5590-A68A-7AE4B2DAB462">Client level objects</xref>. </p> </section>
</conbody><related-links>
<link href="GUID-2ECF13A1-9D56-5740-A09F-8267E6A45DD9.dita"><linktext>Porting the
Power Resource Manager</linktext></link>
<link href="GUID-66FD040B-133E-57CF-80DD-9369F62709C6.dita"><linktext>Implement
the PSL for the target</linktext></link>
<link href="GUID-E7F91A65-235D-589C-9A8C-0B207D19A24B.dita"><linktext>Port the
client drivers to use the PRM</linktext></link>
<link href="GUID-C8DF0CB0-92F4-5F9E-A8F1-7DE50954C4F1.dita"><linktext>Debugging
the PRM</linktext></link>
<link href="GUID-66E5F769-1156-54CA-94BC-8912159A1240.dita"><linktext>Testing the
PRM PSL</linktext></link>
</related-links></concept>