/*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 =  RSMRSRC.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Resource 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"

/*--------------------------------------------------------*/
/*                                                        */
/* RMCreateResourceClass                                  */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR  f_RMRegisterResourceClass( USHORT  ResClass,
                                       USHORT  ResOrdinal,
                                       PRMNODE pDevNode             )
{
  return ( RMRegisterResourceClass( ResClass, ResOrdinal, pDevNode ) );
}

USHORT NEAR RMRegisterResourceClass( USHORT  ResClass,
                                     USHORT  ResOrdinal,
                                     PRMNODE pDevNode             )
{
  USHORT        ResIndex = 0;
  PRESHDR       pResHdrPrev, pResHdr, pResHdrNew;


  switch ( ResClass )
  {
    case RS_TYPE_IO:
    case RS_TYPE_IRQ:
    case RS_TYPE_MEM:
    case RS_TYPE_DMA:
    case RS_TYPE_TIMER:
      ResIndex = ResClass;
      break;
    case RS_TYPE_NEW:
      if ( NumResClasses < MAX_RESOURCE_CLASSES )
      {
        ResIndex = NumResClasses++;
      }
  }

  if ( ResIndex )
  {
    if ( pResHdrNew = (PRESHDR) RMAlloc( sizeof(RESHDR) ) )
    {
      pResHdrNew->pDevParent = pDevNode;
      pResHdrNew->ResClass   = ResClass;
      pResHdrNew->ResOrdinal = ResOrdinal;
      pResHdrNew->Cookie     = RESOURCE_HDR_COOKIE;
    }

    pResHdrPrev = 0;
    pResHdr     = ResHeader[ResIndex];
    while ( pResHdr )
    {
      if ( pResHdr->ResOrdinal > ResOrdinal )
      {
        break;
      }
      pResHdrPrev = pResHdr;
      pResHdr     = pResHdr->pResHdrSibling;
    }

    if ( pResHdrPrev )
    {
      pResHdrNew->pResHdrSibling  = pResHdrPrev->pResHdrSibling;
      pResHdrPrev->pResHdrSibling = pResHdrNew;
    }
    else
    {
      ResHeader[ResIndex] = pResHdrNew;
    }
  }

  return( ResIndex );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMAddResource                                          */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID FAR  f_RMAddResource( PRMNODE pNode, PRESNODE pResourceNode )
{
  return( RMAddResource( pNode, pResourceNode ) );
}

VOID NEAR RMAddResource( PRMNODE pNode, PRESNODE pResourceNode )
{
  PRESNODE      pRes,    pResPrev;
  PRESNODE      FAR     *ppResChain;
  PDRVRNODE              pDrvrNode;

  /*-------------------------------------------------*/
  /* This code needs to work with both RMNODEs and   */
  /* DRVRNODEs                                       */
  /*-------------------------------------------------*/


  if (pNode->Cookie == DRIVER_NODE_COOKIE)
  {
     ppResChain = &((PDRVRNODE)pNode)->pResChain;
     pDrvrNode  = (PDRVRNODE)pNode;
  }
  else
  {
     ppResChain = &pNode->pResChain;
     pDrvrNode  = pNode->pDriver;
  }

  pRes     = *ppResChain;
  pResPrev = 0;

  while ( pRes )
  {
    pResPrev = pRes;
    pRes     = pRes->pResDevChain;
  }

  if ( !pResPrev )
  {
    *ppResChain = pResourceNode;
  }
  else
  {
    pResPrev->pResDevChain = pResourceNode;
  }
  pResourceNode->pResDevChain = 0;
  pResourceNode->pDevUser     = pNode;

  switch ( pResourceNode->ResourceType )
  {
    case RS_TYPE_IO:
      RMAddIOResource( pNode, pResourceNode );
      break;
    case RS_TYPE_MEM:
      RMAddMEMResource( pNode, pResourceNode );
      break;
    case RS_TYPE_IRQ:
    case RS_TYPE_DMA:
    case RS_TYPE_TIMER:
      RMAddDMAorIRQResource( pNode, pResourceNode );
      break;
    default:
      _asm { int 3 }
  }

  if ( pDrvrNode == (PDRVRNODE) PDevPtrs[PDEV_KRNLDD] )
  {
    RMTraceAlloc( (USHORT)      RSM_TRACE_ALLOCATE,
                  (PDRVRNODE)   pDrvrNode,
                  (USHORT)      pResourceNode->ResourceType,
                  (PIORESOURCE) pResourceNode->pIO,
                  (USHORT)      0         );
  }

}


/*--------------------------------------------------------*/
/*                                                        */
/* RMIOAddResource                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMAddIOResource( PRMNODE pNode, PRESNODE pResNodeNew )
{
  PRESHDR       pResHdr;
  PIORESOURCE   pIONew;
  PRESNODE      pResNodePrev, pResNode;

  pIONew = pResNodeNew->pIO;

  if ( !(pResHdr = ResHeader[RS_TYPE_IO]) )
  {
    _asm int 3;
  }

  pResNodePrev = 0;
  pResNode     = pResHdr->pResUsers;

  while ( pResNode )
  {
    if ( pResNode->pIO->BaseIOPort > pIONew->BaseIOPort )
    {
      break;
    }
    pResNodePrev = pResNode;
    pResNode = pResNode->pResUsers;
  }

  if ( pResNodePrev )
  {
    pResNodeNew->pResUsers  = pResNodePrev->pResUsers;
    pResNodePrev->pResUsers = pResNodeNew;
  }
  else
  {
    pResNodeNew->pResUsers = pResHdr->pResUsers;
    pResHdr->pResUsers     = pResNodeNew;
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMAddMemResource                                       */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/


VOID NEAR RMAddMEMResource( PRMNODE pNode, PRESNODE pResNodeNew )
{
{
  PRESHDR        pResHdr;
  PMEMRESOURCE   pMEMNew;
  PRESNODE       pResNodePrev, pResNode;


  if ( !(pResHdr = ResHeader[RS_TYPE_MEM]) )
  {
    _asm int 3;
  }

  pMEMNew = pResNodeNew->pMEM;

  pResNodePrev = 0;
  pResNode     = pResHdr->pResUsers;

  while ( pResNode )
  {
    if ( pResNode->pMEM->MemBase > pMEMNew->MemBase )
    {
      break;
    }
    pResNodePrev = pResNode;
    pResNode = pResNode->pResUsers;
  }

  if ( pResNodePrev )
  {
    pResNodeNew->pResUsers  = pResNodePrev->pResUsers;
    pResNodePrev->pResUsers = pResNodeNew;
  }
  else
  {
    pResNodeNew->pResUsers = pResHdr->pResUsers;
    pResHdr->pResUsers     = pResNodeNew;
  }
}
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMAddIRQorDMAResource                                  */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/


VOID NEAR RMAddDMAorIRQResource( PRMNODE pNode, PRESNODE pResourceNode )
{
  PRESHDR       pResHdr;
  PRESNODE      pResNode, pResNodePrev;

  USHORT        ResClass, ResOrdinal;

  ResClass = pResourceNode->ResourceType;

  switch ( ResClass )
  {
    case RS_TYPE_DMA:
      ResOrdinal = pResourceNode->pDMA->DMAChannel;
      break;
    case RS_TYPE_IRQ:
      ResOrdinal = pResourceNode->pIRQ->IRQLevel;
      break;
    case RS_TYPE_TIMER:
      ResOrdinal = pResourceNode->pTMR->TMRChannel;
      break;
    default:
      _asm int 3
  }

  if ( pResHdr=RMFindResourceHdr(ResClass, ResOrdinal) )
  {
    pResNode     = pResHdr->pResUsers;
    pResNodePrev = 0;

    while( pResNode )
    {
      pResNodePrev = pResNode;
      pResNode     = pResNode->pResUsers;
    }

    if ( pResNodePrev )
    {
      pResNodePrev->pResUsers = pResourceNode;
    }
    else
    {
      pResHdr->pResUsers      = pResourceNode;
    }

    pResourceNode->pResUsers = 0;
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMFindResourceHdr                                      */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/


PRESHDR NEAR RMFindResourceHdr( USHORT ResClass, USHORT ResOrdinal )
{
  PRESHDR       pResHdr;

  if ( !(pResHdr = ResHeader[ResClass]) )
  {
    _asm int 3;
  }

  while ( pResHdr && (pResHdr->ResOrdinal != ResOrdinal) )
  {
    pResHdr = pResHdr->pResHdrSibling;
  }

  return ( pResHdr );
}



/*--------------------------------------------------------*/
/*                                                        */
/* RMUnlinkResourceNode                                   */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMUnlinkResourceNode( PRESNODE pResNodeDel )
{

  PRESNODE      FAR *ppResChain;
  PRESNODE      pResNode, pResNodePrev;
  PRMNODE       pDevOwner;
  PRESHDR       pResHdr;

  USHORT        ResClass;
  USHORT        ResOrdinal;


  if ( pDevOwner=pResNodeDel->pDevUser )
  {
    if ( pDevOwner->Cookie == DRIVER_NODE_COOKIE )
    {
      ppResChain = &((PDRVRNODE) pDevOwner)->pResChain;
    }
    else
    {
      ppResChain = &pDevOwner->pResChain;
    }

    if ( pResNode = *ppResChain )
    {
      pResNodePrev = 0;

      while( pResNode && (pResNode != pResNodeDel) )
      {
        pResNodePrev = pResNode;
        pResNode     = pResNode->pResDevChain;
      }

      if ( pResNode )
      {
        if ( pResNodePrev )
        {
          pResNodePrev->pResDevChain = pResNode->pResDevChain;
        }
        else
        {
          *ppResChain = pResNode->pResDevChain;
        }
        pResNode->pDevUser     = 0;
        pResNode->pResDevChain = 0;
      }

    }
  }

  ResClass = pResNodeDel->ResourceType;

  switch ( ResClass )
  {
    case RS_TYPE_DMA:
      ResOrdinal = pResNodeDel->pDMA->DMAChannel;
      break;
    case RS_TYPE_IRQ:
      ResOrdinal = pResNodeDel->pIRQ->IRQLevel;
      break;
    case RS_TYPE_TIMER:
      ResOrdinal = pResNodeDel->pTMR->TMRChannel;
      break;
    default:
      ResOrdinal = 0;
      break;
  }


  if ( !(pResHdr = RMFindResourceHdr(ResClass, ResOrdinal)) )
  {
    return( 1 );
  }

  pResNode     = pResHdr->pResUsers;
  pResNodePrev = 0;

  while( pResNode && (pResNode != pResNodeDel) )
  {
    pResNodePrev = pResNode;
    pResNode     = pResNode->pResUsers;
  }

  if ( pResNode )
  {
    if ( pResNodePrev )
    {
      pResNodePrev->pResUsers = pResNode->pResUsers;
    }
    else
    {
      pResHdr->pResUsers = pResNode->pResUsers;
    }

    pResNode->pResUsers = 0;
  }

  return ( 0 );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckResConflict                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckResConflict( PRESOURCESTRUCT pRes, PRMNODE pAdptShare )
{
  return ( RMCheckResConflict( pRes, pAdptShare ) );
}


USHORT NEAR RMCheckResConflict( PRESOURCESTRUCT pRes, PRMNODE pAdptShare )
{
  USHORT rc;

  switch ( pRes->ResourceType )
  {
    case RS_TYPE_IO:
      rc = RMCheckIOConflict( &pRes->IOResource, pAdptShare );
      break;
    case RS_TYPE_MEM:
      rc = RMCheckMEMConflict( &pRes->MEMResource );
      break;
    case RS_TYPE_IRQ:
      rc = RMCheckIRQConflict( &pRes->IRQResource );
      break;
    case RS_TYPE_DMA:
      rc = RMCheckDMAConflict( &pRes->DMAResource );
      break;
    case RS_TYPE_TIMER:
      rc = RMCheckTMRConflict( &pRes->TMRResource );
      break;
    default:
      _asm { int 3 }
  }

  return ( rc );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckIOConflict                                      */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckIOConflict( PIORESOURCE pIO, PRMNODE pAdptShare )
{
  return ( RMCheckIOConflict( pIO, pAdptShare ) );
}

USHORT NEAR RMCheckIOConflict( PIORESOURCE pIO, PRMNODE pAdptShare )
{
  return ( RMCheckIOConflictSub( pIO, pAdptShare, NULL, NULL ) );
}

USHORT NEAR RMCheckIOConflictSub( PIORESOURCE pIO, PRMNODE pAdptShare,
                                  PRMFN pRMFcn,    PVOID pRMFcnParm     )
{
  PIORESOURCE   pIOCur;

  PRESHDR       pResHdr;
  PRESNODE      pResNodePrev, pResNode;

  USHORT        PortNewLow, PortNewCount;
  USHORT        PortNew0,   PortNew1;
  USHORT        PortCur0,   PortCur1;

  USHORT        fShareNew;
  USHORT        fMultiplexNew;                                      /*@V103757*/

  USHORT        IOLines;
  USHORT        IOLinesNew;

  USHORT        Mask;

  USHORT        rc = 0;

  if ( !(pResHdr = ResHeader[RS_TYPE_IO]) )
  {
    _asm int 3;
  }

  PortNewLow   = pIO->BaseIOPort;
  PortNewCount = pIO->NumIOPorts - 1;

  fShareNew       = pIO->IOFlags & RS_IO_SHARED;
  fMultiplexNew   = pIO->IOFlags & RS_IO_MULTIPLEXED;               /*@V103757*/

  IOLinesNew  = pIO->IOAddressLines;

  pResNodePrev = 0;
  pResNode     = pResHdr->pResUsers;

  while ( pResNode )
  {
    pIOCur = pResNode->pIO;

    IOLines = pIOCur->IOAddressLines;
    if ( IOLinesNew < IOLines )
    {
      IOLines = IOLinesNew;
    }

    Mask = CalcDecodeMask( IOLines );

    PortNew0 = Mask     & PortNewLow;
    PortNew1 = PortNew0 + PortNewCount;

    PortCur0 = Mask     & pIOCur->BaseIOPort;
    PortCur1 = PortCur0 + pIOCur->NumIOPorts - 1;

    if ( !((PortNew1 < PortCur0) || (PortNew0 > PortCur1)) )
    {
      if ( pAdptShare == pResNode->pDevUser->pDevParent )
      {
        ;
      }
      else if ( fShareNew && (pIOCur->IOFlags & RS_IO_SHARED) )
      {
        ;
      }
      else if ( fMultiplexNew && (pIOCur->IOFlags & RS_IO_MULTIPLEXED) )/*@V103757*/
      {                                                             /*@V103757*/
        ;                                                           /*@V103757*/
      }                                                             /*@V103757*/
      else
      {
        rc = 1;
        if ( !pRMFcn || (rc=(*pRMFcn)(pResNode, pRMFcnParm)) )
        {
          break;
        }
      }
    }
    pResNodePrev = pResNode;
    pResNode     = pResNode->pResUsers;
  }
  return ( rc );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckIRQConflict                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckIRQConflict( PIRQRESOURCE pIRQ )
{
  return ( RMCheckIRQConflict( pIRQ ) );
}

USHORT NEAR RMCheckIRQConflict( PIRQRESOURCE pIRQ )
{
  return ( RMCheckIRQConflictSub( pIRQ, NULL, NULL, NULL ) );
}

USHORT NEAR RMCheckIRQConflictSub( PIRQRESOURCE pIRQ, PRMNODE pUnused,
                                   PRMFN pRMFcn,      PVOID pRMFcnParm )
{
  USHORT        rc = 1;

  PRESHDR       pResHdr;
  PRESNODE      pResNode;
  PIRQRESOURCE  pIRQCur;

  USHORT        fExclusive, fShare, fMultiplex;

  if ( pResHdr=RMFindResourceHdr(RS_TYPE_IRQ, pIRQ->IRQLevel) )
  {
    rc = 0;

    fShare     = pIRQ->IRQFlags & RS_IRQ_SHARED;
    fMultiplex = pIRQ->IRQFlags & RS_IRQ_MULTIPLEXED;
    fExclusive = pIRQ->IRQFlags & RS_IRQ_EXCLUSIVE;

    pResNode = pResHdr->pResUsers;

    while ( pResNode )
    {
      pIRQCur = pResNode->pIRQ;

      if ( fExclusive || (pIRQCur->IRQFlags & RS_IRQ_EXCLUSIVE) )
      {
        rc = 1;
      }
      else if ( fShare && !(pIRQCur->IRQFlags & RS_IRQ_SHARED) )
      {
        rc = 1;
      }
      else if ( fMultiplex && !(pIRQCur->IRQFlags & RS_IRQ_MULTIPLEXED) )
      {
        rc = 1;
      }
      if ( rc )
      {
        if ( !pRMFcn || (rc=(*pRMFcn)(pResNode, pRMFcnParm)) )
        {
          break;
        }
      }
      pResNode = pResNode->pResUsers;
    }
  }
  return( rc );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckDMAConflict                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckDMAConflict( PDMARESOURCE pDMA )
{
  return ( RMCheckDMAConflict( pDMA ) );
}

USHORT NEAR RMCheckDMAConflict( PDMARESOURCE pDMA )
{
  return ( RMCheckDMAConflictSub( pDMA, NULL, NULL, NULL ) );
}

USHORT NEAR RMCheckDMAConflictSub( PDMARESOURCE pDMA, PRMNODE pUnused,
                                   PRMFN pRMFcn,      PVOID   pRMFcnParm )
{
  USHORT        rc = 1;

  PRESHDR       pResHdr;
  PRESNODE      pResNode;
  PDMARESOURCE  pDMACur;

  USHORT        fExclusive, fShare, fMultiplex;

  if ( pResHdr=RMFindResourceHdr(RS_TYPE_DMA, pDMA->DMAChannel) )
  {
    rc = 0;

    fShare     = pDMA->DMAFlags & RS_DMA_SHARED;
    fMultiplex = pDMA->DMAFlags & RS_DMA_MULTIPLEXED;
    fExclusive = pDMA->DMAFlags & RS_DMA_EXCLUSIVE;

    pResNode = pResHdr->pResUsers;

    while ( pResNode )
    {
      pDMACur = pResNode->pDMA;

      if ( fExclusive || (pDMACur->DMAFlags & RS_DMA_EXCLUSIVE) )
      {
        rc = 1;
      }
      else if ( fShare && !(pDMACur->DMAFlags & RS_DMA_SHARED) )
      {
        rc = 1;
      }
      else if ( fMultiplex && !(pDMACur->DMAFlags & RS_DMA_MULTIPLEXED) )
      {
        rc = 1;
      }
      if ( rc )
      {
        if ( !pRMFcn || (rc=(*pRMFcn)(pResNode, pRMFcnParm)) )
        {
          break;
        }
      }

      pResNode = pResNode->pResUsers;
    }
  }
  return( rc );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckTMRConflict                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckTMRConflict( PTMRRESOURCE pTMR )
{
  return ( RMCheckTMRConflict( pTMR ) );
}

USHORT NEAR RMCheckTMRConflict( PTMRRESOURCE pTMR )
{
  return ( RMCheckTMRConflictSub( pTMR, NULL, NULL, NULL ) );
}

USHORT NEAR RMCheckTMRConflictSub( PTMRRESOURCE pTMR,   PRMNODE pUnused,
                                   PRMFN        pRMFcn, PVOID   pRMFcnParm )
{
  USHORT        rc = 1;

  PRESHDR       pResHdr;
  PRESNODE      pResNode;
  PTMRRESOURCE  pTMRCur;

  USHORT        fExclusive, fShare, fMultiplex;

  if ( pResHdr=RMFindResourceHdr(RS_TYPE_TIMER, pTMR->TMRChannel) )
  {
    rc = 0;

    fShare     = pTMR->TMRFlags & RS_TMR_SHARED;
    fMultiplex = pTMR->TMRFlags & RS_TMR_MULTIPLEXED;
    fExclusive = pTMR->TMRFlags & RS_TMR_EXCLUSIVE;

    pResNode = pResHdr->pResUsers;

    while ( pResNode )
    {
      pTMRCur = pResNode->pTMR;

      if ( fExclusive || (pTMRCur->TMRFlags & RS_TMR_EXCLUSIVE) )
      {
        rc = 1;
      }
      else if ( fShare && !(pTMRCur->TMRFlags & RS_TMR_SHARED) )
      {
        rc = 1;
      }
      else if ( fMultiplex && !(pTMRCur->TMRFlags & RS_TMR_MULTIPLEXED) )
      {
        rc = 1;
      }
      if ( rc )
      {
        if ( !pRMFcn || (rc=(*pRMFcn)(pResNode, pRMFcnParm)) )
        {
          break;
        }
      }

      pResNode = pResNode->pResUsers;
    }
  }
  return( rc );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMCheckMEMConflict                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR f_RMCheckMEMConflict( PMEMRESOURCE pMEM )
{
  return ( RMCheckMEMConflict( pMEM ) );
}

USHORT NEAR RMCheckMEMConflict( PMEMRESOURCE pMEM )
{
  return ( RMCheckMEMConflictSub( pMEM, NULL, NULL, NULL ) );
}

USHORT NEAR RMCheckMEMConflictSub( PMEMRESOURCE pMEM, PRMNODE pAdptShare,
                                   PRMFN pRMFcn,    PVOID pRMFcnParm     )
{

  PRESHDR       pResHdr;
  PRESNODE      pResNodePrev, pResNode;

  PMEMRESOURCE  pMEMCur;

  ULONG         MemNew0,   MemNew1;
  ULONG         MemCur0,   MemCur1;

  USHORT        fShareNew;

  USHORT        rc = 0;

  if ( !(pResHdr = ResHeader[RS_TYPE_MEM]) )
  {
    _asm int 3;
  }

  if ( ((pMEM->MemBase+pMEM->MemSize) > MAX_MEM_RANGE) ||
                                   (pMEM->MemBase < MIN_MEM_RANGE)  )
  {
    return( 1 );
  }

  MemNew0   = pMEM->MemBase;
  MemNew1   = MemNew0 + pMEM->MemSize - 1 ;

  fShareNew   = pMEM->MemFlags & RS_MEM_SHARED;

  pResNodePrev = 0;
  pResNode     = pResHdr->pResUsers;

  while ( pResNode )
  {
    pMEMCur = pResNode->pMEM;

    MemCur0 = pMEMCur->MemBase;
    MemCur1 = MemCur0 + pMEMCur->MemSize - 1;

    if ( !((MemNew1 < MemCur0) || (MemNew0 > MemCur1)) )
    {
      if ( fShareNew && (pMEMCur->MemFlags & RS_MEM_SHARED) )
      {
        ;
      }
      else
      {
        rc = 1;
        if ( !pRMFcn || (rc=(*pRMFcn)(pResNode, pRMFcnParm)) )
        {
          break;
        }
      }
    }
    pResNodePrev = pResNode;
    pResNode     = pResNode->pResUsers;
  }
  return ( rc );

}


/*--------------------------------------------------------*/
/*                                                        */
/* RMFindIOPorts                                          */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMFindIOPorts( PIORESOURCE pIO )
{
  IORESOURCE   IOTmp;
  USHORT       Align;
  USHORT       rc = 1;                                              /*@V103757*/
  USHORT       MaxIOPort;

  *&IOTmp   = *pIO;

  Align     = CalcAlignMask( pIO->NumIOPorts );

  MaxIOPort = CalcDecodeMask( pIO->IOAddressLines ) - pIO->NumIOPorts;

  for ( IOTmp.BaseIOPort = (pIO->BaseIOPort + Align - 1) & ~(Align - 1);
        IOTmp.BaseIOPort < MaxIOPort;
        IOTmp.BaseIOPort += Align )
  {
    if ( !(rc = RMCheckIOConflictSub( &IOTmp, NULL, NULL, NULL )) )
    {
      break;
    }
  }

  if ( !rc )
  {
    *pIO = *&IOTmp;
  }

  return ( rc );
}


USHORT NEAR CalcDecodeMask( USHORT IOLines )
{
  USHORT i;
  USHORT Mask = 0;

  for ( i=0; i < IOLines; i++ )
  {
    Mask <<= 1;
    Mask  |= 1;
  }

  return( Mask );
}

USHORT NEAR CalcAlignMask( USHORT Num )
{
  USHORT i;
  USHORT Mask = 1;

  Num--;

  for ( i=0; (i < 16) && (Num >= Mask); i++)
  {
    Mask <<= 1;
  }

  return( Mask );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMFindMemSpace                                         */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMFindMemSpace( PMEMRESOURCE pMEM )
{
  MEMRESOURCE     MEMTmp;
  ULONG           MaxMem;

  USHORT          rc = 1;

  *&MEMTmp   = *pMEM;

  MaxMem =  MAX_MEM_RANGE - pMEM->MemSize;

  for ( MEMTmp.MemBase = pMEM->MemBase;
        MEMTmp.MemBase < MaxMem;
        MEMTmp.MemBase += (4*1024L) )
  {
    if ( !(rc = RMCheckMEMConflictSub( &MEMTmp, NULL, NULL, NULL )) )
    {
      break;
    }
  }

  if ( !rc )
  {
    *pMEM = *&MEMTmp;
  }

  return ( rc );
}
