/*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 =  RSMSRCH.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Node Search Functions
 *
 *
 *
 * VERSION = V1.01
 *
 * DATE
 *
 * DESCRIPTION :
 *
 * Purpose:
 *
 *
 *
 * FUNCTIONS  :
 *
 * NOTES
 *        Does good stuff........
 *
 *
 * 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"

/*--------------------------------------------------------*/
/*                                                        */
/* RMDevToLDev                                            */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

static PRMNODE  pStartLDev;

PRMNODE NEAR RMDevToLDev( PRMNODE pLDev, PRMNODE pDev )
{
  pStartLDev = pLDev;

  return( RMDevToLDevSub( pLDev, pDev ) );
}


PRMNODE NEAR RMDevToLDevSub( PRMNODE pLDev, PRMNODE pDev )
{
  PRMNODE       pLDevRet;

  if ( pLDev->Cookie != LDEV_NODE_COOKIE )
  {
    return( 0 );
  }

  if ( pLDev->pDevAssoc == pDev )
  {
    return( pLDev );
  }

  if ( pLDev->pDevChild )
  {
    if ( pLDevRet = RMDevToLDev( pLDev->pDevChild, pDev ) )
    {
      return( pLDevRet );
    }
  }
  if ( pLDev->pDevSibling && (pLDev != pStartLDev) )
  {
    if ( pLDevRet = RMDevToLDev( pLDev->pDevSibling, pDev ) )
    {
      return( pLDevRet );
    }
  }

  return( NULL );
}


/*--------------------------------------------------------*/
/*                                                        */
/* RMAdjunctToNodeList                                    */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/
VOID NEAR RMAdjToNodeList( PRMNODE pNode, PADJUNCT pAdj,
                              PADJNODELIST   pNodeList  )
{
  PADJUNCT      pNodeAdj;
  PSEARCHINFO   pSI;


  pNodeList->cNodes = 0;

  if ( pSI = (PSEARCHINFO) RMAlloc(sizeof(SEARCHINFO)) )
  {
    pSI->CmpLen    = pAdj->AdjLength - ADJ_HEADER_SIZE;
    pSI->pAdjNodeL = pNodeList;
    pSI->cMaxNodes = pNodeList->cMaxNodes;
    pSI->cNodes    = 0;
    pSI->pStartNode = pNode;
    pSI->pAdj       = pAdj;

    RMAdjToNodeListSub( pNode, pSI );

    pNodeList->cNodes = pSI->cNodes;

    RMFree( (PBYTE) pSI );
  }
}

