/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1992 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 source code is provided to you solely for       */
/*    the purpose of assisting you in your development of OS/2 device        */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Developer Connection Device Driver       */
/*    Source Kit for OS/2. This Copyright statement may not be removed.      */
/*                                                                           */
/*****************************************************************************/
/*static char *SCCSID = "%w% %e%";*/
/**************************************************************************
 *
 * SOURCE FILE NAME = S506OEMI.C
 *
 * DESCRIPTIVE NAME = IBM1S506.ADD - Adapter Driver for ST506/IDE DASD
 *
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION : Adapter Driver OEM Specific routines, resident during
 *               initialization only
 *
 * Purpose:
 *
 * Note:
 *  All functions contained within assume the user first has called
 *  GetBiosInfo to setup global pointers to OEMHLP.
 *
*/
#define INCL_NOBASEAPI
#define INCL_NOPMAPI
#define INCL_NO_SCB
#define INCL_DOSERRORS
#include "os2.h"
#include "dskinit.h"
#include "dhcalls.h"
#include "strat2.h"
#include "reqpkt.h"
#include "iorb.h"
#include "addcalls.h"
#include "s506cons.h"
#include "s506regs.h"
#include "s506type.h"
#include "s506ext.h"
#include "s506pro.h"                                                /*@V129765*/


UCHAR SetupOEMHlp()
{

   /* Setup Global OEMHlp Variables */
   if (DevHelp_AttachDD( OEMDriverName, (NPBYTE)&DDTable) )         /*@V153732*/
      return(1);    /* Couldn't find OEMHLP's IDC */

   if ((DDTable.ProtIDCEntry == NULL) || (DDTable.ProtIDC_DS == 0))
      return(1);    /*     Entry Point or Data Segment */

   pOEMHLPEntry = DDTable.ProtIDCEntry;
   OemhlpDS = DDTable.ProtIDC_DS;

   return( 0 );
}


