/**************************************************************************
 *
 * SOURCE FILE NAME =  RMHELP.C
 *
 * DESCRIPTIVE NAME =  Helpers for COM.SYS
 *
 *
 * Copyright : COPYRIGHT IBM CORPORATION, 1994, 1995
 *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
 *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
 *             RESTRICTED MATERIALS OF IBM
 *             IBM CONFIDENTIAL
 *
 * VERSION = V0.1
 *
 * DATE  09/07/94
 *
 * DESCRIPTION : (see above)
 *
 * Purpose: (see above)
 *
 *
 *
 * FUNCTIONS  :
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 *
 *
 * EXTERNAL FUNCTIONS
 *
 * CHANGE ACTIVITY =
 *   DATE      FLAG        APAR     CHANGE DESCRIPTION
 *   --------  ----------  -----    --------------------------------------
 *   09/07/94                       RobRose - Created
 *   03/29/95  @dlb        p148630  D.Beatty - increase resource buffer size
 *   07/23/97  @V179596    JR10605  DHDremann - Allow for 16 ISA cards-config.sys baseport parameters
 *
 ****************************************************************************/
#define INCL_NOPMAPI
#define INCL_DOS
#define INCL_NOXLATE_DOS16
#include <os2.h>
#include <string.h>

#ifndef FAR
#define FAR far
#endif

#include "dhcalls.h"
#include "rmcalls.h"
#include "cominfo.h"
#include "rmhelp.h"  // brings in rmcalls.h

#define USESIRQ     1         //Driver does indeed use IRQs....

/*--------------------------------------------------------*/
/* # D E F I N E S                                        */
/*--------------------------------------------------------*/
#ifndef MAXADN                          //Maximum number of adapters
#define MAXADN 4
#endif
#ifndef MAXPORT                         //Maximum number of I/O ranges
#define MAXPORT 1
#endif
#ifndef MAXIRQ                          //Maximum number of IRQs
#define MAXIRQ  1
#endif
#define MAXRESOURCE (MAXPORT+MAXIRQ)


/*--------------------------------------------------------*/
/* Set the DRIVERSTRUCT and ADAPTERSTRUCT data areas      */
/*--------------------------------------------------------*/

/*----------------------------------------------*/
/* Driver Description                           */
/*----------------------------------------------*/
DRIVERSTRUCT DriverStruct =
{
   "COM.SYS",                                /* DrvrName                */
   "Asynchronous Communications Driver",     /* DrvrDescript            */
   "IBM OS/2",                               /* VendorName              */
   CMVERSION_MAJOR,                          /* MajorVer                */
   CMVERSION_MINOR,                          /* MinorVer                */
   1994,9,17,                                /* Date                    */
   DRF_STATIC,                               /* DrvrFlags               */
   DRT_OS2,                                  /* DrvrType                */
   DRS_CHAR,                                 /* DrvrSubType             */
   NULL                                      /* DrvrCallback            */
};

/*----------------------------------------------*/
/* Adapter Description 0                        */
/*----------------------------------------------*/
ADAPTERSTRUCT AdapterStruct=
{
  "SERIAL_# Serial Controller",      /* AdaptDescriptName; */
  AS_NO16MB_ADDRESS_LIMIT,           /* AdaptFlags;        */
  AS_BASE_COMM,                      /* BaseType;          */
  AS_SUB_SERIAL,                     /* SubType;           */
  AS_INTF_16450,                     /* InterfaceType;     */
  AS_HOSTBUS_OTHER,                  /* HostBusType;       */
  AS_BUSWIDTH_16BIT,                 /* HostBusWidth;      */
  NULL                               /* pAdjunctList;      */
};

UCHAR LComName[] = KEY_COMM;

UCHAR FSComName[] = "COM#: ";


