/*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 =  RSMAPIR0.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Services for Ring 0 Clients
 *
 *
 *
 * 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 "iorb.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"

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMGetVersion                                        */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMGetVersion(PUCHAR pMajorVersion,
                                 PUCHAR pMinorVersion)
{
USHORT rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      rc = RMRC_IRQ_ENTRY_ILLEGAL;
      goto RSMGetVersionExit;
   }

   if ((pMajorVersion == NULL) || (pMinorVersion == NULL)){
      rc = RMRC_NULL_POINTER;
      goto RSMGetVersionExit;
   }

   *pMajorVersion = CMVERSION_MAJOR;
   *pMinorVersion = CMVERSION_MINOR;

   rc = RMRC_SUCCESS;

RSMGetVersionExit:

   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;

}


/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateDriver                                      */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateDriver(PDRIVERSTRUCT pDriverStruct,
                                   PHDRIVER phDriver)
{
   ULONG      hDriver;
   PDRVRNODE  pRMDriver;
   USHORT     rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if (pDriverStruct == NULL){
       rc = RMRC_NULL_POINTER;
       goto RSMCreateDriverExit;
   }

   /*------------------------------------*/
   /*   Force string information         */
   /*------------------------------------*/

   if ( (pDriverStruct->DrvrName     == NULL) ||
        (pDriverStruct->DrvrDescript == NULL) ||
        (pDriverStruct->VendorName   == NULL) ) {
      rc = RMRC_NULL_STRINGS;
      goto RSMCreateDriverExit;
   }

   /*------------------------------------------*/
   /*   Must be less than or equal to version  */
   /*------------------------------------------*/

   if ( (!((pDriverStruct->MajorVer) <= CMVERSION_MAJOR) &&
          ((pDriverStruct->MinorVer) <= CMVERSION_MINOR)) ) {
      rc = RMRC_BAD_VERSION;
      goto RSMCreateDriverExit;
   }

   /*------------------------------------------*/
   /*   Create Driver Storage and copy         */
   /*------------------------------------------*/

   pRMDriver = RMCreateDriverNode( pDriverStruct );

   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   DriverState |= DRIVER_CREATED;

   *phDriver = (HDRIVER)RMMAKEHANDLE(pRMDriver);

   rc = RMRC_SUCCESS;

RSMCreateDriverExit:

   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;

}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDestroyDriver                                     */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDestroyDriver(HDRIVER hDriver)
{
PDRVRNODE pDrvrNode;
USHORT     rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*----------------------------------*/
   /* Get pointer to my Driver         */
   /*----------------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle((RMHANDLE)hDriver,
                                             DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDestroyDriverExit;
   }

   /*----------------------------------*/
   /* Free any Resources on ResChain   */
   /*----------------------------------*/

   while(pDrvrNode->pResChain)
   {
      RMDeleteResourceNode(pDrvrNode->pResChain);
   }

   /*----------------------------------*/
   /* Free any Resources on DevChain   */
   /*----------------------------------*/

   if (pDrvrNode->pDevChain)
   {
      RMDestroyRMNode( pDrvrNode->pDevChain->pDriver,
                       pDrvrNode->pDevChain          );
   }


   /*---------------------------*/
   /* Delete this Drivers Node  */
   /*---------------------------*/

   RMDeleteDriverNode( pDrvrNode );

   rc = RMRC_SUCCESS;

RSMDestroyDriverExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateAdapter                                     */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateAdapter(HDRIVER hDriver,
                                    PHADAPTER phAdapter,
                                    PADAPTERSTRUCT pAdapterStruct,
                                    HDEVICE hDevice,
                                    PAHRESOURCE pahResource)
{
PRMNODE     pNode;
PRMNODE     pParentNode;
PDRVRNODE   pDrvrNode;
PRESNODE    pResNode;
USHORT      i;
USHORT     rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*-----------------------------*/
   /*   Null pointer checks       */
   /*-----------------------------*/

   if ((pAdapterStruct == NULL)||(phAdapter==NULL)){
      rc = RMRC_NULL_POINTER;
      goto RSMCreateAdapterExit;
   }

   if (pAdapterStruct->AdaptDescriptName == NULL){
      rc = RMRC_NULL_STRINGS;
      goto RSMCreateAdapterExit;
   }

   /*----------------------------------*/
   /* Get pointer to my Driver         */
   /*----------------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle((RMHANDLE)hDriver,
                                             DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMCreateAdapterExit;
   }

   /*--------------------------------*/
   /* Get pointer to Parent Node     */
   /*--------------------------------*/

   if (hDevice != NULL) {
      pParentNode = RMNodeFromHandle( (RMHANDLE)hDevice, DEVICE_NODE_COOKIE);
      if (pParentNode == NULL) {
         rc = RMRC_BAD_DRIVERHANDLE;
         goto RSMCreateAdapterExit;
      }
   } else {
      pParentNode = RMNodeFromBusType(pAdapterStruct->HostBusType);
   }

   /*------------------------------------------------------------*/
   /* Check that my driver owns these resources and haven't been */
   /* given to another of my adapter structs                     */
   /*------------------------------------------------------------*d */

   if (pahResource)
   {
      for (i=0;i<pahResource->NumResource;i++)
      {
         pResNode = (PRESNODE)RMNodeFromHandle((RMHANDLE)pahResource->hResource[i],
                                               RESOURCE_NODE_COOKIE);
         if ((pResNode == NULL) || (pResNode->pDevUser != (PRMNODE)pDrvrNode)) {
            rc = RMRC_BAD_RESOURCEHANDLE;
            goto RSMCreateAdapterExit;
         }
      }
   }



   /*----------------------------------------*/
   /* Create my Adapter                      */
   /*----------------------------------------*/

   pNode = RMCreateAdapterNode( pAdapterStruct);

   /*---------------------*/
   /* Attach Resources    */
   /*---------------------*/
   if (pahResource)
   {
      for (i=0;i<pahResource->NumResource;i++)
      {
         pResNode = (PRESNODE)RMNodeFromHandle((RMHANDLE)pahResource->hResource[i],
                                               RESOURCE_NODE_COOKIE);
         RMUnlinkResourceNode(pResNode);
         RMAddResource(pNode, pResNode);
      }
   }

   /*-------------------*/
   /* Register Driver   */
   /*-------------------*/

   RMRegisterNode( pDrvrNode, pNode);

   /*----------------------------------------*/
   /* Place in Node Tree                     */
   /*----------------------------------------*/

   RMAddChild( pParentNode, pNode );

   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   *phAdapter = (HADAPTER)RMMAKEHANDLE(pNode);

   rc = RMRC_SUCCESS;

RSMCreateAdapterExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDestroyAdapter                                    */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDestroyAdapter(HDRIVER hDriver,
                                     HADAPTER hAdapter)
{
PDRVRNODE pDrvrNode;
PRMNODE   pAdptNode;
USHORT     rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   if ((pAdptNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hAdapter,
                                                ADAPTER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_ADAPTERHANDLE;
      goto RSMDestroyAdapterExit;
   }

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDestroyAdapterExit;
   }

   /*----------------------------------------*/
   /* Destroy Adapter - Call Generic Destroy */
   /*----------------------------------------*/

   rc = RMDestroyRMNode(pDrvrNode, pAdptNode);

RSMDestroyAdapterExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}


/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateDevice                                      */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateDevice(HDRIVER hDriver,
                                   PHDEVICE phDevice,
                                   PDEVICESTRUCT pDeviceStruct,
                                   HADAPTER hAdapter,
                                   PAHRESOURCE pahResource)
{
PRMNODE       pNode;
PRMNODE       pParentNode;
PDRVRNODE     pDrvrNode;
PRESNODE      pResNode;
USHORT        i;
USHORT        rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*-----------------------------*/
   /*   Null pointer checks       */
   /*-----------------------------*/

   if ((pDeviceStruct == NULL)||(phDevice==NULL)){
      rc = RMRC_NULL_POINTER;
      goto RSMCreateDeviceExit;
   }

   if (pDeviceStruct->DevDescriptName == NULL){
      rc = RMRC_NULL_STRINGS;
      goto RSMCreateDeviceExit;
   }

   /*----------------------------------*/
   /* Get pointer to my Driver         */
   /*----------------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle((RMHANDLE)hDriver,
                                              DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMCreateDeviceExit;
   }

   /*--------------------------------*/
   /* Get pointer to Parent Node     */
   /*--------------------------------*/

   if (hAdapter != NULL) {
      pParentNode = RMNodeFromHandle( (RMHANDLE)hAdapter, ADAPTER_NODE_COOKIE);
      if (pParentNode == NULL) {
         rc = RMRC_BAD_DRIVERHANDLE;
         goto RSMCreateDeviceExit;
      }
   } else {
      rc = RMRC_BAD_ADAPTERHANDLE;
      goto RSMCreateDeviceExit;
   }


   /*------------------------------------------------------------*/
   /* Check that my driver owns these resources and haven't been */
   /* given to another of my adapter structs                     */
   /*------------------------------------------------------------*/

   if (pahResource)
   {
      for (i=0;i<pahResource->NumResource;i++)
      {
         pResNode = (PRESNODE)RMNodeFromHandle((RMHANDLE)pahResource->hResource[i],
                                               RESOURCE_NODE_COOKIE);
         if ((pResNode == NULL) || (pResNode->pDevUser != (PRMNODE)pDrvrNode)) {
            rc = RMRC_BAD_RESOURCEHANDLE;
            goto RSMCreateDeviceExit;
         }
      }
   }

   /*----------------------------------------*/
   /* Create my Device                       */
   /*----------------------------------------*/

   pNode = RMCreateDeviceNode( pDeviceStruct);

   /*---------------------*/
   /* Attach Resources    */
   /*---------------------*/
   if (pahResource)
   {
      for (i=0;i<pahResource->NumResource;i++)
      {
         pResNode = (PRESNODE)RMNodeFromHandle((RMHANDLE)pahResource->hResource[i],
                                               RESOURCE_NODE_COOKIE);
         RMUnlinkResourceNode(pResNode);
         RMAddResource(pNode, pResNode);
      }
   }

   /*----------------------------------------*/
   /* Place in Node Tree                     */
   /*----------------------------------------*/

   RMRegisterNode( pDrvrNode, pNode);
   RMAddChild( pParentNode, pNode );

   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   *phDevice = (HDEVICE)RMMAKEHANDLE(pNode);

   rc = RMRC_SUCCESS;

RSMCreateDeviceExit:

   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDestroyDevice                                     */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDestroyDevice(HDRIVER hDriver,
                                    HDEVICE hDevice)
{
PDRVRNODE pDrvrNode;
PRMNODE   pDevNode;
USHORT    rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDestroyDeviceExit;
   }

   if ((pDevNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hDevice,
                                                DEVICE_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMDestroyDeviceExit;
   }

   /*----------------------------------------*/
   /* Destroy Device  - Call Generic Destroy */
   /*----------------------------------------*/

   rc = RMDestroyRMNode(pDrvrNode, pDevNode);

RSMDestroyDeviceExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;

}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMAllocResource                                     */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMAllocResource(HDRIVER hDriver,
                                    PHRESOURCE phResource,
                                    PRESOURCESTRUCT pResourceStruct)
{
PRMNODE          pNode;
PDRVRNODE        pDrvrNode = NULL;
PRESNODE         pResNode;
USHORT           rc;
USHORT           IOPort;
USHORT           IOLines;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if ((pResourceStruct == NULL)||(phResource == NULL)){
      rc = RMRC_NULL_POINTER;
      goto RSMAllocResourceExit;
   }

   /*--------------------------*/
   /* Get Driver Handle        */
   /*--------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                               DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMAllocResourceExit;
   }

   /*---------------------------------------*/
   /* If IO Resource request and search for */
   /* unallocated IO Ports requested        */
   /*---------------------------------------*/

   if ( pResourceStruct->ResourceType == RS_TYPE_IO )
   {
     IOLines = pResourceStruct->IOResource.IOAddressLines;
     IOPort  = pResourceStruct->IOResource.BaseIOPort;

     if ( (IOLines != 10) && (IOLines != 16) )
     {
       rc = RMRC_INVALID_PARM_VALUE;
       goto RSMAllocResourceExit;
     }

     if ( (IOLines != 16)
              && ((IOPort < MIN_ISA_PORT) || (IOPort > MAX_ISA_PORT)) )
     {
       rc = RMRC_INVALID_PARM_VALUE;
       goto RSMAllocResourceExit;
     }

     if ( pResourceStruct->IOResource.IOFlags & RS_SEARCH )
     {
        /*-----------------------------------------*/
        /* Update IOResource struct with available */
        /* IO Port range                           */
        /*-----------------------------------------*/
        if ( RMFindIOPorts( &pResourceStruct->IOResource ) ) {
           rc = RMRC_RES_ALREADY_CLAIMED;
           goto RSMAllocResourceExit;
        }
     }
   }
   /*----------------------------------------*/
   /* If MEM Resource request and search for */
   /* unallocated Memory space requested     */
   /*----------------------------------------*/

   else if ( (pResourceStruct->ResourceType == RS_TYPE_MEM) &&
              (pResourceStruct->MEMResource.MemFlags & RS_SEARCH)      )
   {
      /*------------------------------------------*/
      /* Update MEMResource struct with available */
      /* Memory  range                            */
      /*------------------------------------------*/
      if ( RMFindMemSpace( &pResourceStruct->MEMResource ) ) {
         rc =  RMRC_RES_ALREADY_CLAIMED;
         goto RSMAllocResourceExit;
      }
   }

   /*---------------------------*/
   /* Do normal conflict checks */
   /*---------------------------*/

   if (RMCheckResConflict( pResourceStruct, NULL)) {
      rc = RMRC_RES_ALREADY_CLAIMED;
      goto RSMAllocResourceExit;
   }

   /*-----------------------------*/
   /* Create Resource and link in */
   /*-----------------------------*/

   pResNode = RMCreateResourceNode( pResourceStruct );
   RMAddResource( (PRMNODE)pDrvrNode, pResNode);

   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   *phResource = (HRESOURCE)RMMAKEHANDLE(pResNode);

   rc = RMRC_SUCCESS;

RSMAllocResourceExit:

   if ( pDrvrNode && pResourceStruct )
   {
     RMTraceAlloc( (USHORT)      RSM_TRACE_ALLOCATE,
                   (PDRVRNODE)   pDrvrNode,
                   (USHORT)      pResourceStruct->ResourceType,
                   (PIORESOURCE) &pResourceStruct->IOResource,
                   (USHORT)      rc       );
   }

   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}


/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDeallocResource                                   */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDeallocResource(HDRIVER hDriver,
                                      HRESOURCE hResource)
{
PDRVRNODE      pDrvrNode;
PRESNODE       pResNode;
USHORT         rc = RMRC_SUCCESS;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDeallocResourceExit;
   }

   if ((pResNode = (PRESNODE)RMNodeFromHandle( (RMHANDLE)hResource,
                                                RESOURCE_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_RESOURCEHANDLE;
      goto RSMDeallocResourceExit;
   }

   if ( !(RMGetResFlags( pResNode ) & RS_NONOWNER_ALLOWED) )        /*@V103757*/
   {
     /*-------------------------------------*/
     /* Verify This Driver in some way      */
     /* manages this resource.  Either      */
     /* the resource is owned by hdriver or */
     /* or its adapter is owned by hdriver  */
     /*------------------------------------ */

     if (!( (pResNode->pDevUser == (PRMNODE)pDrvrNode) ||
            (pResNode->pDevUser->pDriver == pDrvrNode )) ) {
        rc = RMRC_BAD_DRIVERHANDLE;
        goto RSMDeallocResourceExit;
     }
   }

   RMTraceAlloc( (USHORT)      RSM_TRACE_DEALLOCATE,
                 (PDRVRNODE)   pDrvrNode,
                 (USHORT)      pResNode->ResourceType,
                 (PIORESOURCE) pResNode->pIO,
                 (USHORT)      rc );

   /*--------------------------*/
   /* Finally, Delete Resource */
   /*--------------------------*/

   RMDeleteResourceNode( pResNode);


RSMDeallocResourceExit:

   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/

   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMClaimResources                                    */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMClaimResources(HDRIVER hDriver,
                                     HADAPTER hAdapter)
{
   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMReleaseResources                                  */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMReleaseResources(HDRIVER hDriver,
                                       HADAPTER hAdapter)
{
   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateLDev                                        */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateLDev(HDRIVER hDriver,
                                 PHLDEV  phLDev,
                                 HDEVICE hDevice,
                                 PLDEVSTRUCT pLDevStruct)
{
   PDRVRNODE    pDrvrNode;
   PRMNODE      pLDevParent;
   PRMNODE      pLDev;
   PRMNODE      pDevAssoc=0;

   USHORT       LDevClass;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*--------------------------*/
   /* Get Driver Handle        */
   /*--------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                             DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMCreateLDevExit;
   }

   if ((pLDevStruct == NULL)||(phLDev == NULL))
   {
      rc = RMRC_NULL_POINTER;
      goto RSMCreateLDevExit;
   }

   LDevClass = pLDevStruct->LDevClass;

   if ( LDevClass > NumLDevClasses || LDevClass <= LDEV_CLASS_BASE )/*@V103757*/
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMCreateLDevExit;
   }
   pLDevParent = LDevPtrs[LDevClass];

   /*--------------------------*/
   /* Get Device Handle        */
   /*--------------------------*/

   if ( hDevice )
   {
     if ((pDevAssoc = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hDevice,
                                                  ANY_PHYS_COOKIE)) == NULL)
     {
        rc = RMRC_BAD_DEVICEHANDLE;
        goto RSMCreateLDevExit;
     }
   }

   /*--------------------------*/
   /* Create LDEV Node         */
   /*--------------------------*/
   pLDevStruct->LDevHDevice = hDevice;

   if ( !(pLDev = RMCreateLDEVNode( pLDevStruct )) )
   {
     rc = RMRC_OUT_OF_MEMORY;
     goto RSMCreateLDevExit;
   }

   /*-------------------*/
   /* Register Driver   */
   /*-------------------*/

   RMRegisterNode( pDrvrNode, pLDev);

   /*-----------------------------------------*/
   /* Link LDEV node to parent node for class */
   /*-----------------------------------------*/

   if ( RMLinkLDEVNode(pLDevParent, pLDev, pDevAssoc ) )
   {
     RMDeleteLDEVNode( pLDev );
     rc = RMRC_DEV_ALREADY_CLAIMED;
     goto RSMCreateLDevExit;
   }


   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   *phLDev = (HLDEV)RMMAKEHANDLE(pLDev);

   rc = RMRC_SUCCESS;

RSMCreateLDevExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDestroyLDev                                       */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDestroyLDev(HDRIVER hDriver,
                                  HLDEV   hLDev)
{
PDRVRNODE pDrvrNode;
PRMNODE   pLDevNode;
USHORT    rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDestroyLDevExit;
   }

   if ((pLDevNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hLDev,
                                                LDEV_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMDestroyLDevExit;
   }

   /*-------------------------------------*/
   /* Destroy LDev - Call Generic Destroy */
   /*-------------------------------------*/

   cRMLNodes--;
   cRMNodes++;
   rc = RMDestroyRMNode(pDrvrNode, pLDevNode);

RSMDestroyLDevExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateSysName                                     */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateSysName(HDRIVER hDriver,
                                    PHSYSNAME phSysName,
                                    HLDEV hLDev,
                                    PSYSNAMESTRUCT pSysNameStruct)
{

   PDRVRNODE    pDrvrNode;
   PRMNODE      pLDevParent;
   PRMNODE      pSysNameNode;
   USHORT       rc;


   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*--------------------------*/
   /* Get Driver Handle        */
   /*--------------------------*/

   pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                             DRIVER_NODE_COOKIE);
   if (pDrvrNode == NULL) {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMCreateSysNameExit;
   }

   if ((pSysNameStruct == NULL)||(phSysName == NULL))
   {
      rc = RMRC_NULL_POINTER;
      goto RSMCreateSysNameExit;
   }


   /*--------------------------*/
   /* Get LDev Parent Node     */
   /*--------------------------*/

   if ((pLDevParent = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hLDev,
                                                   ANY_LOG_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMCreateSysNameExit;
   }

   /*--------------------------*/
   /* Create SysName Node      */
   /*--------------------------*/

   if ( !(pSysNameNode = RMCreateSysNameNode( pSysNameStruct )) )
   {
      rc = RMRC_OUT_OF_MEMORY;
      goto RSMCreateSysNameExit;
   }

   /*-----------------------------------------*/
   /* Link SysName node to parent node        */
   /*-----------------------------------------*/

   RMRegisterNode( pDrvrNode, pSysNameNode );

   RMAddChild( pLDevParent, pSysNameNode );

   /*------------------------------------------*/
   /*   Calculate Handle                       */
   /*------------------------------------------*/

   *phSysName = (HSYSNAME)RMMAKEHANDLE(pSysNameNode);

   rc = RMRC_SUCCESS;

RSMCreateSysNameExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDestroySysName                                    */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDestroySysName(HDRIVER hDriver,
                                     HSYSNAME   hSysName)
{
PDRVRNODE pDrvrNode;
PRMNODE   pSysNameNode;
USHORT    rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMDestroySysNameExit;
   }

   if ((pSysNameNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hSysName,
                                                SYS_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMDestroySysNameExit;
   }

   /*-------------------------------------*/
   /* Destroy LDev - Call Generic Destroy */
   /*-------------------------------------*/

   cRMLNodes--;
   cRMNodes++;
   rc = RMDestroyRMNode(pDrvrNode, pSysNameNode);

RSMDestroySysNameExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMADDToHDEVICE                                      */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMADDToHDEVICE(PHDEVICE phDevice,
                                   USHORT ADDHandle,
                                   USHORT UnitHandle)
{
ADJUNCT         Adj;
PRMNODE         pRMNode;
ADJNODELIST     NodeList;
USHORT          rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*----------------*/
   /* Check Pointers */
   /*----------------*/

   if (!phDevice) {
      rc = RMRC_NULL_POINTER;
      goto RSMADDToHDEVICEExit;
   }


   NodeList.cNodes    = 0;
   NodeList.cMaxNodes = 1;

   /*-------------------*/
   /* Fill In Dummy Adj */
   /*-------------------*/

   memset( &Adj, 0, sizeof(ADJUNCT) );

   Adj.AdjType   = ADJ_ADD_UNIT;
   Adj.AdjLength = ADJ_HEADER_SIZE+sizeof(ADD_UNIT);

   Adj.Add_Unit.ADDHandle  = ADDHandle;
   Adj.Add_Unit.UnitHandle = UnitHandle;
   RMAdjToNodeList( PDevPtrs[PDEV_CPU_0], &Adj, (PADJNODELIST) &NodeList );


   if (!NodeList.cNodes) {
      rc = RMRC_SEARCH_FAILED;
      goto RSMADDToHDEVICEExit;
   }

   *phDevice = (HDEVICE)RMMAKEHANDLE( NodeList.Adj[0].pNode );

   rc = RMRC_SUCCESS;

RSMADDToHDEVICEExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMKeyToHandleList                                   */
/*   ------------------                                   */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMKeyToHandleList( HADAPTER    hStartNode,
                                       PSZ         Key,
                                       PHANDLELIST pHndList     )
{
   USHORT       i, j;
   PRMNODE      pNode;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*----------------*/
   /* Check Pointers */
   /*----------------*/

   if ( !Key || !pHndList ) {
      rc = RMRC_NULL_POINTER;
      goto RSMKeyToHandleListExit;
   }

   if ( !pHndList->cMaxHandles )
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMKeyToHandleListExit;
   }

   pHndList->cHandles = 0;

   if ( pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hStartNode,
                                            DRIVER_NODE_COOKIE) )
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMKeyToHandleListExit;
   }
   else if ( pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hStartNode,
                                                 ANY_COOKIE        ) )
   {
     ;
   }
   else
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMKeyToHandleListExit;
   }

   RMKeyToNodeList( Key, pNode, (PNODELIST) pHndList );

   if ( (j = pHndList->cHandles) > pHndList->cMaxHandles )
   {
     j = pHndList->cMaxHandles;
   }

   for ( i=0; i < j; i++ )
   {
     pHndList->Handles[i] = (HDEVICE)RMMAKEHANDLE( (PRMNODE) pHndList->Handles[i] );
   }
   rc = RMRC_SUCCESS;

RSMKeyToHandleListExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}


/*--------------------------------------------------------*/
/*                                                        */
/*   RSMHandleToType                                      */
/*   ---------------                                      */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMHandleToType( RMHANDLE  hHandle,
                                    PUSHORT   pHandleType )
{
   PRMNODE      pNode;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if ( !pHandleType )
   {
     rc = RMRC_NULL_POINTER;
     goto RSMHandleToTypeExit;
   }

   *pHandleType = HANDLE_TYPE_INVALID;


   if ( !(pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE) hHandle,
                                              ANY_COOKIE )) )
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMHandleToTypeExit;
   }

   switch( pNode->Cookie )
   {
     case DEVICE_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_DEVICE;
       break;

     case ADAPTER_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_ADAPTER;
       break;

     case DRIVER_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_DRIVER;
       break;

     case LDEV_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_LOGDEV;
       break;

     case SYS_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_SYSDEV;
       break;

     case RESOURCE_NODE_COOKIE:
       *pHandleType = HANDLE_TYPE_RESOURCE;
       break;
   }

   rc = RMRC_SUCCESS;

RSMHandleToTypeExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMHandleToParent                                    */
/*   -----------------                                    */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMHandleToParent( RMHANDLE   hHandle,
                                      PRMHANDLE  phParent )
{
   PRMNODE      pNode, pParent;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if ( !phParent )
   {
     rc = RMRC_NULL_POINTER;
     goto RSMHandleToParentExit;
   }

   *phParent = NULL;

   if ( pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE) hHandle,
                                            DRIVER_NODE_COOKIE ) )
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMHandleToParentExit;
   }
   else if ( !(pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE) hHandle,
                                                   ANY_COOKIE )) )
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMHandleToParentExit;
   }

   switch( pNode->Cookie )
   {
     case DEVICE_NODE_COOKIE:
     case ADAPTER_NODE_COOKIE:
       if ( !(pParent = pNode->pDevParent) )
       {
         *phParent = HANDLE_PHYS_TREE;
       }
       break;

     case LDEV_NODE_COOKIE:
     case SYS_NODE_COOKIE:
       if ( !(pParent = pNode->pDevParent) )
       {
         *phParent = HANDLE_SYS_TREE;
       }
       break;

     case RESOURCE_NODE_COOKIE:
       pParent = ((PRESNODE)pNode)->pDevUser;
       break;
   }

   if ( pParent )
   {
     *phParent = (HDEVICE)RMMAKEHANDLE( (PRMNODE) pParent );
   }

   rc = RMRC_SUCCESS;

RSMHandleToParentExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMUpdateAdjunct                                     */
/*   ----------------                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMUpdateAdjunct(HDRIVER  hDriver,
                                    HDEVICE  hDevice,
                                    USHORT   AdjunctIndex,
                                    PADJUNCT pAdjunct   )
{
   PRMNODE      pNode;
   PADJUNCT     pAdj;

   USHORT       i;
   USHORT       Len;
   USHORT       AdjHeaderLen;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if ( !RMNodeFromHandle( (RMHANDLE)hDriver,
                                     DRIVER_NODE_COOKIE) )
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMUpdateAdjunctExit;
   }

   if ( !(pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hDevice,
                                                       ANY_COOKIE)) )
   {
      rc = RMRC_BAD_DEVICEHANDLE;
      goto RSMUpdateAdjunctExit;
   }

   switch ( pNode->Cookie )
   {
      case ADAPTER_NODE_COOKIE:
        pAdj = pNode->pAdpt->pAdjunctList;
        break;

      case DEVICE_NODE_COOKIE:
        pAdj = pNode->pDev->pAdjunctList;
        break;

      default:
        rc = RMRC_BAD_DEVICEHANDLE;
        goto RSMUpdateAdjunctExit;
   }

   for ( i=0; i != AdjunctIndex && pAdj; i++, pAdj=pAdj->pNextAdj )
     ;

   if ( !pAdj )
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMUpdateAdjunctExit;
   }

   AdjHeaderLen = ((PBYTE)&pAdj->AdjBase - (PBYTE)pAdj );

   if ( (pAdj->AdjLength < pAdjunct->AdjLength) ||
                                (pAdjunct->AdjLength < AdjHeaderLen) )
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMUpdateAdjunctExit;
   }

   Len = pAdjunct->AdjLength - AdjHeaderLen;
   memcpy( &pAdj->AdjBase, &pAdjunct->AdjBase, Len );

   pAdj->AdjLength = pAdjunct->AdjLength;

   rc = RMRC_SUCCESS;

RSMUpdateAdjunctExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMAdjToHandleList                                   */
/*   ----------------                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMAdjToHandleList( PADJUNCT       pAdj,
                                       HADAPTER       hStartNode,
                                       PADJHANDLELIST pHndList   )
{
   USHORT       i, j;
   PRMNODE      pNode;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*----------------*/
   /* Check Pointers */
   /*----------------*/

   if ( !pAdj || !pHndList ) {
      rc = RMRC_NULL_POINTER;
      goto RSMAdjToHandleListExit;
   }

   if ( !pHndList->cMaxHandles )
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMAdjToHandleListExit;
   }

   pHndList->cHandles = 0;

   if ( ! (pNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hStartNode,
                                                        ANY_PHYS_COOKIE))  )
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMAdjToHandleListExit;
   }

   RMAdjToNodeList( pNode, pAdj, (PADJNODELIST) pHndList );

   if ( (j = pHndList->cHandles) > pHndList->cMaxHandles )
   {
     j = pHndList->cMaxHandles;
   }

   for ( i=0; i < j; i++ )
   {
     pHndList->Adj[i].hAdapter = (HDEVICE)RMMAKEHANDLE( (PRMNODE) pHndList->Adj[i].hAdapter );
   }
   rc = RMRC_SUCCESS;

RSMAdjToHandleListExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMHDevToHLDev                                       */
/*   --------------                                       */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMHDevToHLDev( HDEVICE  hDevice,
                                   HDEVICE  hStartLDev,
                                   PHLDEV   phLDev )
{
   PRMNODE      pDevNode;
   PRMNODE      pLDevNode;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   if ( !phLDev )
   {
     rc = RMRC_NULL_POINTER;
     goto RSMHDevToLDevExit;
   }

   *phLDev = NULL;

   if ( !(pDevNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hDevice, /*@V103757*/
                                                          ANY_PHYS_COOKIE))  )
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMHDevToLDevExit;
   }

   if ( !(pLDevNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hStartLDev,
                                                           ANY_LOG_COOKIE))  )
   {
     rc = RMRC_BAD_DEVICEHANDLE;
     goto RSMHDevToLDevExit;
   }

   if ( pLDevNode = RMDevToLDev( pLDevNode, pDevNode ) )
   {
     *phLDev = (HLDEV)RMMAKEHANDLE( (PRMNODE) pLDevNode );
   }

   rc = RMRC_SUCCESS;

RSMHDevToLDevExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMResToHDevList                                     */
/*   ----------------                                     */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMResToHandleList( PRESOURCESTRUCT   pRes,
                                       PHANDLELIST       pHndList )
{
   USHORT       i, j;
   USHORT       rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*----------------*/
   /* Check Pointers */
   /*----------------*/

   if ( !pRes || !pHndList ) {
      rc = RMRC_NULL_POINTER;
      goto RSMResToHandleListExit;
   }

   if ( !pHndList->cMaxHandles )
   {
     rc = RMRC_INVALID_PARM_VALUE;
     goto RSMResToHandleListExit;
   }

   pHndList->cHandles = 0;

   RMResourceToNodeList( pRes, (PNODELIST) pHndList );

   if ( (j = pHndList->cHandles) > pHndList->cMaxHandles )
   {
     j = pHndList->cMaxHandles;
   }

   for ( i=0; i < j; i++ )
   {
     pHndList->Handles[i] = (HDEVICE)RMMAKEHANDLE( (PRMNODE) pHndList->Handles[i] );
   }
   rc = RMRC_SUCCESS;

RSMResToHandleListExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMActivateAdapter                                   */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMActivateAdapter(HDRIVER hDriver,
                                      HADAPTER hAdapter)
{
   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMDeactivateAdapter                                 */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMDeactivateAdapter(HDRIVER hDriver,
                                        HADAPTER hAdapter)
{
   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMCreateLinkDevice                                  */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMCreateLinkDevice(HDRIVER  hDriver,
                                       PHDEVICE phLinkDevice,
                                       PDEVICESTRUCT pDeviceStruct,
                                       PAHDEVICES pahDevices)
{
   return RMRC_SUCCESS;
}

/*--------------------------------------------------------*/
/*                                                        */
/*   RSMModifyResources                                   */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMModifyResources(HDRIVER   hDriver,
                                      HADAPTER  hAdapter,
                                      USHORT    ModifyAction,
                                      HRESOURCE hResource)
{
PDRVRNODE pDrvrNode;
PRMNODE   pRMNode;
PRESNODE  pResNode;
PRESNODE  pRes;
USHORT    fNonOwnerOK;
USHORT    rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*---------------*/
   /* Check handles */
   /*---------------*/

   pRMNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hAdapter,
                                           ADAPTER_NODE_COOKIE);
   if (pRMNode == NULL)
   {
      pRMNode = (PRMNODE)RMNodeFromHandle( (RMHANDLE)hAdapter,
                                              DEVICE_NODE_COOKIE);

      if (pRMNode == NULL)
      {
         rc = RMRC_BAD_ADAPTERHANDLE;
         goto RSMModifyResourcesExit;
      }
   }

   if ((pDrvrNode = (PDRVRNODE)RMNodeFromHandle( (RMHANDLE)hDriver,
                                                 DRIVER_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_DRIVERHANDLE;
      goto RSMModifyResourcesExit;
   }

   if ((pResNode = (PRESNODE)RMNodeFromHandle( (RMHANDLE)hResource,
                                                RESOURCE_NODE_COOKIE)) == NULL)
   {
      rc = RMRC_BAD_RESOURCEHANDLE;
      goto RSMModifyResourcesExit;
   }

   /*--------------------------*/
   /* Do Action - Add/Delete   */
   /*--------------------------*/

   fNonOwnerOK = (RMGetResFlags(pResNode) & RS_NONOWNER_ALLOWED);   /*@V103757*/

   switch (ModifyAction)
   {
      case RM_MODIFY_ADD:
         if ( !fNonOwnerOK )                                        /*@V103757*/
         {                                                          /*@V103757*/
           if ((pResNode->pDevUser != (PRMNODE)pDrvrNode))
           {
              rc = RMRC_BAD_RESOURCEHANDLE;
              goto RSMModifyResourcesExit;
           }
         }                                                          /*@V103757*/
         RMUnlinkResourceNode(pResNode);
         RMAddResource(pRMNode, pResNode);
         break;

      case RM_MODIFY_DELETE:
         if ( !fNonOwnerOK )                                        /*@V103757*/
         {
           if (!( (pResNode->pDevUser == (PRMNODE)pDrvrNode) ||
                (pResNode->pDevUser->pDriver == pDrvrNode )) )
           {
              rc = RMRC_BAD_RESOURCEHANDLE;
              goto RSMModifyResourcesExit;
           }
         }                                                          /*@V103757*/

         RMTraceAlloc( (USHORT)      RSM_TRACE_DEALLOCATE,          /*@V103757*/
                       (PDRVRNODE)   pDrvrNode,                     /*@V103757*/
                       (USHORT)      pResNode->ResourceType,        /*@V103757*/
                       (PIORESOURCE) pResNode->pIO,                 /*@V103757*/
                       (USHORT)      rc );                          /*@V103757*/

         RMDeleteResourceNode(pResNode);
         break;

      default:
         rc = RMRC_SUCCESS;
   }

   rc = RMRC_SUCCESS;

RSMModifyResourcesExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;
}



/*--------------------------------------------------------*/
/*                                                        */
/*   RSMGetNodeInfo                                       */
/*   -------------                                        */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMGetNodeInfo(RMHANDLE         RMHandle,
                                  PRM_GETNODE_DATA pGetNodeData,
                                  USHORT           BufferSize)
{
PRM_NODE           pNodeInfo;          /* Ring 3 Super Node             */
PUCHAR             pCurrent;           /* Pointer to start of free      */
USHORT             NeededSize;         /* Minimum buffer size           */
PRMNODE            pRMNode;            /* Copy From this RMNode         */
PDRVRNODE          pDrvrNode;          /* Copy From this DrvrNode       */
PRESNODE           pResChain;          /* Copy From this Resource Chain */
USHORT             rc;

   /*----------------------------------------------------*/
   /* Obtain RSM Semaphore and check for TASK Time entry */
   /*----------------------------------------------------*/
   if ( RMEntry() ) {
      return RMRC_IRQ_ENTRY_ILLEGAL;
   }

   /*-------------------------------------*/
   /* Get pointer to RMNode               */
   /*  or DriverNode                      */
   /*-------------------------------------*/

  if ((pRMNode = RMNodeFromHandle( RMHandle, ANY_COOKIE)) == NULL){
     if ((pRMNode = (PRMNODE)pDrvrNode = RMNodeFromHandle( RMHandle, DRIVER_NODE_COOKIE)) == NULL){
        rc = RMRC_BAD_ADAPTERHANDLE;
        goto RSMGetNodeInfoExit;
     }
  }


  NeededSize = RMCalcNodeInfoSize( RMHandle );

  /*---------------------------*/
  /* Size of Node Info         */
  /*---------------------------*/

  pGetNodeData->RMNodeSize = NeededSize;


  if (BufferSize < NeededSize){
     rc = RMRC_BUFFER_TOO_SMALL;
     goto RSMGetNodeInfoExit;
  }

   /*--------------------*/
   /* Get first entry    */
   /*--------------------*/

  pNodeInfo = (PRM_NODE)&pGetNodeData->RMNode;


   /*--------------------------------------------*/
   /* Fill in Node Info Version                  */
   /*--------------------------------------------*/

  pNodeInfo->VersionInfo = (CMVERSION_MAJOR * 100) + (CMVERSION_MINOR);

   /*--------------------------------------------*/
   /* Point to bottom of Base Node Info          */
   /*--------------------------------------------*/


  pCurrent = (PUCHAR)pNodeInfo + sizeof(RM_NODE);


   /*-----------------------------*/
   /* Copy RMNode Structure       */
   /*-----------------------------*/

  pNodeInfo->pAdapterNode = (PADAPTERSTRUCT)pCurrent;
  switch (pRMNode->Cookie){
     case ADAPTER_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_ADAPTER;
        pDrvrNode=pRMNode->pDriver;
        RMCopyAdapter((PUCHAR FAR *)&pCurrent, pRMNode->pAdpt);
        break;
     case DEVICE_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_DEVICE;
        pDrvrNode=pRMNode->pDriver;
        RMCopyDevice((PUCHAR FAR*)&pCurrent, pRMNode->pDev);
        break;
     case DRIVER_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_DRIVER;
        RMCopyDriver((PUCHAR FAR*)&pCurrent, pDrvrNode->pDrv);
        break;
     case LDEV_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_LDEV;
        RMCopyLDev((PUCHAR FAR*)&pCurrent, pRMNode->pLDev);
        break;
     case SYS_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_SYSNAME;
        RMCopySysName((PUCHAR FAR*)&pCurrent, pRMNode->pSysDev);
        break;
     default:
        rc = RMRC_BAD_ADAPTERHANDLE;
        goto RSMGetNodeInfoExit;
  }

  pNodeInfo->DriverHandle = RMMAKEHANDLE( pDrvrNode );


   /*-----------------------------*/
   /* Copy Resource Structures    */
   /*-----------------------------*/


   pNodeInfo->pResourceList = (PRESOURCELIST)pCurrent;
   if (pNodeInfo->NodeType == RMTYPE_DRIVER)
      pResChain = pDrvrNode->pResChain;
   else
      pResChain = pRMNode->pResChain;


   RMCopyResources((PUCHAR FAR *)&pCurrent, pResChain);

   rc = RMRC_SUCCESS;

RSMGetNodeInfoExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;

}


/*--------------------------------------------------------*/
/*                                                        */
/*   RSMParseScsiInquiry                                  */
/*   -------------                                        */
/*     Create DevDescriptName from Scsi Inquiry Data      */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT _loadds FAR RSMParseScsiInquiry(PVOID            pInqBuf,
                                       PSZ              pDescBuffer,
                                       USHORT           BufferSize)
{
PSCSI_INQDATA pInquiry = (PSCSI_INQDATA) pInqBuf;
PSZ pScsiString;
USHORT ScsiTextSize;
USHORT rc;

   if ((pInquiry == NULL) || (pDescBuffer == NULL)) {
      rc = RMRC_NULL_POINTER;
      goto RSMParseScsiInquiryExit;
   }

   switch (pInquiry->DevType) {
        case UIB_TYPE_DISK      :
           pScsiString = pszKeyFixDisk;
           break;
        case UIB_TYPE_TAPE      :
           pScsiString = pszKeyTape;
           break;
        case UIB_TYPE_PRINTER   :
           pScsiString = pszKeyPrinter;
           break;
        case UIB_TYPE_PROCESSOR :
           pScsiString = pszKeyCPU;
           break;
        case UIB_TYPE_WORM      :
           pScsiString = pszKeyWORM;
           break;
        case UIB_TYPE_CDROM     :
           pScsiString = pszKeyCDROM;
           break;
        case UIB_TYPE_SCANNER   :
           pScsiString = pszKeyScanner;
           break;
        case UIB_TYPE_OPTICAL_MEMORY :
           pScsiString = pszKeyOpticalMem;
           break;
        case UIB_TYPE_CHANGER   :
           pScsiString = pszKeyChanger;
           break;
        case UIB_TYPE_COMM      :
           pScsiString = pszKeyComm;
           break;
        default:
           pScsiString = pszKeyScsiUnknown;
           break;
   }

   ScsiTextSize = strlen(pScsiString) +
                  sizeof(pInquiry->VendorID)   +
                  sizeof(pInquiry->ProductID)  +
                  sizeof(pInquiry->ProductRev) +
                  3;

   if (BufferSize < ScsiTextSize){
      rc = RMRC_BUFFER_TOO_SMALL;
      goto RSMParseScsiInquiryExit;
   }

   memcpy(pDescBuffer, pScsiString, strlen(pScsiString));
   pDescBuffer += strlen(pScsiString);

   memcpy(pDescBuffer, pInquiry->VendorID, sizeof(pInquiry->VendorID));
   pDescBuffer += sizeof(pInquiry->VendorID);
   *pDescBuffer++ = ' ';

   memcpy(pDescBuffer, pInquiry->ProductID, sizeof(pInquiry->ProductID));
   pDescBuffer += sizeof(pInquiry->ProductID);
   *pDescBuffer++ = ' ';

   memcpy(pDescBuffer, pInquiry->ProductRev, sizeof(pInquiry->ProductRev));
   pDescBuffer += sizeof(pInquiry->ProductRev);
   *pDescBuffer++ = '\0';


   rc = RMRC_SUCCESS;

RSMParseScsiInquiryExit:
   /*-----------------------*/
   /* Release RSM Semaphore */
   /*-----------------------*/
   RMExit();

   return rc;

}