BOOL NEAR PresenseCheckPCI( NPATBL npAT, PCI_DEVICE PCIDev )        /*@VVVVVVV*/
{                                                                   /*@V119250*/
   USHORT            rc = 0;
   RP_GENIOCTL       IOCtlRP;
   PRPH              pRPH = (PRPH)&IOCtlRP;
   PCI_DATA          PCIDataPkt;
   PCI_PARM_FIND_DEV PCIParmPkt;
   ULONG             Data;
   USHORT            i;                                             /*@V129765*/
   UCHAR PciBusNum;                                                 /*@V151345*/
   UCHAR PciDevFunc;                                                /*@V151345*/
   struct {                                                         /*@V129765*/
      UCHAR          ucRevision;                                    /*@V129765*/
      UCHAR          ucProgIF;                                      /*@V129765*/
      UCHAR          ucSubClass;                                    /*@V129765*/
      UCHAR          ucBaseClass;                                   /*@V129765*/
   } ConfigReg;                                                     /*@V129765*/

   Setmem ( (PBYTE) &PCIDataPkt, 0, sizeof(PCIDataPkt));

   if ( !(rc = SetupOEMHlp()))
   {
      /*----------------------------------*/
      /* Determine if PCI BIOS is present */
      /*----------------------------------*/

      /* Setup Parm Packet */
      PCIParmPkt.PCISubFunc = PCI_GET_BIOS_INFO;

      /* Setup IOCTL Request Packet */
      IOCtlRP.Category = 0x00;
      IOCtlRP.Function = PCI_FUNC;
      IOCtlRP.ParmPacket = (PUCHAR)&PCIParmPkt;
      IOCtlRP.DataPacket = (PUCHAR)&PCIDataPkt;
      IOCtlRP.rph.Len = sizeof(IOCtlRP);
      IOCtlRP.rph.Unit = 0;
      IOCtlRP.rph.Cmd  = 0x10;      /* Generic IOCtl */
      IOCtlRP.rph.Status = 0;

      CallOEMHlp(pRPH);

      if (IOCtlRP.rph.Status & STERR)
         rc = 1;

      if (PCIDataPkt.bReturn != PCI_SUCCESSFUL)
         rc = 1;
   }

   if (!rc)
   {                                                                /*@V129765*/
      MaxPCIBuses = PCIDataPkt.Data_Bios_Info.LastBus + 1;          /*@V129765*/
      PCIMajorVer = PCIDataPkt.Data_Bios_Info.MajorVer;             /*@V129765*/
      PCIMinorVer = PCIDataPkt.Data_Bios_Info.MinorVer;             /*@V129765*/

      if( !(rc = FindPCIDevice( &npAT->PCIInfo, PCIDev )) )         /*@V129765*/
      {                                                             /*@VVVVVVV*/
         /* CHL                                                       @V151345
         ** We have found the PCI device, save the bus number,        @V151345
         ** device/function number for the use of the other           @V151345
         ** channel.  The other channel needs to be filled with       @V151345
         ** the same identifucation data.                             @V151345
         */                                                         /*@V151345*/
         PciDevFunc = npAT->PCIInfo.DevFunc;                        /*@V151345*/
         PciBusNum  = npAT->PCIInfo.BusNum;                         /*@V151345*/

         npAT->npPCIDeviceMsg = PCIDev.npDeviceMsg;

         /* Begin [001] Add special case for Intel 82371FB, PIXX3 & PIIX4 ... */

         if( (PCIDev.Ident.Vendor ==
              PCIDevice[PCID_INTEL82371FB].Ident.Vendor) &&         /*@V156660*/
           ( (PCIDev.Ident.Device ==
              PCIDevice[PCID_INTEL82371FB].Ident.Device) ||         /*@V156660*/
             (PCIDev.Ident.Device ==
              PCIDevice[PCID_PIIX3].Ident.Device) ||
             (PCIDev.Ident.Device ==                                /*@V156660*/
              PCIDevice[PCID_PIIX4].Ident.Device) ||                
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801AB].Ident.Device) ||              
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801BA_1].Ident.Device) ||            
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801BA_2].Ident.Device) ||            
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801BA_3].Ident.Device) ||            
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801BA_4].Ident.Device) ||            
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801BA_5].Ident.Device) ||            
             (PCIDev.Ident.Device ==                                
              PCIDevice[PCID_82801AA].Ident.Device) ) )             
         {                                                          /*@V156660*/
            /* change to same bus and device but function 1 */      /*@V156660*/

            PciDevFunc = npAT->PCIInfo.DevFunc &= 0xF8;             /*@V156660*/
            PciDevFunc = npAT->PCIInfo.DevFunc |= 0x01;             /*@V156660*/
         }
         /* End [001]  */
         if (PCIDev.Ident.Device == PCIDevice[PCID_VIA596].Ident.Device) 
         {
            PciDevFunc = npAT->PCIInfo.DevFunc |= 0x01;
         }
         if (PCIDev.Ident.Device == PCIDevice[PCID_SIS630].Ident.Device)
         {
            PciDevFunc = npAT->PCIInfo.DevFunc |= 0x01;
         }
         /*
         **  The requested PCI device was found.  Determine which, if
         **  any, IDE interfaces are implemented by the device.
         **
         **  1. Read the PCI Device Revision and Class Code
         **     registers.
         **  2. If the Programming Interface byte of the Class Code
         **     register indicates the interfaces are legacy mode,
         **     then activate the interface.
         **  3. If the Programming Interface byte indicates native
         **     mode, then search the PCI base registers to
         **     determine which IDE interfaces are active.
         */
         if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo,
                                        (UCHAR) PCIREG_CLASS_CODE,
                                        (PULONG) &ConfigReg,
                                        sizeof(ConfigReg) )) )
         {
            if( (ConfigReg.ucBaseClass == (UCHAR)PCI_MASS_STORAGE) &&
                (ConfigReg.ucSubClass  == (UCHAR)PCI_IDE_CONTROLLER) )
            {
               i = 0;

               npAT->PCIInfo.Ident.Revision = ConfigReg.ucRevision;      

               if( !(ConfigReg.ucProgIF & (UCHAR)PCI_IDE_NATIVE_IF1) &&
                   !npAT->PCIInfo.Present ) /* Interface must be unclaimed */
               {
                  npAT->PCIInfo.Ident          = PCIDev.Ident;
                  npAT->PCIInfo.Ident.Revision = ConfigReg.ucRevision;   
                  /* Index to first PCI configuration operation record */
                  npAT->PCIInfo.FirstConfigRec = PCIDev.FirstConfigRec[0];
                  npAT->npPCIDeviceMsg         = PCIDev.npDeviceMsg;
                  npAT->PCIInfo.Present        = TRUE;
                  i++;     /* Move to second IDE Adapter Table Entry */
                  npAT++;  /* Move to second IDE Adapter Table Entry */
               }
               if( !(ConfigReg.ucProgIF & (UCHAR)PCI_IDE_NATIVE_IF2) &&
                   !npAT->PCIInfo.Present ) /* Interface must be unclaimed */
               {
                  npAT->PCIInfo.Ident          = PCIDev.Ident;
                  npAT->PCIInfo.Ident.Revision = ConfigReg.ucRevision;   
                 /* CHL
                  * We have to fill in the bus number, device/function number
                  * for this "PCIInfo" because the information will be used to
                  * "Read/Write PCI Config space".
                  * If we don't do this, Read/write config space will fail.
                  */
                  npAT->PCIInfo.DevFunc        = PciDevFunc;        /*@V151345*/
                  npAT->PCIInfo.BusNum         = PciBusNum;         /*@V151345*/
                  /* Index to first PCI configuration operation record */
                  npAT->PCIInfo.FirstConfigRec = PCIDev.FirstConfigRec[1];
                  npAT->npPCIDeviceMsg         = PCIDev.npDeviceMsg;
                  npAT->PCIInfo.Present        = TRUE;
                  i++;     /* Move to third IDE Adapter Table Entry */
                  npAT++;  /* Move to third IDE Adapter Table Entry */
               }

               /*                                                     @V156660
               ** If the PCI IDE interface is NOT emulating a legacy  @V156660
               ** device at one of the standard addresses, then must  @V156660
               ** read the device's base registers from PCI config    @V156660
               ** space and use these values as the location of the   @V156660
               ** device's registers.                                 @V156660
               */                                                   /*@V156660*/
               for( ; i < MAX_ADAPTERS; i++, npAT++ )
               {
                  /* Interface must so far be unclaimed. */
                  if( !npAT->PCIInfo.Present )
                  {
                     /* Initialize PCI address components */
                     npAT->PCIInfo.DevFunc = PciDevFunc;            /*@V156660*/
                     npAT->PCIInfo.BusNum  = PciBusNum;             /*@V156660*/
                     ScanPCIBaseRegs( &npAT->PCIInfo, npAT->BasePort, PCIDev );
                  }
               }
            }  /* if( (ConfigReg.ucBaseClass == (UCHAR)PCI_MASS_STORAGE) &&... */
         }  /* if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo,... */