/*----------------------------------------------*/
/* GLOBAL VARS FOR RM                           */
/*                                              */
/* RM.LIB needs these declared                  */
/*----------------------------------------------*/
PFN             RM_Help               = 0L;
ULONG           RMFlags               = 0L;
ULONG           Device_Help           = 0L;
PFN             RM_Help0              = 0L;
PFN             RM_Help3              = 0L;

/*----------------------------------------------*/
/* GLOBAL HANDLE VARIABLES                      */
/*                                              */
/* These variables get the handles for          */
/* drivers, adapter (only 1), and resources.    */
/* The RMHELP wrappers are written so that most */
/* drivers using RMHELP as a template will not  */
/* have to reference these directly.            */
/*                                              */
/*----------------------------------------------*/

USHORT    curadn  = 0;        /* Current Adapter Number           */
USHORT    cSerialNodes = 0;   /* Number of other SERIAL_# Nodes   */
HDRIVER   hDriver = NULL;     /* global handle to driver          */
HADAPTER  hAdapter[MAXADN];   /* global handle to adapter         */
HRESOURCE hResPorts[MAXADN];  /* global handles to ports resource */
HRESOURCE hResIRQs[MAXADN];   /* global handles to IRQs resource  */

VOID FAR RMHELP_SetDevHelp(ULONG dhaddr)
{
     Device_Help = dhaddr;
}

/*--------------------------------------------------------*/
/* RMHELP_CreateDriver - registers to RM susbsystem       */
/*                       (which initializes the DD to     */
/*                        RM connection)                  */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR RMHELP_CreateDriver()
{
   USHORT     rc;
   HANDLELIST HandleList;

   memset(hResPorts,0,MAXADN*sizeof(HRESOURCE));
   memset(hResIRQs,0,MAXADN*sizeof(HRESOURCE));

   if (rc = RMCreateDriver(&DriverStruct,&hDriver) )
      return( rc );

   HandleList.cMaxHandles = 1;

   if ( !(RMKeyToHandleList(HANDLE_PHYS_TREE,
                            "SERIAL*",
                            &HandleList) ) ) {
      cSerialNodes = HandleList.cHandles;
   }


   return(rc);

}

/*--------------------------------------------------------*/
/* RMHELP_DestroyDriver - deregisters the driver from     */
/*                        RM sub-system and releases all  */
/*                        claimed resources               */
/*                                                        */
/*--------------------------------------------------------*/

VOID FAR RMHELP_DestroyDriver()
{
     RMDestroyDriver(hDriver);

     /*-------------------------*/
     /* Null out global handles */
     /*-------------------------*/

     hDriver = NULL;
     memset(hAdapter,0,MAXADN*sizeof(HRESOURCE));
     memset(hResPorts,0,MAXADN*MAXPORT*sizeof(HRESOURCE));
     memset(hResIRQs,0,MAXADN*MAXIRQ*sizeof(HRESOURCE));

}

/*--------------------------------------------------------*/
/* RMHELP_CreateAdapter - tells RM to associate adapter   */
/*                        to driver and resources to      */
/*                        adapater                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT FAR RMHELP_CreateAdapter(USHORT adn)
{
     UCHAR       ResourceBuf[sizeof(AHRESOURCE) + sizeof(HRESOURCE) * MAXRESOURCE ]; /* @dlb */
     PAHRESOURCE pResourceList = (PAHRESOURCE)ResourceBuf;
     ADJUNCT     adj;
     USHORT      rescnt;


     adj.pNextAdj=NULL;
     adj.AdjLength=sizeof(ADJUNCT);
     adj.AdjType=ADJ_ADAPTER_NUMBER;
     adj.Adapter_Number = adn + cSerialNodes ;

     rescnt=0;                          //no resources to begin with

     if (hResPorts[adn] != 0) {
        pResourceList->hResource[rescnt++]=hResPorts[adn];
     }


     if (hResIRQs[adn] != 0) {
        pResourceList->hResource[rescnt++] = hResIRQs[adn];
     }

     pResourceList->NumResource=rescnt;
     AdapterStruct.pAdjunctList=&adj;

     RMCreateAdapter(hDriver,
                     &hAdapter[adn],
                     &AdapterStruct,
                     NULL,
                     pResourceList) ;



     return(0);
}

