/*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 =  RSMINIT.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Initialization
 *
 *
 *
 * VERSION = V1.01
 *
 * DATE
 *
 * DESCRIPTION :
 *
 * Purpose:
 *
 *
 *
 * FUNCTIONS  :
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 *
 *
 * EXTERNAL FUNCTIONS
 *
*/
#define  INCL_NOBASEAPI
#define  INCL_NOPMAPI
#define  INCL_DOSERRORS
#include <os2.h>

#include <eisa.h>
#include <dskinit.h>
#include <devhdr.h>
#include <sas.h>
#include <infoseg.h>

#include "dhcalls.h"

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

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

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


/*------------------------------------------------------------------------*/
/*                                                                        */
/* Initialization                                                         */
/*                                                                        */
/*------------------------------------------------------------------------*/

typedef struct SysDev           FAR *PDDHDR;

typedef struct SAS              FAR *PSAS;
typedef struct SAS_info_section FAR *PSASINFO;

typedef struct InfoSegGDT FAR *PSYSINFOSEG;

/*------------------------------------*/
/* RMInit                             */
/*                                    */
/* Process Initialization Request     */
/* Packet from kernel.                */
/*                                    */
/*------------------------------------*/

VOID FAR RMInit(PRPINITIN pRPH )
{
  PRPINITIN             pRPI = (PRPINITIN)  pRPH;
  PRPINITOUT            pRPO = (PRPINITOUT) pRPH;
  PDDD_PARM_LIST        pDDD_Parm_List;
  PMACHINE_CONFIG_INFO  pMCHI;

  PDDHDR                pDDHdr;

  PSAS                  pSAS;
  PSASINFO              pSASInfo;
  PSYSINFOSEG           pSysInfoSeg;



  /*----------------------------------------*/
  /* Setup DevHelp service entry point for  */
  /* DHCALLS library.                       */
  /*----------------------------------------*/
  Device_Help = pRPH->DevHlpEP;


  /*---------------------------------------*/
  /* Point to initialization vector table. */
  /*                                       */
  /* See h\dskinit.h for contents.         */
  /*---------------------------------------*/
  pDDD_Parm_List = (PDDD_PARM_LIST) pRPI->InitArgs;

  /*-----------------------------------------------*/
  /* Transfer information from Machine Info packet */
  /*-----------------------------------------------*/
  pMCHI = MAKEP( SELECTOROF(pDDD_Parm_List),
                 (USHORT)   pDDD_Parm_List->machine_config_table );


  /*----------------------------*/
  /* Initialize Heap Management */
  /*----------------------------*/

  RMAllocInit();

  if ( DevHelp_DynamicAPI( (PVOID)  RSMR3Entry,
                           (USHORT) 3,
                           (USHORT) DYNAPI_CALLGATE16 | DYNAPI_ROUTINE16,
                           (PSEL)   &RMR3CallGate  ) )
  {
    _asm int 3
  }

  pDDHdr             = (PDDHDR) &RMDDHeader;
  pDDHdr->SDevInt    = (USHORT)  RSMR0Entry;
  pDDHdr->SDevRealCS = (USHORT) (((ULONG)&RSMR0Entry) >> 16);
  pDDHdr->SDevRealDS = (USHORT)  RMR3CallGate;

  if ( DevHelp_GetDOSVar( (USHORT) DHGETDOSV_INTERRUPTLEV,
                          (USHORT) 0,
                          (PPVOID) &pCurIntLevel ) )
  {
    _asm int 3
  }

  /*--------------------------------------------------------------*/
  /* Why go through such contortions to get the System InfoSeg?   */
  /* The kernel couldn't have a     in DH_GETDOSVAR?              */
  /* Say it ain't so!                                             */
  /*--------------------------------------------------------------*/

  SELECTOROF(pSAS) = SAS_SELECTOR;
  OFFSETOF(pSAS)   = 0;

  pSASInfo         = (PSASINFO)((PBYTE)pSAS + pSAS->SAS_info_data);

  SELECTOROF(pSysInfoSeg) = pSASInfo->SAS_info_global;
  OFFSETOF(pSysInfoSeg)   = 0;

  pTraceBits = pSysInfoSeg->SIS_mec_table;

  /*----------------------------*/
  /* Create Driver for RM       */
  /*----------------------------*/

  PDevPtrs[PDEV_RMDD]   = (PRMNODE) f_RMCreateDriverNode(&RMDriverStruct);
  PDevPtrs[PDEV_KRNLDD] = (PRMNODE) f_RMCreateDriverNode(&KrnlDriverStruct);

  /*----------------------------*/
  /* Update Driver Chain        */
  /*----------------------------*/
  PDevPtrs[PDEV_DRIVER] = PDevPtrs[PDEV_RMDD];
  ((PDRVRNODE) PDevPtrs[PDEV_RMDD])->pDrvSibling =
                                    (PDRVRNODE) PDevPtrs[PDEV_KRNLDD];


  /*----------------------------*/
  /* Create Initial Topology    */
  /*----------------------------*/

  RMBusInit( pMCHI );

  /*--------------------------------*/
  /* Create Initial Psuedo Handles  */
  /*--------------------------------*/

  RMInitPseudoHandles();

  pRPO->CodeEnd     = (USHORT) &RMInit;
  pRPO->DataEnd     = (USHORT) &RMInitData;
  pRPO->rph.Status  = STDON;

}