#ifdef DEBUG
         else
         {
            _asm  int 3
         }
#endif
      }  /* if (!rc) */                                             /*@VAAAAAA*/
   }                                                                /*@V129765*/

   return( rc );                                                    /*@V119250*/
}                                                                   /*AAAAAAAA*/


/*                                                                    @V129765
** FindPCIDevice()                                                    @VVVVVVV
**
** Find the PCI device indicated by:
**
**   PCIDevice.Ident.Vendor
**   PCIDevice.Ident.Device
**   PCIDevice.Ident.Index
**
** Try first using the PCI_FIND_DEVICE BIOS function through the OEMHlp
** Device Driver.  If PCI_FIND_DEVICE is not implemented in this machine's
** BIOS then scan the PCI bus to find the requested device.
**
** If the device is found, return(0) and the requested device's:
**
**   npPCIInfo->BusNum;
**   npPCIInfo->DevFunc;
**
** If the device is not found return( TRUE ).
*/                                                                  /*@VAAAAAA*/
BOOL NEAR FindPCIDevice( NPPCI_INFO npPCIInfo, PCI_DEVICE PCIDev )  /*@V129765*/
{
   PCI_PARM_FIND_DEV  PCIParmPkt;
   PCI_DATA           PCIDataPkt;
   RP_GENIOCTL        IOCtlRP;     /* From reqpkt.h */
   PRPH               pRPH = (PRPH)&IOCtlRP;
   UCHAR              ucBusNum, ucDevNum, ucIndex = 0;              /*@V129765*/
   UCHAR              rc = TRUE;                                    /*@V129765*/
   struct {                                                         /*@V129765*/
      USHORT          Vendor;       /*@V151345*/ /*@V129765*/
      USHORT          Device;                                       /*@V129765*/
   } ChipID;                                                        /*@V129765*/

   /* Setup Parm Packet */
   PCIParmPkt.PCISubFunc   = PCI_FIND_DEVICE;
   PCIParmPkt.Ident = PCIDev.Ident;

   /* Setup IOCTL Request Packet */
   IOCtlRP.Category = 0x00;
   IOCtlRP.Function = PCI_FUNC;
   IOCtlRP.ParmPacket = (PUCHAR)&PCIParmPkt;
   IOCtlRP.DataPacket = (PUCHAR)&PCIDataPkt;
   IOCtlRP.rph.Len = sizeof(IOCtlRP);
   IOCtlRP.rph.Unit = 0;
   IOCtlRP.rph.Cmd  = 0x10;      /* Generic IOCtl */
   IOCtlRP.rph.Status = 0;

   CallOEMHlp(pRPH);

   if( !(IOCtlRP.rph.Status & STERR) &&                             /*@V129765*/
       (PCIDataPkt.bReturn == PCI_SUCCESSFUL) )                     /*VVVVVVVV*/
   {
      /*
      ** PCI_FIND_DEVICE BIOS function worked so do not need to scan the bus.
      */
      npPCIInfo->BusNum  = PCIDataPkt.Data_Find_Dev.BusNum;
      npPCIInfo->DevFunc = PCIDataPkt.Data_Find_Dev.DevFunc;
      rc = FALSE;
   }
   else
   {
      /*
      ** The PCI_FIND_DEVICE BIOS Function is not supported so scan the
      ** bus in attempt to find the device.  DevNum is initialized to -1
      ** so that the search may continue for a another device of
      ** the same vendor and type.
      */
      for( ucBusNum = 0; ucBusNum < MaxPCIBuses; ucBusNum++ )
      {
         for( ucDevNum = 0; ucDevNum < MAX_PCI_DEVICES; ucDevNum++ )
         {
            npPCIInfo->BusNum  = ucBusNum;
            npPCIInfo->DevFunc = ucDevNum << 3;
            if( !(rc = ReadPCIConfigSpace( npPCIInfo,
                                           (UCHAR) PCIREG_VENDOR_ID,
                                           (PULONG) &ChipID,
                                           sizeof(ChipID) )) )
            {
               if( (ChipID.Vendor == PCIDev.Ident.Vendor) &&
                   (ChipID.Device == PCIDev.Ident.Device) )
               {
                  if( ucIndex == PCIDev.Ident.Index )
                     /* Found it the hard way! */
                     return( rc );
                  else
                     ucIndex++;
               }
            }  /* if( !(rc = ReadPCIConfigSpace( npPCIInfo,... */
#ifdef DEBUG
            else
               _asm { int 3 }
#endif
         }  /* for( ucDevNum = 0; ucDevNum < MAX_PCI_DEVICES; ucDevNum++ ) */
      }  /* for( ucBusNum = 0; ucBusNum < MaxPCIBuses; ucBusNum++ ) */
      rc = TRUE;

      /*
      ** Scanned the bus "by hand" and still found nothing.
      */
      npPCIInfo->BusNum  = 0;
      npPCIInfo->DevFunc = -1;
   }

   return( rc );                                                    /*@V129765*/
}                                                                   /*@VAAAAAA*/