/*--------------------------------------------------------*/
/* RMHELP_FreeAdapter -   tells RM to free adapter and    */
/*                        resources allocated to adapter  */
/*                                                        */
/*--------------------------------------------------------*/

VOID FAR RMHELP_FreeAdapter(USHORT adn)
{

   if (hResPorts[adn] != 0) {
        RMDeallocResource(hDriver,hResPorts[adn]);
   }

   if (hResIRQs[adn] != 0) {
        RMDeallocResource(hDriver,hResIRQs[adn]);
   }

   if (hAdapter[adn] != 0) {
        RMDestroyAdapter(hDriver,hAdapter[adn]);
   }
}

/*--------------------------------------------------------*/
/* RMHELP_AllocPorts - attempts to claim a port resource */
/*                       from RM subsystem                */
/*                                                        */
/* ARGS:                                                  */
/*                                                        */
/* USHORT baseport - base IO port.                        */
/* USHORT nPorts   - number of prts inclusive of base port*/
/*                                                        */
/*--------------------------------------------------------*/
USHORT FAR RMHELP_AllocPorts(USHORT MachType, USHORT baseport,USHORT nPorts)
{
   RESOURCESTRUCT Resource;


   if (hResPorts[curadn] == 0) {

      Resource.ResourceType             = RS_TYPE_IO;
      Resource.IOResource.BaseIOPort    = baseport;
      Resource.IOResource.NumIOPorts    = nPorts;

      if ( (MachType == MACH_EISA) || (MachType == MACH_UCHNL) ) {
           Resource.IOResource.IOAddressLines=16;
      } else {
           Resource.IOResource.IOAddressLines=10;
      }

      // @V179596  Check for > 10 bit I/O decode config.sys parameter.
      // 16 bit ISA card with serial ports.
      if ( baseport >= 0x0400) {                      // @V179596
         Resource.IOResource.IOAddressLines=16;       // @V179596
      }                                               // @V179596

      Resource.IOResource.IOFlags       = RS_IO_MULTIPLEXED;
      return(RMAllocResource( hDriver, &hResPorts[curadn], &Resource ));
   }

   return(RMHELP_ERR_RESOURCECLAIMED);
}


/*--------------------------------------------------------*/
/* RMHELP_AllocIRQ   - attempts to claim a IRQ resource   */
/*                       from RM subsystem                */
/*                                                        */
/* ARGS:                                                  */
/*                                                        */
/* USHORT IRQlevel - IRQ level to claim                   */
/*                                                        */
/*--------------------------------------------------------*/
USHORT FAR RMHELP_AllocIRQ(USHORT MachType, USHORT IRQlevel)
{
     RESOURCESTRUCT Resource;

     if (hResIRQs[curadn] == 0) {
          Resource.ResourceType          = RS_TYPE_IRQ;
          Resource.IRQResource.PCIIrqPin = RS_PCI_INT_NONE;
          if (MachType == MACH_UCHNL)
             Resource.IRQResource.IRQFlags  = RS_IRQ_SHARED;
          else
             Resource.IRQResource.IRQFlags  = RS_IRQ_MULTIPLEXED;
          Resource.IRQResource.IRQLevel  = IRQlevel;
          return(RMAllocResource(hDriver,&(hResIRQs[curadn]),&Resource));
     }

     return(RMHELP_ERR_RESOURCECLAIMED);
}



/*****************************************************************************/
/*****************************************************************************/
/********                                               **********************/
/********  All COM specific code appears below this     **********************/
/********                divider!!!                     **********************/
/********                                               **********************/
/********                                               **********************/
/*****************************************************************************/
/*****************************************************************************/