VOID NEAR RMAdjToNodeListSub( PRMNODE pNode, PSEARCHINFO pSI )
{
  PADJUNCT      pNodeAdj;
  USHORT        i;
  USHORT        Len;

  pNodeAdj = 0;

  if ( pNode->Cookie == ADAPTER_NODE_COOKIE )
  {
    pNodeAdj = pNode->pAdpt->pAdjunctList;
  }
  else if ( pNode->Cookie == DEVICE_NODE_COOKIE )
  {
    pNodeAdj = pNode->pDev->pAdjunctList;
  }

  i = 0;
  while ( pNodeAdj )
  {
    if ( pNodeAdj->AdjType == pSI->pAdj->AdjType )
    {
      Len = pNodeAdj->AdjLength - ADJ_HEADER_SIZE;

      if ( Len > pSI->CmpLen )
      {
        Len = pSI->CmpLen;
      }

      if ( !memcmp( &pSI->pAdj->AdjBase, &pNodeAdj->AdjBase, Len ) )
      {
        if ( pSI->cNodes < pSI->cMaxNodes );
        {
          pSI->pAdjNodeL->Adj[pSI->cNodes].pNode = pNode;
          pSI->pAdjNodeL->Adj[pSI->cNodes].AdjIndex = i;
        }
        pSI->cNodes++;
      }
    }
    i++;
    pNodeAdj = pNodeAdj->pNextAdj;
  }

  if ( pNode->pDevChild )
  {
    RMAdjToNodeListSub( pNode->pDevChild, pSI );
  }

  if ( pNode->pDevSibling && (pNode != pSI->pStartNode) )
  {
    RMAdjToNodeListSub( pNode->pDevSibling, pSI );
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMKeyToNodeList                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/


VOID FAR  f_RMKeyToNodeList( PSZ pKey, PRMNODE pNode, PNODELIST pNodeList )
{
  RMKeyToNodeList( pKey, pNode, pNodeList );
}

VOID NEAR RMKeyToNodeList( PSZ pKey, PRMNODE pNode, PNODELIST pNodeList )
{
  USHORT        l;
  PSEARCHINFO   pSI;


  pNodeList->cNodes = 0;

  if ( pSI = (PSEARCHINFO) RMAlloc(sizeof(SEARCHINFO)) )
  {
    pSI->pNodeL     = pNodeList;
    pSI->cMaxNodes  = pNodeList->cMaxNodes;
    pSI->cNodes     = 0;
    pSI->pStartNode = pNode;

    if ( (l=strlen(pKey)) > 16 )
    {
      l = 17;
    }

    RMCpyKey( pSI->SearchKey, pKey );

    pSI->CmpLen = 16;

    if ( pKey[l-1] == '*' )
    {
      pSI->CmpLen = l-1;
    }


    RMKeyToNodeSub( pNode, pSI );

    pNodeList->cNodes = pSI->cNodes;

    RMFree( (PBYTE) pSI );
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMKeyToNodeSub                                         */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMKeyToNodeSub( PRMNODE pNode, PSEARCHINFO pSI )
{
  PSZ   pNodeKey;

  if ( pNode->Cookie == ADAPTER_NODE_COOKIE )
  {
    pNodeKey = pNode->pAdpt->AdaptDescriptName;
  }
  else if ( pNode->Cookie == DEVICE_NODE_COOKIE )
  {
    pNodeKey = pNode->pDev->DevDescriptName;
  }

  RMCpyKey( pSI->NodeKey, pNodeKey );

  if ( !memcmp( pSI->SearchKey, pSI->NodeKey, pSI->CmpLen ) )
  {
    if ( pSI->cMaxNodes > pSI->cNodes )
    {
      pSI->pNodeL->pNodes[pSI->cNodes] = pNode;
    }

    pSI->cNodes++;
  }

  if ( pNode->pDevChild )
  {
    RMKeyToNodeSub( pNode->pDevChild, pSI );
  }
  if ( pNode->pDevSibling && (pNode != pSI->pStartNode) )
  {
    RMKeyToNodeSub( pNode->pDevSibling, pSI );
  }

}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCpyKey                                               */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

#define toupper(c) (((c >= 'a') && (c <= 'z')) ? c + 'A' - 'a' : c )

VOID NEAR RMCpyKey( PSZ d, PSZ s )
{
  UCHAR         c;
  USHORT        i;

  memset( d, ' ', 16 );

  for ( i=0; (c = toupper(s[i])) && ( c != ' ' ) && i < 16; i++ )
  {
    d[i] = c;
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMResourceToNodeList                                   */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID FAR f_RMResourceToNodeList( PRESOURCESTRUCT pRes, PNODELIST pNodeList )
{
  RMResourceToNodeList( pRes, pNodeList );
}

VOID NEAR RMResourceToNodeList( PRESOURCESTRUCT pRes, PNODELIST pNodeList )
{
  pNodeList->cNodes = 0;

  switch ( pRes->ResourceType )
  {
    case RS_TYPE_IO:
      RMCheckIOConflictSub(  &pRes->IOResource,  NULL, RMNodeListFcn, pNodeList );
      break;
    case RS_TYPE_IRQ:
      RMCheckIRQConflictSub( &pRes->IRQResource, NULL, RMNodeListFcn, pNodeList );
      break;
    case RS_TYPE_DMA:
      RMCheckDMAConflictSub( &pRes->DMAResource, NULL, RMNodeListFcn, pNodeList );
      break;
    case RS_TYPE_TIMER:
      RMCheckTMRConflictSub( &pRes->TMRResource, NULL, RMNodeListFcn, pNodeList );
      break;
    case RS_TYPE_MEM:
      RMCheckMEMConflictSub( &pRes->MEMResource, NULL, RMNodeListFcn, pNodeList );
      break;
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMNodeListFcn                                          */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/


USHORT NEAR RMNodeListFcn( PRESNODE pResNode, PNODELIST pNodeList )
{
  if ( pNodeList->cNodes < pNodeList->cMaxNodes )
  {
    pNodeList->pNodes[pNodeList->cNodes] = pResNode->pDevUser;
  }
  pNodeList->cNodes++;

  return( 0 );
}