/*                                                                    @V129765
**   ScanPCIBaseRegs()                                                @VVVVVVV
**
** Determine if the PCI IDE Interface for this Adapter Table entry
** is active.  Read the PCI Base Address Registers and compare to the
** IDE base port (BasePort) address defined for this interface number.
** If there is a match, then the IDE interface is present and active.
**
** The main purpose is to set up/activate the PCIInfo structure.  This
** function assumes the PCI address components of the PCIInfo structure
** point to a located IDE PCI device.  This function also assumes this
** Adapter Table entry has not yet been claimed; PCIInfo.Present is
** FALSE.
**
** This function has no return code, as the result is to activate the
** the PCIInfo structure.  If anything goes       or the base registers
** indicate the interface is not active, PCIInfo is left deactivated.
*/
VOID ScanPCIBaseRegs( NPPCI_INFO npPCIInfo,
                      USHORT BasePort, PCI_DEVICE PCIDev )
{
   ULONG  usDataRead;
   USHORT i;
   UCHAR  rc;

   if( BasePort )  /* BasePort must be defined to activate the interface */
   {
      for( i = 0; i < MAX_PCI_BASE_REGS; i++ )
      {
         if( !(rc = ReadPCIConfigSpace( npPCIInfo,
                                        PCIBaseAddressReg[i],
                                        (PULONG)&usDataRead,
                                        sizeof(usDataRead) )) )
         {
            usDataRead &= 0xFFF0;
            if( usDataRead == BasePort )
            {
               npPCIInfo->Ident          = PCIDev.Ident;
               /* Index to first PCI configuration operation record */
               npPCIInfo->FirstConfigRec = PCIDev.FirstConfigRec[i];
               npPCIInfo->Present        = TRUE;
               break; /* Since only 1 will match, can exit the search */
            }
         }
      }  /* for( i = 0; i < MAX_PCI_BASE_REGS; i++ ) */
   }  /* if( BasePort ) */

   return;                                                          /*@V129765*/
}                                                                   /*@VAAAAAA*/