/*--------------------------------------------------------*/
/* RMHELP_GetPorts   - attempts to claim resources for a  */
/*                     COM port                           */
/*                                                        */
/* ARGS:  ptr = COM driver ComInfo structure              */
/*                                                        */
/*--------------------------------------------------------*/
USHORT FAR RMHELP_GetPorts(USHORT MachType,PCOMINFO pComInfo)
{
     USHORT rc = 0;

     curadn = pComInfo->ci_port_number;

     if ( (pComInfo->ci_port != 0) &&
          (rc = RMHELP_AllocPorts(MachType, pComInfo->ci_port,8)) ) {
        return(rc);
     }

     if ( (pComInfo->ci_irq != 0) &&
          (rc=RMHELP_AllocIRQ(MachType, pComInfo->ci_irq)) ) {
       return(rc);
     }

     return(0);
}

/*----------------------------------------------------------*/
/* RMHELP_PortInitComplete - Bind resources to the port     */
/*                                                          */
/*      We also examine the ComInfo structure for the       */
/*      hardware type and update our structures accordingly */
/*                                                          */
/* ARGS:  pComInfo = COM driver ComInfo structure           */
/*                                                          */
/*----------------------------------------------------------*/

USHORT FAR RMHELP_PortInitComplete(PCOMINFO pComInfo, USHORT BusType)
{
   USHORT rc=0;

   switch (BusType) {
      case MACH_EISA:
         AdapterStruct.HostBusType=AS_HOSTBUS_EISA;
         break;
      case MACH_UCHNL:
         AdapterStruct.HostBusType=AS_HOSTBUS_uCHNL;
         break;
      case MACH_PCMCIA:
         AdapterStruct.HostBusType=AS_HOSTBUS_PCMCIA;
         break;
      case MACH_ISA:
         AdapterStruct.HostBusType=AS_HOSTBUS_ISA;
         break;
      default:
         AdapterStruct.HostBusType=AS_HOSTBUS_PLANAR;
         break;
   }

   switch (pComInfo->ci_flagx & FX_CHIP_MASK) {
      case FX_8250:
      case FX_16450:
         AdapterStruct.InterfaceType=AS_INTF_16450;
         break;
      case FX_16550A:
         AdapterStruct.InterfaceType=AS_INTF_16550;
         break;
   }

   /*-------------------------------*/
   /* If not pcmcia modem, create   */
   /* an adapter                    */
   /*-------------------------------*/

   if (!(pComInfo->ci_flagx1 & FX1_PCMCIA_MODEM)) {
      rc = RMHELP_CreateAdapter( pComInfo->ci_port_number );
      if (!rc){
        pComInfo->ci_hAdapter = hAdapter[pComInfo->ci_port_number];
        rc = RMHELP_CreateLDev(pComInfo);
      }
   }

   return( rc  );
}

/*----------------------------------------------------------*/
/* RMHELP_PortDidntInstall - Free resources from a port     */
/*                                                          */
/* ARGS:  locus = code to indicate point of failure         */
/*        port  = adapter number to free                    */
/*                                                          */
/*----------------------------------------------------------*/
USHORT FAR RMHELP_PortDidntInstall(USHORT Locus, USHORT Port)
{
     return( RMHELP_FreeAdapter( Port ));
}