/*--------------------------------------------------------*/
/*                                                        */
/* RMAllocInit                                            */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

USHORT NEAR RMAllocInit()
{

  pBUFChain->pNext = 0;
  pBUFChain->Size  = RMPoolSize;

  RMPools[0] = SELECTOROF(pBUFChain);

  return( 0 );
}


/*--------------------------------------------------------*/
/*                                                        */
/* RMBusInit                                              */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMBusInit(PMACHINE_CONFIG_INFO pMCHI)
{
  USHORT                i;

  ADAPTERSTRUCT         AdptStr;
  DEVICESTRUCT          DevStr;
  ADJUNCT               AdjInfo[2];

  PNODELIST             pNodeList;
  UCHAR                 NodeList[sizeof(NODELIST)+29*sizeof(PVOID)];


  /*------------------------------------------------*/
  /* Adapter Structure for Physical Tree Root Node  */
  /*------------------------------------------------*/

  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.HostBusType  = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth = AS_BUSWIDTH_32BIT;

  AdptStr.AdaptDescriptName = PDevTxtRoot;

  PDevPtrs[PDEV_ROOT] = f_RMCreateAdapterNode( &AdptStr );

  f_RMRegisterNode( (PDRVRNODE) PDevPtrs[PDEV_RMDD],
                    (PRMNODE)   PDevPtrs[PDEV_ROOT]   );


  /*---------------------------------*/
  /* Adapter Structure for CPU Node  */
  /*---------------------------------*/

  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  switch ( pMCHI->CpuInfo )
  {
    case CPUINFO_386:
      AdptStr.AdaptDescriptName = CpuText386;
      break;
     case CPUINFO_486:
      AdptStr.AdaptDescriptName = CpuText486;
      break;
     case CPUINFO_586:
      AdptStr.AdaptDescriptName = CpuText586;
      break;
     default:
      AdptStr.AdaptDescriptName = CpuTextxxx;
  }

  AdptStr.HostBusType  = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth = AS_BUSWIDTH_32BIT;

  memset( (PBYTE)&AdjInfo, 0, sizeof(AdjInfo) );                    /*@V103757*/

  AdptStr.pAdjunctList = &AdjInfo[0];                               /*@V103757*/

  AdjInfo[0].pNextAdj       = &AdjInfo[1];                          /*@V103757*/
  AdjInfo[0].AdjLength      = sizeof(ADJUNCT);                      /*@V103757*/
  AdjInfo[0].AdjType        = ADJ_ADAPTER_NUMBER;                   /*@V103757*/
  AdjInfo[0].Adapter_Number = 0;                                    /*@V103757*/

  AdjInfo[1].AdjLength      = sizeof(ADJUNCT);                      /*@V103757*/
  AdjInfo[1].AdjType        = ADJ_MODEL_INFO;                       /*@V103757*/
  AdjInfo[1].Model_Info     = (pMCHI->Model << 8) | pMCHI->SubModel;/*@V103757*/

  PDevPtrs[PDEV_CPU_0] = f_RMCreateAdapterNode( &AdptStr );

  f_RMRegisterNode( (PDRVRNODE) PDevPtrs[PDEV_KRNLDD],
                    (PRMNODE)   PDevPtrs[PDEV_CPU_0]   );

  /*----------------------------------*/
  /* Make CPU a child of PDEV_ROOT    */
  /*----------------------------------*/
  f_RMAddChild( PDevPtrs[PDEV_ROOT], PDevPtrs[PDEV_CPU_0] );

  /*-----------------------------------------------*/
  /* Create IO Port Resource class as child of CPU */
  /*-----------------------------------------------*/
  f_RMRegisterResourceClass( RS_TYPE_IO, 0, PDevPtrs[PDEV_CPU_0] );

  /*----------------------------------------------*/
  /* Create Memory Resource class as child of CPU */
  /*----------------------------------------------*/
  f_RMRegisterResourceClass( RS_TYPE_MEM, 0, PDevPtrs[PDEV_CPU_0] );


  /*-------------------------------------------*/
  /* Create Adapter Structure for System Buses */
  /*-------------------------------------------*/

  /*--------------------------*/
  /* Integrated Controler Bus */
  /*--------------------------*/
  RMInitXBus( pMCHI, PDevPtrs[PDEV_CPU_0] );

  /*-----------------*/
  /* ISA/uC/EISA Bus */
  /*-----------------*/
  if ( pMCHI->BusInfo & BUSINFO_MCA )
  {
    PDevPtrs[PDEV_SYSBUS] = RMInitMCA( pMCHI, PDevPtrs[PDEV_CPU_0] );
  }
  else if ( pMCHI->BusInfo & BUSINFO_EISA )
  {
    PDevPtrs[PDEV_SYSBUS] = RMInitEISA( pMCHI, PDevPtrs[PDEV_CPU_0] );
  }
  else
  {
    PDevPtrs[PDEV_SYSBUS] = RMInitISA( pMCHI, PDevPtrs[PDEV_CPU_0] );
  }

  if ( pMCHI->BusInfo & BUSINFO_PCI )
  {
    RMInitPCI( pMCHI, PDevPtrs[PDEV_CPU_0] );
  }
  /*-------------------------*/
  /* Create LDev Structures  */
  /*-------------------------*/
  RMInitLDev();


  return( PDevPtrs[PDEV_CPU_0] );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitXBus                                             */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMInitXBus( PMACHINE_CONFIG_INFO pMCHI, PRMNODE pCpuNode )
{
  ADAPTERSTRUCT         AdptStr;
  DEVICESTRUCT          DevStr;
  RESOURCESTRUCT        ResStr;

  PRMNODE               pAdptNode;
  PRMNODE               pDevNode;
  PRMNODE               pDevNode0;                                  /*@V103757*/
  PRESNODE              pResNode;

  ADJUNCT               Adjunct[2];

  USHORT                i, j, m, p;
  USHORT                ShareFlag;

  /*----------------------------------------------*/
  /* Create X-Bus Node for Integrated Controllers */
  /*----------------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName = XBusText;
  AdptStr.BaseType          = AS_BASE_PERIPH;
  AdptStr.HostBusType       = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth      = AS_BUSWIDTH_32BIT;
  PDevPtrs[PDEV_XBUS] = f_RMCreateAdapterNode( &AdptStr );

  /*-------------------------------*/
  /* Make X-BUS a child of the CPU */
  /*-------------------------------*/
  f_RMAddChild( pCpuNode, PDevPtrs[PDEV_XBUS] );

  /*----------------------------------*/
  /* Create Adapter Nodes for PIC 0/1 */
  /*----------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );
  AdptStr.HostBusType         = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth        = AS_BUSWIDTH_16BIT;
  AdptStr.AdaptDescriptName   = PICText;

  AdptStr.pAdjunctList        = Adjunct+1;
  Adjunct[1].pNextAdj         = NULL;
  Adjunct[1].AdjLength        = sizeof(ADJUNCT);
  Adjunct[1].AdjType          = ADJ_ADAPTER_NUMBER;

  memset( (PBYTE)&DevStr, 0, sizeof(DEVICESTRUCT) );
  DevStr.DevDescriptName = IRQText;
  DevStr.DevType         = DS_TYPE_PLANAR_CHIPSET;

  DevStr.pAdjunctList    = Adjunct;
  Adjunct[0].pNextAdj    = NULL;
  Adjunct[0].AdjLength   = sizeof(ADJUNCT);
  Adjunct[0].AdjType     = ADJ_DEVICE_NUMBER;

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );

  ResStr.ResourceType              = RS_TYPE_IO;
  ResStr.IOResource.NumIOPorts     =  2;
  ResStr.IOResource.IOAddressLines = 16;
  ResStr.IOResource.IOFlags        = RS_IO_EXCLUSIVE;

  for ( i=m=0; i < NUM_PIC_DEVICES; i++ )
  {
    Adjunct[1].Adapter_Number = i;

    AdptStr.BaseType            = AS_BASE_PERIPH;
    AdptStr.SubType             = AS_SUB_PIC;

    pAdptNode = f_RMCreateAdapterNode( &AdptStr );

    if (i == 1) pDevNode0 = pAdptNode;                              /*@V103757*/

    /*----------------------------------*/
    /* Make PIC Adapters child of X-BUS */
    /*----------------------------------*/
    f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

    /*------------------------------------------*/
    /* Assign PIC resources (ports) to PIC Node */
    /*------------------------------------------*/
    ResStr.IOResource.BaseIOPort = (i) ? PIC_1_PORT : PIC_0_PORT;   /*@V103757*/

    pResNode = f_RMCreateResourceNode( &ResStr );
    f_RMAddResource( pAdptNode, pResNode );

    /*------------------------------------*/
    /* Create Device Nodes For IRQ Levels */
    /*------------------------------------*/
    for ( j = 0; j <  NUM_PIC_LEVELS; j++, m++ )
    {
      Adjunct[0].Device_Number = m;
      pDevNode = f_RMCreateDeviceNode( &DevStr );

      /*-------------------------------------------*/
      /* Make IRQ Device Node Child of PIC Adapter */
      /*-------------------------------------------*/
      f_RMAddChild( pAdptNode, pDevNode );

      /*---------------------------*/
      /* Create IRQ resource class */
      /*---------------------------*/
      f_RMRegisterResourceClass( RS_TYPE_IRQ, m, pDevNode );
    }
  }

  /*----------------------------------*/
  /* Assign IRQ 2 to PIC 1            */
  /*----------------------------------*/
  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );              /*@V103757*/

  ResStr.ResourceType              = RS_TYPE_IRQ;                   /*@V103757*/
  ResStr.IRQResource.IRQLevel      = PIC_CASCADE_IRQ;               /*@V103757*/
  ResStr.IRQResource.IRQFlags      = RS_IRQ_EXCLUSIVE;              /*@V103757*/
  pResNode = f_RMCreateResourceNode( &ResStr );                     /*@V103757*/
  f_RMAddResource( pDevNode0, pResNode);                            /*@V103757*/


  /*--------------------------------------------*/
  /* Create Adapter Structure for DMA Subsystem */
  /*--------------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );


  AdptStr.AdaptDescriptName   = DMAText;
  AdptStr.BaseType            = AS_BASE_PERIPH;
  AdptStr.SubType             = AS_SUB_DMA;
  AdptStr.HostBusType  = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth = AS_BUSWIDTH_16BIT;

  AdptStr.pAdjunctList        = Adjunct+1;
  Adjunct[1].pNextAdj         = NULL;
  Adjunct[1].AdjLength        = sizeof(ADJUNCT);
  Adjunct[1].AdjType          = ADJ_ADAPTER_NUMBER;

  for ( i=m=0; i < NUM_DMA_CONTROLLERS; i++  )
  {
    Adjunct[1].Adapter_Number = i;

    pAdptNode = f_RMCreateAdapterNode( &AdptStr );

    if (i == 1) pDevNode0 = pAdptNode;                              /*@V107246*/

    /*-----------------------------------*/
    /* Make DMA Subsystem child of X-BUS */
    /*-----------------------------------*/
    f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

    /*--------------------------------------------*/
    /* Create Device Nodes for DMA Controller     */
    /*--------------------------------------------*/
    memset( (PBYTE)&DevStr, 0, sizeof(DEVICESTRUCT) );

    DevStr.DevDescriptName = DMAChnText;
    DevStr.DevType         = DS_TYPE_PLANAR_CHIPSET;

    DevStr.pAdjunctList    = Adjunct;
    Adjunct[0].pNextAdj    = NULL;
    Adjunct[0].AdjLength   = sizeof(ADJUNCT);
    Adjunct[0].AdjType     = ADJ_DEVICE_NUMBER;

    memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );

    ResStr.ResourceType              = RS_TYPE_IO;
    ResStr.IOResource.NumIOPorts     =  2;
    ResStr.IOResource.IOAddressLines = 16;


    for ( j = 0; j < NUM_DMA_CHANNELS; j++, m++ )
    {
      Adjunct[0].Device_Number = m;

      pDevNode = f_RMCreateDeviceNode( &DevStr );

      /*--------------------------------------*/
      /* Make DMA Node Child of DMA Subsystem */
      /*--------------------------------------*/
      f_RMAddChild( pAdptNode, pDevNode );

      /*------------------------------------------*/
      /* Assign DMA resources (ports) to DMA Node */
      /*------------------------------------------*/
      for ( p=0; p < NUM_DMA_PORT_RANGES; p++ )
      {
        ShareFlag = ( p == NUM_DMA_PORT_RANGES-1 ) ? RS_IO_SHARED    /*@V103757*/
                                                   : RS_IO_EXCLUSIVE;/*@V103757*/
        ResStr.IOResource.IOFlags = ShareFlag;                       /*@V103757*/
        ResStr.IOResource.BaseIOPort = DMAPort[m][p].BasePort;
        ResStr.IOResource.NumIOPorts = DMAPort[m][p].NumPorts;

        pResNode = f_RMCreateResourceNode( &ResStr );

        f_RMAddResource( pDevNode, pResNode);
      }

      /*---------------------------*/
      /* Create DMA resource class */
      /*---------------------------*/
      f_RMRegisterResourceClass( RS_TYPE_DMA, m, pDevNode );
    }
  }

  /*------------------------------------*/
  /* DMA CH 4 is used to cascade CH 5-7 */
  /*------------------------------------*/
  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );              /*@V107246*/

  ResStr.ResourceType              = RS_TYPE_DMA;                   /*@V107246*/
  ResStr.DMAResource.DMAChannel    = DMA_CASCADE_CH;                /*@V107246*/
  ResStr.DMAResource.DMAFlags      = RS_DMA_EXCLUSIVE;              /*@V107246*/
  pResNode = f_RMCreateResourceNode( &ResStr );                     /*@V107246*/
  f_RMAddResource( pDevNode0, pResNode);                            /*@V107246*/

  /*---------------------------------------*/
  /* Create Adapter Node for VGA Subsystem */
  /*---------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName = VGAText;

  AdptStr.BaseType  = AS_BASE_DISPLAY;
  AdptStr.SubType   = AS_SUB_VGA;
  AdptStr.HostBusType  = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth = AS_BUSWIDTH_16BIT;

  pAdptNode = f_RMCreateAdapterNode( &AdptStr );

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );

  /*-------------------------------------*/
  /* Make VGA Subsystem child of X-BUS   */
  /*-------------------------------------*/
  f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

  ResStr.ResourceType              = RS_TYPE_IO;
  ResStr.IOResource.IOAddressLines = 16;
  ResStr.IOResource.IOFlags        = RS_IO_EXCLUSIVE;

  for (i=0; i < NUM_VGA_PORT_RANGES; i++ )
  {
    ResStr.IOResource.BaseIOPort = VGAPorts[i].BasePort;
    ResStr.IOResource.NumIOPorts = VGAPorts[i].NumPorts;

    pResNode = f_RMCreateResourceNode( &ResStr );
    f_RMAddResource( pAdptNode, pResNode );
  }

  /*----------------------------------------------*/
  /* Create Adapter Structure for Timer Subsystem */
  /*----------------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );


  AdptStr.AdaptDescriptName   = TmrText;
  AdptStr.BaseType            = AS_BASE_PERIPH;
  AdptStr.SubType             = AS_SUB_TIMER;
  AdptStr.HostBusType         = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth        = AS_BUSWIDTH_16BIT;

  pAdptNode = f_RMCreateAdapterNode( &AdptStr );

  /*-------------------------------------*/
  /* Make Timer Subsystem child of X-BUS */
  /*-------------------------------------*/
  f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

  /*--------------------------------------------*/
  /* Create Device Nodes for Timer Controller   */
  /*--------------------------------------------*/
  memset( (PBYTE)&DevStr, 0, sizeof(DEVICESTRUCT) );

  DevStr.DevDescriptName = TmrChnText;
  DevStr.DevType         = DS_TYPE_PLANAR_CHIPSET;

  DevStr.pAdjunctList    = Adjunct;
  Adjunct[0].pNextAdj    = NULL;
  Adjunct[0].AdjLength   = sizeof(ADJUNCT);
  Adjunct[0].AdjType     = ADJ_DEVICE_NUMBER;

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );

  ResStr.ResourceType              = RS_TYPE_IO;
  ResStr.IOResource.NumIOPorts     =  2;
  ResStr.IOResource.IOAddressLines = 16;


  for ( i = 0; i < NUM_TIMER_CHANNELS; i++ )
  {
    Adjunct[0].Device_Number = i;

    pDevNode = f_RMCreateDeviceNode( &DevStr );

    /*---------------------------*/                                 /*@V103757*/
    /* Save Timer Ch 0 Node Addr */                                 /*@V103757*/
    /*---------------------------*/                                 /*@V103757*/
    if (!i) pDevNode0 = pDevNode;                                   /*@V103757*/

    /*--------------------------------------------------*/
    /* Make Timer Channel Node Child of Timer Subsystem */
    /*--------------------------------------------------*/
    f_RMAddChild( pAdptNode, pDevNode );

    ResStr.IOResource.BaseIOPort = TIMER_BASE_PORT + i;
    ResStr.IOResource.NumIOPorts = 1;
    ResStr.IOResource.IOFlags    = RS_IO_EXCLUSIVE;                 /*@V103757*/
    pResNode = f_RMCreateResourceNode( &ResStr );
    f_RMAddResource( pDevNode, pResNode);                           /*@V103757*/

    ResStr.IOResource.BaseIOPort = TIMER_BASE_PORT + 3;
    ResStr.IOResource.NumIOPorts = 1;
    ResStr.IOResource.IOFlags    = RS_IO_SHARED;                    /*@V103757*/
    pResNode = f_RMCreateResourceNode( &ResStr );

    f_RMAddResource( pDevNode, pResNode);

    /*-----------------------------*/
    /* Create Timer resource class */
    /*-----------------------------*/
    f_RMRegisterResourceClass( RS_TYPE_TIMER, i, pDevNode );
  }

  /*----------------------------*/                                  /*@V103757*/
  /* Assign IRQ 0 to Timer Ch 0 */                                  /*@V103757*/
  /*----------------------------*/                                  /*@V103757*/

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );              /*@V103757*/

  ResStr.ResourceType              = RS_TYPE_IRQ;                   /*@V103757*/
  ResStr.IRQResource.IRQLevel      = TIMER_0_IRQ;                   /*@V103757*/
  ResStr.IRQResource.IRQFlags      = RS_IRQ_EXCLUSIVE;              /*@V103757*/
  pResNode = f_RMCreateResourceNode( &ResStr );                     /*@V103757*/
  f_RMAddResource( pDevNode0, pResNode);                            /*@V103757*/


  /*-------------------------------------------*/
  /* Create BIOS_ROM pseudo adapter and assign */
  /* BIOS areas to it.                         */
  /*-------------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );


  AdptStr.AdaptDescriptName   = BIOSText;
  AdptStr.BaseType            = AS_BASE_MEMORY;
  AdptStr.SubType             = AS_SUB_BIOS_ROM;
  AdptStr.HostBusType         = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth        = AS_BUSWIDTH_8BIT;

  pAdptNode = f_RMCreateAdapterNode( &AdptStr );

  /*-----------------------------------------------*/
  /* Make BIOS_ROM pseudo adapter child of X-BUS   */
  /*-----------------------------------------------*/
  f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

  /*---------------------------------------------*/
  /* Scan C0000 - DFFFF and assign ROMs found to */
  /* BIOS_ROM adapter as MEM Resources           */
  /*---------------------------------------------*/
  RMInitROMScan( pAdptNode );

  /*-------------------------------------------*/
  /* Create RTC adapter                        */
  /*-------------------------------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName   = RTCText;
  AdptStr.BaseType            = AS_BASE_PERIPH;
  AdptStr.SubType             = AS_SUB_RTC;
  AdptStr.HostBusType         = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth        = AS_BUSWIDTH_8BIT;

  pAdptNode = f_RMCreateAdapterNode( &AdptStr );

  /*-----------------------------------*/
  /* Make RTC Adapter child of X-BUS   */
  /*-----------------------------------*/
  f_RMAddChild( PDevPtrs[PDEV_XBUS], pAdptNode );

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );

  ResStr.ResourceType              = RS_TYPE_IO;
  ResStr.IOResource.IOAddressLines = 16;
  ResStr.IOResource.IOFlags        = RS_IO_EXCLUSIVE;
  ResStr.IOResource.BaseIOPort     = RTC_BASE_PORT;
  ResStr.IOResource.NumIOPorts     = NUM_RTC_PORTS;

  pResNode = f_RMCreateResourceNode( &ResStr );

  f_RMAddResource( pAdptNode, pResNode);

  memset( (PBYTE)&ResStr, 0, sizeof(RESOURCESTRUCT) );              /*@V103757*/

  ResStr.ResourceType              = RS_TYPE_IRQ;                   /*@V103757*/
  ResStr.IRQResource.IRQFlags      = RS_IRQ_EXCLUSIVE;              /*@V103757*/
  ResStr.IRQResource.IRQLevel      = RTC_IRQ;                       /*@V103757*/

  pResNode = f_RMCreateResourceNode( &ResStr );                     /*@V103757*/

  f_RMAddResource( pAdptNode, pResNode);

  return( PDevPtrs[PDEV_XBUS] );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitISA                                              */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMInitISA( PMACHINE_CONFIG_INFO pMCHI, PRMNODE pCpuNode )
{
  ADAPTERSTRUCT         AdptStr;
  PRMNODE               pBusNode;

  /*----------------------*/
  /* Create ISA Bus Node  */
  /*----------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName   = ISABusText;
  AdptStr.HostBusType         = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth        = AS_BUSWIDTH_16BIT;
  pBusNode = f_RMCreateAdapterNode( &AdptStr );

  /*---------------------------------*/
  /* Make ISA-BUS a child of the CPU */
  /*---------------------------------*/
  f_RMAddChild( pCpuNode, pBusNode );

  return( pBusNode );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitPCI                                              */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMInitPCI( PMACHINE_CONFIG_INFO pMCHI, PRMNODE pCpuNode )
{
  ADAPTERSTRUCT         AdptStr;
  PRMNODE               pBusNode;

  /*----------------------*/
  /* Create PCI Bus Node  */
  /*----------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName = PCIBusText;
  AdptStr.HostBusType       = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth      = AS_BUSWIDTH_32BIT;
  PDevPtrs[PDEV_PCIBUS] = f_RMCreateAdapterNode( &AdptStr );

  /*---------------------------------*/
  /* Make PCI-BUS a child of the CPU */
  /*---------------------------------*/
  f_RMAddChild( pCpuNode, PDevPtrs[PDEV_PCIBUS] );

  return( PDevPtrs[PDEV_PCIBUS] );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitMCA                                              */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMInitMCA( PMACHINE_CONFIG_INFO pMCHI, PRMNODE pCpuNode )
{
  ADAPTERSTRUCT         AdptStr;
  PRMNODE               pBusNode;

  /*----------------------*/
  /* Create MCA Bus Node  */
  /*----------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName = MCABusText;
  AdptStr.HostBusType       = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth      = AS_BUSWIDTH_32BIT;
  pBusNode = f_RMCreateAdapterNode( &AdptStr );

  /*---------------------------------*/
  /* Make MCA-BUS a child of the CPU */
  /*---------------------------------*/
  f_RMAddChild( pCpuNode, pBusNode );

  return( pBusNode );
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitEISA                                             */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

PRMNODE NEAR RMInitEISA( PMACHINE_CONFIG_INFO pMCHI, PRMNODE pCpuNode )
{
  ADAPTERSTRUCT         AdptStr;
  PRMNODE               pBusNode;
  PRMNODE               pSlotNode;
  UCHAR                 i,l;


  /*-----------------------*/
  /* Create EISA Bus Node  */
  /*-----------------------*/
  memset( (PBYTE)&AdptStr, 0, sizeof(ADAPTERSTRUCT) );

  AdptStr.AdaptDescriptName = EISABusText;
  AdptStr.HostBusType       = AS_HOSTBUS_PLANAR;
  AdptStr.HostBusWidth      = AS_BUSWIDTH_32BIT;
  pBusNode = f_RMCreateAdapterNode( &AdptStr );

  /*----------------------------------*/
  /* Make EISA-BUS a child of the CPU */
  /*----------------------------------*/
  f_RMAddChild( pCpuNode, pBusNode );

  return( pBusNode );

#if 0

  SlotDevice.DevDescriptName = EISASlotDescript;

  /*-----------------------------------------*/
  /* Enumerate Slots and Create Slot Devices */
  /*-----------------------------------------*/

  l = strlen(EISASlotDescript)-1;

  for(i=1;i<CFG_MAX_EISA_SLOTS;i++) {    /* For each possible slot */
     _asm {
          pusha                          /* Save Registers     */
          mov ax, EISA_SLOT_INFO_16      /* ax - EISA Function */
          mov cl, i                      /* cx - Slot          */
          int 0x15                       /* EISA BIOS Call     */
          or ah, ah                      /* error?             */
          popa                           /* restore regs       */
          jnz eisadone                   /* yes, no slot       */
     }

     /*---------------------------*/
     /* Put Slot Number in String */
     /*---------------------------*/


     if (i<10)
        EISASlotDescript[l-1] = ' ';
     else
        EISASlotDescript[l-1] = '1';

     EISASlotDescript[l] = '0' + i;

     pSlotNode = f_RMCreateDeviceNode( &SlotDevice );

     eisadone:  ;      /* Null Statement needed for eisadone label */


  }

  return( pBusNode );
#endif

}
/*--------------------------------------------------------*/
/*                                                        */
/* RMInitROMScan                                          */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMInitROMScan( PRMNODE pRomAdpt )
{
  RESOURCESTRUCT        ResStr;
  PRESNODE              pResNode;

  ULONG                 Addr;
  ULONG                 ROMLen;
  PBYTE                 pROM = 0;

  USHORT                i;
  USHORT                ModeFlag;

  memset( (PBYTE) &ResStr, 0, sizeof(RESOURCESTRUCT) );

  for ( Addr = MIN_MEM_RANGE;
        Addr < MAX_MEM_RANGE;
        Addr += (64*1024L)    )
  {
    if ( !DevHelp_PhysToVirt( (ULONG)   Addr,
                              (USHORT)  0,
                              (PVOID)   &pROM,
                              (PUSHORT) &ModeFlag   ) )
    {
      for ( i=0; i < 32; i++, pROM += 2*1024)
      {
        if ( *(PUSHORT)pROM == 0xAA55 )
        {
          ROMLen = ((ULONG)pROM[2]) << 9;

          if ( !ROMLen )
          {
            continue;
          }
          if ( ROMLen > (64*1024L) )
          {
            ROMLen = (64*1024L);
          }

          ResStr.ResourceType         = RS_TYPE_MEM;
          ResStr.MEMResource.MemBase  = Addr+OFFSETOF(pROM);
          ResStr.MEMResource.MemSize  = ROMLen;
          ResStr.MEMResource.MemFlags = RS_MEM_SHARED;

          if ( !f_RMCheckMEMConflict( &ResStr.MEMResource ) )
          {
            pResNode = f_RMCreateResourceNode( &ResStr );
            f_RMAddResource( pRomAdpt, pResNode);
          }
        }
      }
    }
  }
}


/*--------------------------------------------------------*/
/*                                                        */
/* RMInitLDEV                                             */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMInitLDEV()
{
  LDEVSTRUCT    LDevStr;

  USHORT        Class;
  USHORT        i;

  /*---------------------------------*/
  /* Create Root LDEV Node           */
  /*---------------------------------*/
  memset( (PBYTE) &LDevStr, 0, sizeof(LDEVSTRUCT));
  LDevStr.LDevDescriptName =  LDevNodes[0].Name;
  Class = LDevStr.LDevClass = LDevNodes[0].Class;

  LDevPtrs[Class] = f_RMCreateLDEVNode( &LDevStr );
  f_RMRegisterNode( (PDRVRNODE) PDevPtrs[PDEV_RMDD],
                    (PRMNODE)   LDevPtrs[Class] );

  /*--------------------------------------------------------------*/
  /* Create LDEV class nodes for DASD, CDROM, SERIAL, PRT, etc... */
  /*--------------------------------------------------------------*/
  for ( i=1; i < NUM_LDEV_CLASSES; i++ )
  {
    LDevStr.LDevDescriptName  = LDevNodes[i].Name;
    Class = LDevStr.LDevClass = LDevNodes[i].Class;
    LDevStr.LDevFlags = 0;

    LDevPtrs[Class] = f_RMCreateLDEVNode( &LDevStr );

    f_RMLinkLDEVNode( LDevPtrs[LDEV_CLASS_ROOT], LDevPtrs[Class], NULL );
  }
}

/*--------------------------------------------------------*/
/*                                                        */
/* RMInitPseudoHandleList                                 */
/*                                                        */
/*                                                        */
/*                                                        */
/*--------------------------------------------------------*/

VOID NEAR RMInitPseudoHandles()
{

  PseudoLookup[0].pRMNode  = PDevPtrs[PDEV_ROOT];                   /*@V103757*/
  PseudoLookup[0].RMHandle = HANDLE_PHYS_TREE;
  PseudoLookup[1].pRMNode  = LDevPtrs[LDEV_CLASS_ROOT];
  PseudoLookup[1].RMHandle = HANDLE_SYS_TREE;
  PseudoLookup[2].pRMNode  = PDevPtrs[PDEV_SYSBUS];
  PseudoLookup[2].RMHandle = HANDLE_DEFAULT_SYSBUS;
  PseudoLookup[3].pRMNode  = PDevPtrs[PDEV_XBUS];
  PseudoLookup[3].RMHandle = HANDLE_X_BUS;
  PseudoLookup[4].pRMNode  = PDevPtrs[PDEV_PCIBUS];
  PseudoLookup[4].RMHandle = HANDLE_PCI_BUS;


}