UCHAR ReadEISAConfig( USHORT SlotNumber, PULONG CompressedID)
{
   EISA_PARM     EISAParmPkt;
   EISA_DATA     EISADataPkt;
   RP_GENIOCTL   IOCtlRP;     /* From reqpkt.h */
   PRPH          pRPH = (PRPH)&IOCtlRP;

   /* Setup Parm Packet */
   EISAParmPkt.SubFunction = 0;
   EISAParmPkt.Function    = 0;
   EISAParmPkt.SlotNumber  = SlotNumber;

   /* Setup IOCTL Request Packet */
   IOCtlRP.Category = 0x00;
   IOCtlRP.Function = EISA_READ;
   IOCtlRP.ParmPacket = (PUCHAR)&EISAParmPkt;
   IOCtlRP.DataPacket = (PUCHAR)&EISADataPkt;
   IOCtlRP.rph.Len = sizeof(IOCtlRP);
   IOCtlRP.rph.Unit = 0;
   IOCtlRP.rph.Cmd  = 0x10;      /* Generic IOCtl */
   IOCtlRP.rph.Status = 0;

   CallOEMHlp(pRPH);

   if (IOCtlRP.rph.Status & STERR)
      return( 1 );

   if (EISADataPkt.bReturn != EISA_SUCCESSFUL)
      return( 1 );

   *CompressedID = EISADataPkt.CompressedID;

   return( 0 );
}


UCHAR DPT_Present ()
{
   UCHAR rc;
   UCHAR SlotNumber;
   ULONG CompressedID;

   if ( SetupOEMHlp() )
   {
      /*-------------------------------------------------*/
      /* unable to establish communication to OEMHlp.    */
      /* Therefore, assume DPT adapters are not present. */
      /*-------------------------------------------------*/
      return( 0 );
   }

   for (SlotNumber = 0 ;SlotNumber <= MAX_EISA_SLOT ;SlotNumber++ )
   {
      CompressedID = 0;
      ReadEISAConfig( SlotNumber, &CompressedID );
      if (((CompressedID & 0xffff)   == DPT_EISA_ID) ||
          ((CompressedID & 0xffffff)  == ATT_EISA_ID) ||
          ((CompressedID & 0xffffff)  == NEC_EISA_ID))
      {
         return( 1 );  /* Found one! */
      }
   }

   return( 0 );
}

/*                                                                    @V147576
**  CMD640_0_PortState()                                              @VVVVVVV
**
**  CMD640 specific routine to determine the current state of the
**  specified IDE port on the first CMD640 chip.
**
**  Called from CheckController().
*/
#define P_ENABLE_REG   0x50              /* CFR R0 Configuration register */
#define P_ENABLE_MASK  0x40              /* Legacy mode disable bit       */
#define P0_ENABLE_REG  0x04
#define P0_ENABLE_MASK 0x01              /* Enable/disable 1st port bit   */
#define P1_ENABLE_REG  0x51
#define P1_ENABLE_MASK 0x08              /* Enable/disable 2nd port bit   */
#define MASK_SIZE      1