/*----------------------------------------------------------*/
/* RMHELP_CreateLDev - Create logical device nodes          */
/*                                                          */
/* ARGS:                                                    */
/*        pComInfo  = pointer to ComInfo                    */
/*                                                          */
/*----------------------------------------------------------*/
USHORT FAR RMHELP_CreateLDev( PCOMINFO pComInfo )
{
  LDEVSTRUCT    RMLDevStr;
  SYSNAMESTRUCT RMSysNameStr;
  ADJUNCT       RMAdjunct;
  HLDEV         hRMLDev;
  HSYSNAME      hRMSysName;
  USHORT        rc=0;

  if (!(pComInfo->ci_hLDev)){
     memset( &RMLDevStr, 0, sizeof(LDEVSTRUCT) );

     memset( &RMSysNameStr, 0, sizeof(SYSNAMESTRUCT) );

     RMLDevStr.LDevClass        = LDEV_CLASS_SERIAL;
     RMLDevStr.pAdjunctList     = &RMAdjunct;
     RMAdjunct.AdjType          = ADJ_DEVICE_NUMBER;
     RMAdjunct.AdjLength        = sizeof(ADJUNCT);
     RMAdjunct.pNextAdj         = NULL;

     RMLDevStr.LDevDescriptName = LComName;
     RMAdjunct.Device_Number = pComInfo->ci_port_number;

     if ( !(rc = RMCreateLDev( (HDRIVER)     hDriver,
                               (PHLDEV)      &hRMLDev,
                               (HDEVICE)     pComInfo->ci_hAdapter,
                               (PLDEVSTRUCT) &RMLDevStr  )) )
     {
       pComInfo->ci_hLDev = hRMLDev;

       RMSysNameStr.SysDescriptName = FSComName;
       RMSysNameStr.pAdjunctList    = NULL;

       FSComName[3] = (UCHAR)(pComInfo->ci_port_number + 1 + '0');

       rc = RMCreateSysName( (HDRIVER)        hDriver,
                             (PHSYSNAME)      &hRMSysName,
                             (HDEVICE)        hRMLDev,
                             (PSYSNAMESTRUCT) &RMSysNameStr  );

       pComInfo->ci_hSysName = hRMSysName;
     }
  }

  return rc;
}


/*----------------------------------------------------------*/
/* RMHELP_DestroyLDev - Destroy logical device nodes        */
/*                                                          */
/* ARGS:  pComInfo = pointer to ComInfo Structure           */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
VOID FAR RMHELP_DestroyLDev( PCOMINFO pComInfo )
{
  if (pComInfo) {
     if (pComInfo->ci_hSysName)
        RMDestroySysName( hDriver, pComInfo->ci_hSysName );
     pComInfo->ci_hSysName = 0;
     if (pComInfo->ci_hLDev)
        RMDestroyLDev( hDriver, pComInfo->ci_hLDev );
     pComInfo->ci_hLDev = 0;
  }
}

/*----------------------------------------------------------*/
/* RMHELP_FindPCMCIA - Find PCMCIA Node to hang LDEV        */
/*                                                          */
/* ARGS:  pComInfo = pointer to ComInfo Structure           */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
VOID FAR RMHELP_FindPCMCIANode( PCOMINFO pComInfo )
{
   HANDLELIST HandleList;

   HandleList.cMaxHandles = 1;

   if ( !(RMKeyToHandleList(HANDLE_PHYS_TREE,
                            "PCMCIA*",
                            &HandleList) ) ) {
      if( HandleList.cHandles )
         pComInfo->ci_hAdapter = HandleList.Handles[0];
      else
         pComInfo->ci_hAdapter = 0;
   } else {
      pComInfo->ci_hAdapter = 0;
   }
}


/*----------------------------------------------------------*/
/* RMHELP_HasPNPCaps - Has PNP Capabilities                 */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
BOOL RMHELP_HasPNPCaps( )
{
APIRET     rc;
PSEL       pSelGInfoSeg;
PGINFOSEG  pGInfoSeg = NULL;


   /*--------------------------------------------------*/
   /* Resource manager originally did not include      */
   /* RMGetVersion so this is our only method to know  */
   /* if it is safe to later call RMDevIDToHandleList  */
   /*--------------------------------------------------*/

   /*---------------------------------------------------*/
   /* Call GetDOSVar to find OS Major and Minor Version */
   /* PDD Ref states that it is not safe at Init time   */
   /* but tests show it is.  Anyway, we don't have any  */
   /* other method since the 16 bit DosQSysInfo didn't  */
   /* support getting the OS version.                   */
   /*---------------------------------------------------*/


   rc = DevHelp_GetDOSVar( DHGETDOSV_SYSINFOSEG,0, &pSelGInfoSeg );

   if(!rc){
      /*--------------------------------*/
      /* Build virtaddr from selector   */
      /*--------------------------------*/

      pGInfoSeg = (PGINFOSEG)((ULONG)*pSelGInfoSeg << 16);

      /*-------------------------*/
      /* Is on version > Warp?   */
      /*-------------------------*/

      if ( (pGInfoSeg->uchMajorVersion > 20) ||
           ( (pGInfoSeg->uchMajorVersion == 20) &&
             (pGInfoSeg->uchMinorVersion > 30) ) ){
         return(TRUE);
      } else {
         return(FALSE);
      }

   }


   return(FALSE);

}

