Adaptation/GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita
changeset 15 307f4279f433
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adaptation/GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita	Fri Oct 15 14:32:18 2010 +0100
@@ -0,0 +1,357 @@
+<?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>
\ No newline at end of file