SHORT FAR CMD640_0_PortState( NPATBL npAT )
{
   BOOL    rc;
   ULONG   ulData;
   USHORT  Result = INDETERMINANT;

   /*
   ** First check the Base Address Enable bit in CFR R0.  If the base
   ** address registers are disabled then the CMD chip will always
   ** respond to both legacy PRIMARY and SECONDAY ports, regardless
   ** of the other configuration bits.
   */
//   if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo, P_ENABLE_REG,
//                                  &ulData, MASK_SIZE )) )
//   {
//      if( ulData & P_ENABLE_MASK )
//         /* base address registers are enabled, must check each port reg */
//         Result = INDETERMINANT;
//      else
//         Result = ON;
//   }
  /*                                                                      @V162970
  ** The above statement is no longer true. If the base address registers are disabled,
  ** we can't assume the Port state is on. The state might be in "OFF" state for
  ** the CMD IDE controller on the COMPUDYNE system. We still have to decide whether
  ** the state of the port is "ON" or "OFF". The previous assumption of state being "ON"
  ** caused the secondary CMD IDE controller on CompuDyne system not being recognized.
  */


      if( npAT->BasePort == FX_PRIMARY )
      {
         if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo, P0_ENABLE_REG,
                                        &ulData, MASK_SIZE )) )
         {
            if( ulData & P0_ENABLE_MASK )
               Result = ON;
            else
               Result = OFF;
         }
      }
      else if( npAT->BasePort == FX_SECONDARY )
      {
         if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo, P1_ENABLE_REG,
                                        &ulData, MASK_SIZE )) )
         {
            if( ulData & P1_ENABLE_MASK )
               Result = ON;
            else
               Result = OFF;

         }
      }

   return( Result );                                                /*@AAAAAAA*/
}                                                                   /*@V147576*/


/*                                                                    @V147576
**  CMD640_0_TurnPort()                                               @VVVVVVV
**
**  CMD640 specific routine to activate/deactivate the specified IDE
**  port on the first CMD640 chip.
**
**  If the CMD640 is in legacy mode then we can't dynamically
**  activate/deactivate the ports so return INDETERMINANT.
**
**  The CMD640 can activate/deactivate the 2nd IDE port but not the
**  first IDE port without affecting the 2nd IDE port.  Requests
**  on the first IDE port are returned INDETERMINANT.
**
**  Called from CheckController().
*/
SHORT FAR CMD640_0_TurnPort( NPATBL npAT, SHORT OnOff )
{
   BOOL    rc;
   ULONG   ulData;
   SHORT   Turnable;
   SHORT   Result = INDETERMINANT;

   /*
   ** First check the Base Address Enable bit in CFR R0.  If the base
   ** address registers are disabled then the CMD chip will always
   ** respond to both legacy PRIMARY and SECONDAY ports, regardless
   ** of the other configuration bits.  So the individual ports
   ** cannot be switched on and off.
   */
//   if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo, P_ENABLE_REG,
//                                  &ulData, MASK_SIZE )) )
//   {
//      if( ulData & P_ENABLE_MASK )
//         /* base address registers are enabled, so can control each port */
//         Turnable = TRUE;
//      else
//         Turnable = FALSE;
//   }
  /*                                                                      @V162970
  ** The above statement is no longer true. If the base address registers are disabled,
  ** we still can switch on/off the port. A good example is the CMD IDE controller on
  ** the COMPUDYNE system. For Compudyne system, the port state for second channel starts
  ** with "OFF" state. Sometime the "CheckCylLReg" fails and we have to turn the PORT
  ** state to "ON" and retry the "CheckCylLreg" in the "CheckController" even if the the
  ** base address registers are disabled.
  ** These changes have fixed the problem of losing secondary channel for COMPUDYNE system
  ** when the jumper is on(base address register are disabled) which is default.
  */
      if( npAT->BasePort == FX_SECONDARY )
      {
         if( !(rc = ReadPCIConfigSpace( &npAT->PCIInfo, P1_ENABLE_REG,
                                        &ulData, MASK_SIZE )) )
         {
            if( OnOff == ON )
               ulData |= P1_ENABLE_MASK;
            else if( OnOff == OFF )
               ulData &= ~P1_ENABLE_MASK;

            if( !(rc = WritePCIConfigSpace( &npAT->PCIInfo, P1_ENABLE_REG,
                                            ulData, MASK_SIZE )) )
            {
               Result = CMD640_0_PortState( npAT );
            }
         }
      }

   return( Result );                                                /*@AAAAAAA*/
}                                                                   /*@V147576*/