/*----------------------------------------------------------*/
/* RMHELP_FindDetectedRes - Return port resource for this  */
/*                          Detected Struct                */
/*                                                          */
/* ARGS:  pComInfo = pointer to ComInfo Structure           */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
BOOL RMHELP_FindDetectedRes( RMHANDLE hDetected, PUSHORT pAddr, PUSHORT pIRQ )
{
   APIRET rc;

   UCHAR          NodeInfo[512];  // Big Number
   PRESOURCELIST  pResList;
   USHORT         portAddr=0;
   USHORT         i;
   HRESOURCE      hResource;
   RESOURCESTRUCT rs;

   *pIRQ = *pAddr = 0;

   rc = RMGetNodeInfo( hDetected,
                       (PRM_GETNODE_DATA)&NodeInfo[0],
                       512);

   /*-----------------------------*/
   /* Find Base Port Address      */
   /*-----------------------------*/

   if(!rc)
      if(pResList = ((PRM_GETNODE_DATA)NodeInfo)->RMNode.pResourceList)
         for(i=0;i<pResList->Count;i++){

            if(pResList->Resource[i].ResourceType == RS_TYPE_IO) {
               *pAddr = pResList->Resource[i].IOResource.BaseIOPort;
            } else if(pResList->Resource[i].ResourceType == RS_TYPE_IRQ) {
               *pIRQ = pResList->Resource[i].IRQResource.IRQLevel;
            } else {
               return(FALSE);
            }
         }



   /*-------------------------------*/
   /* Make sure we found resources  */
   /* Note: IRQ0 not possible       */
   /*-------------------------------*/

   if (!(*pAddr && *pIRQ)){
      return(FALSE);
   }

   /*------------------------------------*/
   /* Try to get the IO resource from RM */
   /* just in case serial snooper found  */
   /* driver, but mouse actually claimed */
   /*------------------------------------*/

   rs.ResourceType = RS_TYPE_IO;
   rs.IOResource.BaseIOPort = *pAddr;
   rs.IOResource.NumIOPorts = 8;
   rs.IOResource.IOFlags = RS_IO_EXCLUSIVE;
   rs.IOResource.IOAddressLines = 16;

   rc = RMAllocResource(hDriver, &hResource, &rs);

   if(rc){
      return(FALSE);
   } else {
      RMDeallocResource(hDriver, hResource);
   }

   return(TRUE);
}


