/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME =  RSMNODE.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Node Services
 *
 *
 *
 * VERSION = V1.01
 *
 * DATE
 *
 * DESCRIPTION :
 *
 * Purpose:
 *
 *
 *
 * FUNCTIONS  :
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 *
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define  INCL_NOBASEAPI
#define  INCL_NOPMAPI
#define  INCL_DOSERRORS
#include <os2.h>

#include <dskinit.h>

#include "dhcalls.h"

#include "strat2.h"
#include "scsi.h"
#include "reqpkt.h"

#define RMCode SwapCode
#include "rmcalls.h"
#include "rmioctl.h"

#include "rsmcons.h"
#include "rsmtypes.h"
#include "rsmproto.h"
#include "rsmextrn.h"

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateAdapterNode                                    */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE FAR f_RMCreateAdapterNode( PADAPTERSTRUCT pAS )
{
  return ( RMCreateAdapterNode( pAS ) );
}

PRMNODE NEAR RMCreateAdapterNode( PADAPTERSTRUCT pAS )
{
  return( RMCreateStdNode( ADAPTER_NODE_COOKIE, pAS ) );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateDeviceNode                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE FAR f_RMCreateDeviceNode( PDEVICESTRUCT pDS )
{
  return ( RMCreateDeviceNode( pDS ) );
}

PRMNODE NEAR RMCreateDeviceNode( PDEVICESTRUCT pDS )
{
  return( RMCreateStdNode( DEVICE_NODE_COOKIE, pDS ) );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateStdNode                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMCreateStdNode( ULONG NodeCookie, PVOID pDS )
{
  USHORT                NodeLen;
  USHORT                NodeClass;
  USHORT                NameLen;
  USHORT                TextLen;
  USHORT                AdjLen = 0;
  USHORT                StructLen;
  PSZ                   pDescName;
  PBYTE                 pNodeStr;
  PADJUNCT              pAdjunct, pAdj, pPrevAdj;
  PADJUNCT              pAdjList;
  PADJUNCT              FAR *ppAdjPtr;
  PSZ                   FAR *ppDescPtr;

  USHORT                Ord1 = -1;
  USHORT                Ord2 = -1;

  PRMNODE               pNode;


  switch ( NodeCookie )
  {
     case ADAPTER_NODE_COOKIE:
       pAdjunct  = ((PADAPTERSTRUCT) pDS)->pAdjunctList;
       pDescName = ((PADAPTERSTRUCT) pDS)->AdaptDescriptName;
       StructLen = sizeof(ADAPTERSTRUCT);
       NodeClass = 0;
       break;
     case DEVICE_NODE_COOKIE:
       pAdjunct  = ((PDEVICESTRUCT) pDS)->pAdjunctList;
       pDescName = ((PDEVICESTRUCT) pDS)->DevDescriptName;
       StructLen = sizeof(DEVICESTRUCT);
       NodeClass = 0;
       break;
     case LDEV_NODE_COOKIE:
       pAdjunct  = ((PLDEVSTRUCT) pDS)->pAdjunctList;
       pDescName = ((PLDEVSTRUCT) pDS)->LDevDescriptName;
       StructLen = sizeof(LDEVSTRUCT);
       NodeClass = 1;
       break;
     case SYS_NODE_COOKIE:
       pAdjunct  = ((PSYSNAMESTRUCT) pDS)->pAdjunctList;
       pDescName = ((PSYSNAMESTRUCT) pDS)->SysDescriptName;
       StructLen = sizeof(SYSNAMESTRUCT);
       NodeClass = 1;
       break;
     default:
       _asm int 3
       break;
  }


  /*-----------------------------------------*/
  /* Calculate total length of Adapter Node  */
  /*-----------------------------------------*/

  if ( (TextLen=strlen(pDescName)+1) > MAX_NODE_TEXT )
  {
    TextLen = MAX_NODE_TEXT;
  }

  for ( pAdjList=pAdjunct; pAdjList; pAdjList=pAdjList->pNextAdj )
  {
    AdjLen += pAdjList->AdjLength;
  }

  NodeLen = RMNODELEN + StructLen + TextLen + AdjLen;

  /*-------------------------*/
  /* Allocate new RMNode     */
  /*-------------------------*/

  if ( pNode = (PRMNODE) RMAlloc( NodeLen ) )
  {
    switch ( NodeCookie )
    {
       case ADAPTER_NODE_COOKIE:
         ppAdjPtr  = &(((PADAPTERSTRUCT) pNode->NodeData)->pAdjunctList);
         ppDescPtr = &(((PADAPTERSTRUCT) pNode->NodeData)->AdaptDescriptName);
         break;
       case DEVICE_NODE_COOKIE:
         ppAdjPtr  = &(((PDEVICESTRUCT) pNode->NodeData)->pAdjunctList);
         ppDescPtr = &(((PDEVICESTRUCT) pNode->NodeData)->DevDescriptName);
         break;
       case LDEV_NODE_COOKIE:
         ppAdjPtr  = &(((PLDEVSTRUCT) pNode->NodeData)->pAdjunctList);
         ppDescPtr = &(((PLDEVSTRUCT) pNode->NodeData)->LDevDescriptName);
         break;
       case SYS_NODE_COOKIE:
         ppAdjPtr  = &(((PSYSNAMESTRUCT) pNode->NodeData)->pAdjunctList);
         ppDescPtr = &(((PSYSNAMESTRUCT) pNode->NodeData)->SysDescriptName);
         break;
    }

    /*----------------------------------*/
    /* Initialize fixed portion of node */
    /*----------------------------------*/
    pNode->Cookie   = NodeCookie;
    pNode->Unique   = cUnique++;
    if (cUnique >= UNIQUE_LIMIT)
       cUnique = 1;
    pNode->pAdpt    = (PADAPTERSTRUCT) pNode->NodeData;
    pNodeStr        = (PBYTE)          pNode->NodeData;

    /*--------------------------------*/
    /* Transfer LDEVStruct to node    */
    /*--------------------------------*/
    memcpy( pNodeStr, pDS, StructLen );

    /*----------------------------------*/
    /* Transfer Adjunct list structures */
    /*----------------------------------*/
    pAdj = (PADJUNCT)(pNodeStr + StructLen);

    if ( AdjLen )
    {
      for ( pAdjList=pAdjunct;
            pAdjList;
            pAdjList=pAdjList->pNextAdj )
      {

        switch ( pAdjList->AdjType )
        {
          case ADJ_SCSI_TARGET_LUN:
            Ord1 = pAdjList->SCSI_Target_LUN >> 8;
            Ord2 = pAdjList->SCSI_Target_LUN &  0xff;
            break;
          case ADJ_DEVICE_NUMBER:
          case ADJ_ADAPTER_NUMBER:
            Ord1 = pAdjList->Adapter_Number;
            break;
        }
        memcpy( pAdj, pAdjList, pAdjList->AdjLength );

        pAdj->pNextAdj = (PADJUNCT)((PBYTE)pAdj + pAdjList->AdjLength);

        pPrevAdj = pAdj;
        pAdj     = pAdj->pNextAdj;
      }

      pPrevAdj->pNextAdj  = NULL;
      *ppAdjPtr           = (PADJUNCT)(pNodeStr+StructLen);
    }

    /*----------------------------------*/
    /* Transfer Device Description Text */
    /*----------------------------------*/
    *ppDescPtr = (PSZ) pAdj;
    memcpy( pAdj, pDescName, TextLen );

    if ( Ord1 != -1 )
    {
      RMUpdateKey( (PSZ) pAdj, Ord1, Ord2 );
    }

  }

  if (pNode)
  {
    if ( !NodeClass )
    {
      cRMNodes++;
    }
    else
    {
      cRMLNodes++;
    }
  }

  return( pNode );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMDeleteRMNode                                         */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMDeleteRMNode( PRMNODE pNodeDel )
{
  RMDeleteRMNode( pNodeDel );
}


USHORT NEAR RMDeleteRMNode( PRMNODE pNodeDel )
{
  PDRVRNODE     pDriver;
  PRMNODE       pNodePrev, pNode, pNodeParent;

  if ( pNodeDel->pDevChild )
  {
    _asm int 3
  }

  if ( pNodeParent = pNodeDel->pDevParent )
  {
    pNode     = pNodeParent->pDevChild;
    pNodePrev = 0;

    while ( pNode && (pNode != pNodeDel) )
    {
      pNodePrev = pNode;
      pNode     = pNode->pDevSibling;
    }

    if ( !pNode )
    {
      _asm int 3
    }
    if ( pNodePrev )
    {
      pNodePrev->pDevSibling = pNode->pDevSibling;
    }
    else
    {
      pNodeParent->pDevChild = pNode->pDevSibling;
    }
  }

  if ( pDriver = pNodeDel->pDriver )
  {
    pNode     = pDriver->pDevChain;
    pNodePrev = 0;

    while ( pNode && (pNode != pNodeDel) )
    {
      pNodePrev = pNode;
      pNode     = pNode->pDevDrvChain;
    }

    if ( !pNode )
    {
      _asm int 3
    }
    if ( pNodePrev )
    {
      pNodePrev->pDevDrvChain = pNode->pDevDrvChain;
    }
    else
    {
      pDriver->pDevChain = pNode->pDevDrvChain;
    }
  }

  RMFree( (PBYTE) pNodeDel );

  cRMNodes--;
  return( 0 );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateDriverNode                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/
PDRVRNODE FAR f_RMCreateDriverNode( PDRIVERSTRUCT pDS )
{
  return ( RMCreateDriverNode( pDS ) );
}

PDRVRNODE NEAR RMCreateDriverNode( PDRIVERSTRUCT pDS )
{
  USHORT                TextLenName;
  USHORT                TextLenDesc;
  USHORT                TextLenVendor;
  USHORT                NodeLen;

  PDRIVERSTRUCT         pDrvr;
  PDRVRNODE             pDrv;         /* For Driver Chain */

  PDRVRNODE             pNode;
  PSZ                   pFree;

  /*-----------------------------------------*/
  /* Calculate total length of Driver Node   */
  /*-----------------------------------------*/

  if ( (TextLenName=strlen(pDS->DrvrName)+1) > MAX_NODE_TEXT )
  {
    TextLenName = MAX_NODE_TEXT;
  }

  if ( (TextLenDesc=strlen(pDS->DrvrDescript)+1) > MAX_NODE_TEXT )
  {
    TextLenDesc = MAX_NODE_TEXT;
  }

  if ( (TextLenVendor=strlen(pDS->VendorName)+1) > MAX_NODE_TEXT )
  {
    TextLenVendor=MAX_NODE_TEXT;
  }


  NodeLen = RMNODELEN + sizeof(DRIVERSTRUCT) + TextLenDesc + TextLenName + TextLenVendor;

  /*-----------------------------*/
  /* Allocate new Driver Node    */
  /*-----------------------------*/

  if ( pNode = (PDRVRNODE) RMAlloc( NodeLen ) )
  {
    /*----------------------------------*/
    /* Initialize fixed portion of node */
    /*----------------------------------*/
    pNode->Cookie   = DRIVER_NODE_COOKIE;
    pNode->Unique   = cUnique++;
    if (cUnique >= UNIQUE_LIMIT)
       cUnique = 1;

    pNode->pDrv = pDrvr = (PDRIVERSTRUCT) pNode->NodeData;


    /*--------------------------------*/
    /* Transfer DriverStruct to node  */
    /*--------------------------------*/
    memcpy( pDrvr, pDS, sizeof(DRIVERSTRUCT) );
    pFree = (PSZ)(pDrvr + 1);


    /*-------------------------------*/
    /* Transfer DrvrDescription Text */
    /*-------------------------------*/
    pDrvr->DrvrName = (PSZ) pFree;
    memcpy( pFree, pDS->DrvrName, TextLenName );
    pFree += TextLenName;

    /*-------------------------------*/
    /* Transfer DrvrDescription Text */
    /*-------------------------------*/
    pDrvr->DrvrDescript = (PSZ) pFree;
    memcpy( pFree, pDS->DrvrDescript, TextLenDesc );
    pFree += TextLenDesc;

    /*-------------------------------*/
    /* Transfer VendorName Text */
    /*-------------------------------*/
    pDrvr->VendorName = (PSZ) pFree;
    memcpy( pFree, pDS->VendorName, TextLenVendor );
    pFree += TextLenDesc;

  }

  if (pNode) {
    /*------------------------------------------*/
    /*   Place at end of DriverChain            */
    /*------------------------------------------*/

    if (pDrv=(PDRVRNODE) PDevPtrs[PDEV_DRIVER]){
       while(pDrv->pDrvSibling){       /* Get to end of chain */
         pDrv=pDrv->pDrvSibling;
       }
       pDrv->pDrvSibling=pNode;         /* Put on end of chain */
    } else {                            /* First Driver        */
       pDrv = pNode;                    /* Put at beginning    */
    }

    cRMDrvrNodes++;
  }
  return( pNode );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMDeleteDriverNode                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/
USHORT FAR f_RMDeleteDriverNode( PDRVRNODE pDriverDel )
{
  return ( RMDeleteDriverNode( pDriverDel ) );
}

USHORT NEAR RMDeleteDriverNode( PDRVRNODE pDriverDel )
{
  PDRVRNODE     pDrv, pDrvPrev;

  if ( pDriverDel->pDevChain )
  {
    _asm int 3
  }
  if ( pDriverDel->pResChain )
  {
    _asm int 3
  }

  pDrv = (PDRVRNODE) PDevPtrs[PDEV_DRIVER];

  while ( pDrv && (pDrv != pDriverDel) )
  {
    pDrvPrev = pDrv;
    pDrv     = pDrv->pDrvSibling;
  }

  if ( !pDrv )
  {
    _asm int 3
    return ( 1 );
  }

  if ( pDrvPrev )
  {
    pDrvPrev->pDrvSibling = pDriverDel->pDrvSibling;
  }
  else
  {
    PDevPtrs[PDEV_DRIVER] = (PRMNODE) pDriverDel->pDrvSibling;
  }

  RMFree( (PUCHAR) pDriverDel );


  cRMDrvrNodes--;
  return( 0 );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateResourceNode                                   */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRESNODE FAR f_RMCreateResourceNode( PRESOURCESTRUCT pRS )
{
  return ( RMCreateResourceNode( pRS ) );
}

PRESNODE NEAR RMCreateResourceNode( PRESOURCESTRUCT pRS )
{
  USHORT                NodeLen;
  PRESNODE              pNode;

  /*-----------------------------------------*/
  /* Calculate total length of Resource Node */
  /*-----------------------------------------*/

  NodeLen = RESNODELEN + sizeof(RESOURCESTRUCT);

  /*-----------------------------*/
  /* Allocate new Resource Node  */
  /*-----------------------------*/

  if ( pNode = (PRESNODE) RMAlloc( NodeLen ) )
  {
    /*----------------------------------*/
    /* Initialize fixed portion of node */
    /*----------------------------------*/
    pNode->Cookie       = RESOURCE_NODE_COOKIE;
    pNode->Unique       = cUnique++;
    if (cUnique >= UNIQUE_LIMIT)
       cUnique = 1;
    pNode->ResourceType = pRS->ResourceType;
    pNode->pIO          = &((PRESOURCESTRUCT) pNode->NodeData)->IOResource;

    /*---------------------------------*/
    /* Transfer ResourceStruct to node */
    /*---------------------------------*/
    memcpy( pNode->NodeData, pRS, sizeof(RESOURCESTRUCT) );
  }

  return( pNode );
}



/*--------------------------------------------------------*/
/*                                                        */
/* RMDeleteResourceNode                                   */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMDeleteResourceNode( PRESNODE pResNodeDel )
{
  return ( RMDeleteResourceNode( pResNodeDel ) );
}

USHORT NEAR RMDeleteResourceNode( PRESNODE pResNodeDel )
{
  if ( !RMUnlinkResourceNode( pResNodeDel ) )
  {
    RMFree( (PBYTE) pResNodeDel );
  }
  else
  {
    _asm int 3
  }
}



/*--------------------------------------------------------*/
/*                                                        */
/* RMAddChild                                             */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID FAR f_RMAddChild( PRMNODE pDevParent, PRMNODE pDevChild )
{
  return( RMAddChild( pDevParent, pDevChild ) );
}

VOID NEAR RMAddChild( PRMNODE pDevParent, PRMNODE pDevChild )
{
  PRMNODE       pNode, pNodePrev;

  pNode     =  pDevParent->pDevChild;
  pNodePrev =  0;

  while ( pNode )
  {
    pNodePrev = pNode;
    pNode     = pNode->pDevSibling;
  }

  if ( !pNodePrev )
  {
    pDevParent->pDevChild = pDevChild;
  }
  else
  {
    pNodePrev->pDevSibling = pDevChild;
  }
  pDevChild->pDevSibling  = 0;
  pDevChild->pDevChild    = 0;
  pDevChild->pDevParent   = pDevParent;

  if ( !pDevChild->pDriver )
  {
    f_RMRegisterNode( (PDRVRNODE) PDevPtrs[PDEV_KRNLDD],
                      (PRMNODE)   pDevChild );
  }

}

/*--------------------------------------------------------*/
/*                                                        */
/* RMRegisterNode                                         */
/*                                                        */
/* Associate Node with Driver                             */
/*                                                        */
/*--------------------------------------------------------*/


VOID FAR f_RMRegisterNode( PDRVRNODE pDriverNode, PRMNODE pDevChild )
{
  RMRegisterNode( pDriverNode, pDevChild );
  return;
}

VOID NEAR RMRegisterNode( PDRVRNODE pDriverNode, PRMNODE pDevChild)
{
  PRMNODE       pNode, pNodePrev;

  pNode     =  pDriverNode->pDevChain;
  pNodePrev =  0;

  while ( pNode )
  {
    pNodePrev = pNode;
    pNode     = pNode->pDevDrvChain;
  }

  if ( !pNodePrev )
  {
    pDriverNode->pDevChain = pDevChild;
  }
  else
  {
    pNodePrev->pDevDrvChain = pDevChild;
  }
  pDevChild->pDevDrvChain  = 0;
  pDevChild->pDriver       = pDriverNode;

  return;
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMUpdateKey                                            */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMUpdateKey( PSZ d, USHORT Ord1, USHORT Ord2 )
{
  USHORT        Len;
  USHORT        i;
  UCHAR         c;
  PSZ           d0;

  Len = strlen(d);

  for ( i=0; i < MAX_KEY_LEN; i++ )
  {
    if ( (c = d[i]) == ' ' || !c)
    {
      break;
    }
  }

  if ( d[i-1] == '#' )
  {
    d0 = d+i-1;

    if ( Ord2 == 0xffff )
    {
      if ( Len >= i+1 )
      {
        RMItoA( d0, Ord1 );
      }
    }
    else
    {
      if ( Len >= i+6 )
      {
        memset( d0, ' ', 7);
        *d0++ = '(';
        d0    = RMItoA( d0, Ord1 );
        *d0++ = ',';
        d0    = RMItoA( d0, Ord2 );
        *d0++ = ')';
      }
    }
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMItoA                                                 */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PSZ NEAR RMItoA( PSZ d, USHORT Value )
{
  UCHAR   c;

  if ( Value < 100 )
  {
    if ( c=Value/10 )
    {
      *d++ = c + '0';
    }
    else
    {
      d[1] = ' ';
    }

    *d++ = Value % 10 + '0';

    return ( d );
  }
}


/*--------------------------------------------------------*/
/*                                                        */
/*   RMDestroyRMNode                                      */
/*   -------------                                        */
/*      Destroy a Node and all children                   */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMDestroyRMNode(PDRVRNODE pDrvrNode, PRMNODE pRMNode)
{

   /*-------------------------------------*/
   /* Verify This Device in some way      */
   /* manages this resource.              */
   /*------------------------------------ */

   if ( pRMNode->pDriver != pDrvrNode )
      return RMRC_BAD_DRIVERHANDLE;

   /*-------------------------------------*/
   /* Destroy Children and their Family   */
   /*-------------------------------------*/

   if( pRMNode->pDevChild )
      RMDestroyFamily( pRMNode->pDevChild );

   /*-------------------------------------*/
   /* Finally, Destroy myself             */
   /*-------------------------------------*/
   RMDestroyMyNode( pRMNode );


   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RMDestroyFamily                                      */
/*   -------------                                        */
/*      Recursively Destroy this node and any             */
/*      children or siblings                              */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMDestroyFamily( PRMNODE pRMNode )
{

   /*-------------------------------------*/
   /* Need to destroy any underlying      */
   /* structures.                         */
   /*-------------------------------------*/

   if ( pRMNode->pDevChild )
   {
      RMDestroyFamily( pRMNode->pDevChild );
   }

   if ( pRMNode->pDevSibling )
   {
      RMDestroyFamily( pRMNode->pDevSibling  );
   }

   /*-------------------------------------*/
   /* Finally, Destroy myself             */
   /*-------------------------------------*/
   RMDestroyMyNode( pRMNode );


   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RMDestroyMyNode                                      */
/*   -------------                                        */
/*      Destroy Adapter/Device Helper                     */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMDestroyMyNode( PRMNODE pRMNode )
{
   PRMNODE  pLDev;



   /*-------------------------------------*/
   /* Need to destroy all owned resource  */
   /* structures.                         */
   /*-------------------------------------*/

   if ( (pRMNode->Cookie == ADAPTER_NODE_COOKIE) ||
        (pRMNode->Cookie == DEVICE_NODE_COOKIE) )
   {
     /*----------------------------------------------*/
     /* If we are deleting an adapter or device node */
     /* then release resources and find and delete   */
     /* from any LDev associations.                  */
     /*----------------------------------------------*/
     while(pRMNode->pResChain)
     {
        RMDeleteResourceNode(pRMNode->pResChain);
     }


     while( pLDev = RMDevToLDev( LDevPtrs[LDEV_CLASS_ROOT], pRMNode ))
     {
        pLDev->pDevAssoc = 0;
     }


   }

   /*-------------------------------------*/
   /* Finally, Destroy myself             */
   /*-------------------------------------*/
   RMDeleteRMNode(pRMNode);


   return RMRC_SUCCESS;
}