/*----------------------------------------------------------*/
/* RMHELP_FindDetected - Find Detected Structures           */
/*                                                          */
/* ARGS:  pComInfo = pointer to ComInfo Structure           */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
VOID RMHELP_UpdateComInfo( PCOMINFO pComInfo, PHANDLELIST pHandlelist )
{
APIRET      rc;
USHORT      i,j;
USHORT      portAddr;
USHORT      Irq;
PUSHORT     pBDA = (PUSHORT)0x400000;  /* 40:0000 Bios Data Area */
BOOL        found;
PCOMINFO    pFirstComInfo = pComInfo;


  /*-----------------------------------------*/
  /* Reminder - Don't count ports with mouse */
  /*-----------------------------------------*/

  for (i=0; i<pHandlelist->cHandles;i++){

     /****************************************/
     /* Get Resources for this device handle */
     /****************************************/

     rc = RMHELP_FindDetectedRes( pHandlelist->Handles[i], &portAddr, &Irq);

     if(rc==TRUE){

        found = FALSE;
        pComInfo = pFirstComInfo;

        for(j = 0; j < MAXADN; j++){

           if(pComInfo->ci_port == portAddr){
              found = TRUE;
              break;
           }

           pComInfo++;    /* Jump to next cominfo */

        }

        if(found == TRUE){    /* Config.sys line had it filled in */
           continue;
        }

        /*-------------------------------------------------*/
        /* Searched Cominfo and and didn't find so lets    */
        /* stuff it in a cominfo. Try to use 40:0 as a     */
        /* guide.                                          */
        /*-------------------------------------------------*/


        pComInfo = pFirstComInfo;
        pBDA = (PUSHORT)0x400000;  /* 40:0000 Bios Data Area */

        for(j=0;j < MAXADN;j++){
           if(*pBDA == portAddr) {
              if(pComInfo->ci_port == 0){
                 pComInfo->ci_port = portAddr;
                 pComInfo->ci_port_number = j;
                 pComInfo->ci_irq = Irq;

                 found = TRUE;
                 break;
              }
           }
           pBDA++;
           pComInfo++;
        }

        if(found == TRUE){
           continue;
        }

        /*------------------------------------------*/
        /* No help from 40:0; find first empty slot */
        /*------------------------------------------*/

        pComInfo = pFirstComInfo;

        for(j=0;j < MAXADN;j++){
           if(pComInfo->ci_port == 0){
              pComInfo->ci_port = portAddr;
              pComInfo->ci_port_number = j;
              pComInfo->ci_irq = Irq;

              found = TRUE;
              break;
           }
           pComInfo++;
        }



     }
  }


}

/*----------------------------------------------------------*/
/* RMHELP_FindDetected - Find Detected Structures           */
/*                                                          */
/* ARGS:  pComInfo = pointer to ComInfo Structure           */
/*                                                          */
/*                                                          */
/*----------------------------------------------------------*/
VOID FAR RMHELP_FindDetected( PCOMINFO pComInfo )
{
APIRET      rc;
UCHAR       Handlelist[sizeof(HANDLELIST)+(sizeof(HADAPTER)*(MAXADN-1))];
PHANDLELIST pHandlelist = (PHANDLELIST)&Handlelist[0];
DEVID       devID;


   /*--------------------------------------------------*/
   /* Are we on a version of OS/2 which has snoopers?  */
   /*--------------------------------------------------*/


   if( RMHELP_HasPNPCaps()){

      /*------------------------------------------------------------------*/
      /* serial snooper is currently only emitting this ID for discovered */
      /* com ports.  This code will need to change if it does.            */
      /*------------------------------------------------------------------*/

      RMConvertID( &devID,
                   "PNP0500",
                   RM_CONVERT_TO_ID);


      pHandlelist->cMaxHandles = MAXADN;

      rc = RMDevIDToHandleList( RM_IDTYPE_EISA,
                                devID,   /* Device ID */
                                0L,
                                0L,
                                0L,
                                0L,
                                SEARCH_ID_DEVICEID,
                                HANDLE_CURRENT_DETECTED,
                                pHandlelist);

      if(!rc){
         if(pHandlelist->cHandles){
            RMHELP_UpdateComInfo(pComInfo,pHandlelist);
         }
      }

      rc = RMDevIDToHandleList( RM_IDTYPE_EISA,
                                0L,
                                0L,
                                devID,   /* Compatible ID */
                                0L,
                                0L,
                                SEARCH_ID_COMPATIBLEID,
                                HANDLE_CURRENT_DETECTED,
                                pHandlelist);

      if(!rc){
         if(pHandlelist->cHandles){
            RMHELP_UpdateComInfo(pComInfo,pHandlelist);
         }
      }


   }
}
