/*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.      */
/*                                                                           */
/*****************************************************************************/
/*
*
*/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME: RSCINIT.C                                              */
/*                                                                            */
/*   DESCRIPTIVE NAME: IBMRSCSI initialization time rountines                 */
/*                                                                            */
/*   FUNCTION:                                                                */
/*                                                                            */
/*   NOTES:   This module is removed from the memory after INIT is completed  */
/*                                                                            */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:  InitPost                                                  */
/*                  RSCInit                                                   */
/*                                                                            */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          01/11/23  VJ              Initial Version                         */
/*  VJ2002  02/01/02  VJ              Corrections of the RM usage & INQUIRY   */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include "rsc.h"              

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  InitSubmitIORB_Wait                              */
/*                                                                    */
/* DESCRIPTIVE NAME: InitSubmitIORB_Wait                              */
/*                                                                    */
/* FUNCTION:  Calls the downstream component IORB entry point ad waits*/
/*            for the IORB tro complete                               */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT: InitSubmitIORB_Wait                                   */
/*     LINKAGE: NEAR                                                  */
/*                                                                    */
/* INPUT: NPIORB npIORB - pointer to the IORB block                   */
/*                        to pass to the downstream component         */
/*        NPUCB npUCB   - pointer to the unit control block           */
/*                                                                    */
/* EXIT-NORMAL:  always                                               */
/*                                                                    */
/* EXIT-ERROR:                                                        */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID NEAR InitSubmitIORB_Wait( NPIORB npIORB, NPUCB npUCB )

{
   (*npUCB->AdapterDriverEP) ((PVOID) (npIORB));

   while ( !(npIORB->Status & IORB_DONE) );

   return ;
} // InitSubmitIORB_Wait END


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:    SetDevType                                     */
/*                                                                    */
/* DESCRIPTIVE NAME:                                                  */
/*                                                                    */
/* FUNCTION:                                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:                                                       */
/*     LINKAGE:                                                       */
/*                                                                    */
/* INPUT: none                                                        */
/*                                                                    */
/* EXIT-NORMAL:                                                       */
/*                                                                    */
/* EXIT-ERROR:                                                        */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID NEAR SetDevType(PUCHAR pDevType, PSZ VendorID, PSZ ProductID)
{
   PDEVTYPETBL pDevTbl = &gDevTypes[0];
   UCHAR i=0;


   //*pDevType = DEVTYPE_DEFAULT; // VJ2002 Let's accept unknown device as ZIP100
   *pDevType = DEVTYPE_UNKNOWN; // VJ20020111 

   while (pDevTbl->DevType!=DEVTYPE_END_OF_GEORTBL)
   {

      if (CompareIDs(VendorID, (PSZ)pDevTbl->VendorID, sizeof(pDevTbl->VendorID)) &&
          CompareIDs(ProductID, (PSZ)pDevTbl->ProductID, sizeof(pDevTbl->ProductID)))
      {
         *pDevType=pDevTbl->DevType;
         break;
      }
      pDevTbl++;
   }

   return;
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:    RSCBuildCBs                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  RSCBuildCBs                                     */
/*                                                                    */
/* FUNCTION:  This function performs control blocks allocation for    */
/*            the devices accepeted for filtering.                    */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:  INIT                                                     */
/*                                                                    */
/* ENTRY POINT: RSCBuildCBs                                           */
/*     LINKAGE: NEAR                                                  */
/*                                                                    */
/* INPUT: none                                                        */
/*                                                                    */
/* EXIT-NORMAL: UCBs are allocated                                    */
/*                                                                    */
/* EXIT-ERROR:                                                        */
/*                                                                    */
/* EFFECTS:   gUT - global unit table                                 */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:        FromatName                                     */
/*                     InitSubmitIORB_Wait                            */
/*                     SetDevType                                     */
/*                                                                    */
/* EXTERNAL REFERENCES:                                               */
/*    ROUTINES:       DevHelp_GetDOSVar                               */
/*                    DevHelp_RegisterDeviceClass                     */
/*                    SetMem                                          */
/*                    BuildIORB                                       */
/*                    VPrint                                          */
/*                    RMUpdateAdjunct                                 */
/*                    CopyBytes                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID RSCBuildCBs( VOID )   
{
   USHORT                rc;               /* Return Code from function call */
   NPBYTE                npNextByte;
   NPUCB                 npUCB;            /* Near Pointer to current UnitCB */
   NPIORB                pIORB;            /* Near Pointer to IORB           */
   NPIORB_CONFIGURATION  npConfIORB;       /* Near Pointer to IORB           */
   PDEVICETABLE          pDeviceTable;     /* Far Pointer to device table    */
   NPADAPTERINFO         pAdapterInfo;     /* Near Pointer to AdapterInfo    */
   USHORT                i, j, k;          /* Indices/counters               */
   USHORT                FilterADDHandle2; /* Another Filter's Handle        */
   struct                DevClassTableStruc far *pDriverTable;   /* ptr to registered ADD EntryPts */
   VOID (FAR * DriverEP) (PIORB);           /* Driver Entry Point            */
   VOID (FAR * DriverEPF)(PIORB);           /* downstream  Fltr Drvr Entry Pt.*/
   ADJUNCT               ADDAdjunct;      
   ADJHANDLELIST         AdjList;         

#ifdef DEBUG
   DBGPrint( "RSCBuildCBs ENTRY\r\n");
#endif

   // verbose output
   VPrint(gVMSGs[VMSG_INITIALIZING]);
   VPrint(gVMSGs[VMSG_BLANK]);

   /* Get the adapter device tables for each adapter driver and create
    the control blocks (Unit and Adapter CBs) from the returned tables. */

   rc = DevHelp_GetDOSVar((USHORT) DHGETDOSV_DEVICECLASSTABLE, 1,
                          (PPVOID) &pDriverTable);

   SetMem((PBYTE)&gCBPool, sizeof(gCBPool), 0);
   npNextByte = (NPBYTE)&gCBPool;
   pIORB =  (NPIORB)npNextByte; 

   pDeviceTable = (PDEVICETABLE) &gDTBuf[0];

   for (i = 0; i < pDriverTable->DCCount; i++)
   {
      /* Ask (with an IORB) each ADD driver for its configuration info.
         First initialize the configuration IORB. */

      npConfIORB = (NPIORB_CONFIGURATION)pIORB;
      npConfIORB->iorbh.Length          = sizeof(IORB_CONFIGURATION);
      npConfIORB->iorbh.CommandCode     = IOCC_CONFIGURATION;
      npConfIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
      npConfIORB->iorbh.Status          = 0;
      npConfIORB->iorbh.ErrorCode       = 0;
      npConfIORB->iorbh.RequestControl  = 0;
      npConfIORB->pDeviceTable          = (PVOID) pDeviceTable;   /* Use ScratchBuf as Device Table */
      npConfIORB->DeviceTableLen        = sizeof(gDTBuf);

      /* Build the Driver Entry Pointer from 16 bit Selector/Offset */
      OFFSETOF(DriverEP)   = pDriverTable->DCTableEntries[i].DCOffset;
      SELECTOROF(DriverEP) = pDriverTable->DCTableEntries[i].DCSelector;

      /*  Fill the DeviceTable with zeroes. */
      SetMem((PBYTE)pDeviceTable, sizeof(gDTBuf), 0);

      (*DriverEP) ((PVOID)(pIORB));  /* Call the Adapter Driver. */

      while ( !(pIORB->Status & IORB_DONE) ); // Single threaded at init. So busy wait. 

      // If an error occurs, go to next adapter. 
      if (pIORB->Status & IORB_ERROR )
         continue;

#ifdef DEBUG
      DBGPrint2( "RSCBuildCBs: Driver=\"%s\" TotalAdapters=%d\r\n", 
                 (ULONG)pDriverTable->DCTableEntries[i].DCName,
                 pDeviceTable->TotalAdapters);
#endif

      for (j = 0; j < pDeviceTable->TotalAdapters; j++)
      {

         // Test for a flex type controller having at least one unit. 
         pAdapterInfo =  pDeviceTable->pAdapter[j];
         if ( !pAdapterInfo )
            continue  ;   // Failsafe check.  Goto next adapter 


#ifdef DEBUG
         DBGPrint3( "RSCBuildCBs: Adapter =\"%s\" AdapterDevBus=%xh AdapterUnits=%xh\r\n", 
                    (ULONG)(PSZ)&pAdapterInfo->AdapterName[0],
                    pAdapterInfo->AdapterDevBus, 
                    pAdapterInfo->AdapterUnits);
#endif

         if ( !pAdapterInfo->AdapterUnits || 
              (UCHAR)pAdapterInfo->AdapterDevBus!=AI_DEVBUS_SCSI_2 )
            continue;

         for (k = 0; k < pAdapterInfo->AdapterUnits; k++)
         {
#ifdef DEBUG
            DBGPrint2("RSCBuildCBs: Type=%xh Flags=%xh\r\n", 
                      pAdapterInfo->UnitInfo[k].UnitType, 
                      pAdapterInfo->UnitInfo[k].UnitFlags);
#endif

            if ( !(pAdapterInfo->UnitInfo[k].UnitType == UIB_TYPE_DISK && 
                   pAdapterInfo->UnitInfo[k].UnitFlags&UF_REMOVABLE))
               continue;
#ifdef DEBUG
            DBGPrint("RSCBUildCBs: Accepting Unit for filtering\r\n");
#endif

            npUCB = (NPUCB) npNextByte;
            npNextByte = npNextByte + sizeof(UCB); // Allocate UCB. 
            gpEndOfData = npNextByte;

            SetMem((PBYTE)npUCB, sizeof(UCB), 0); // Clean UCB memory

            npUCB->UnitInfo = pAdapterInfo->UnitInfo[k];

            npUCB->DriverUnitHandle = pAdapterInfo->UnitInfo[k].UnitHandle;

            npUCB->UnitInfo.UnitHandle = gUT.nLastEntry+1; 

            pIORB = (NPIORB)npUCB->IORBBuffer; 

            BuildIORB(npUCB, IOCC_UNIT_CONTROL, IOCM_ALLOCATE_UNIT, 0, 0);

            // CALL ADD or Filter with IORB to allocate this unit. 
            FilterADDHandle2 = pAdapterInfo->UnitInfo[k].FilterADDHandle;

#ifdef DEBUG
            DBGPrint2( "Filter2 handle=%xh DriverUnitHandle=%xh\r\n", 
                       FilterADDHandle2, 
                       npUCB->DriverUnitHandle);
#endif


            if ( !FilterADDHandle2 )
            {
               (*DriverEP) ((PVOID)pIORB);  // Call Driver.
            }
            else
            {
               OFFSETOF(DriverEPF) =
               pDriverTable->DCTableEntries[FilterADDHandle2-1].DCOffset;
               SELECTOROF(DriverEPF) =
               pDriverTable->DCTableEntries[FilterADDHandle2-1].DCSelector;

               (*DriverEPF) ((PVOID)pIORB); // Call Filter.
            }

            while ( !(pIORB->Status & IORB_DONE) )  // Wait till done.
               ;

#ifdef DEBUG
            DBGPrint1( "Allocate Status=%xh\r\n", pIORB->Status);
#endif

            if ( !(pIORB->Status & IORB_ERROR) )
            {
               // Save the callable entry point of the adapter driver. If
               //   the unit is being filtered, use the entry point of the
               //   filter driver.
               //   The downstream driver handle will be the downstream
               //   filter's handle if a filter exists, else it will be the
               //   ADD's driver handle. 

               npUCB->AdapterDriverEP = FilterADDHandle2 ? DriverEPF : DriverEP;


               // Register ZIP filter exactly once.
               if ( !(gRSCFlags & FF_REGISTERED) )
               {
                  rc = DevHelp_RegisterDeviceClass((NPSZ) &FilterName,
                                                   (PFN)  &RSCIORBEntry,
                                                   (USHORT) 0,
                                                   (USHORT) 1,
                                                   (PUSHORT) &gRSCHandle);

#ifdef DEBUG

                  DBGPrint1("RSCBuildCBs: DevHelp_RegisterDeviceClass rc=%xh\r\n", rc);
#endif

                  if (!rc )
                  {
                     gRSCFlags |= FF_REGISTERED;


                     VPrint( gVMSGs[VMSG_ACCEPTING]    );
                     VPrint( gVMSGs[VMSG_BLANK]        );
                     VPrint( gVMSGs[VMSG_DEVLIST_HEAD] );
                     VPrint( gVMSGs[VMSG_LINE]         );

                  }
                  else
                  {
                     VPrint(gVMSGs[VMSG_DEVCLASS_FAILED]);
                     return;
                  }
               }

               if ( hRMDriver )  // VJ2002
               {
                  // VJ2002
                  SetMem( (PBYTE) &AdjList, sizeof(ADJHANDLELIST),0 );  
                  AdjList.cMaxHandles = 1;                               

                  SetMem( (PBYTE) &ADDAdjunct, sizeof(ADJUNCT),0 );

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

                  ADDAdjunct.Add_Unit.UnitHandle  = npUCB->DriverUnitHandle;

                  ADDAdjunct.Add_Unit.ADDHandle = FilterADDHandle2 ? gRSCHandle : i+1;

                  RMAdjToHandleList( (PADJUNCT)       &ADDAdjunct,
                                     (HADAPTER)       HANDLE_PHYS_TREE,  
                                     (PADJHANDLELIST) &AdjList );  
               } // VJ2002
               // Issue change unit info to update unitinfo to contain:
               // 1. Our Filter handle,  2. our Filter unit handle.

               npUCB->UnitInfo.FilterADDHandle = gRSCHandle; 
               npUCB->UnitInfo.UnitHandle = gUT.nLastEntry+1;  

               if ( hRMDriver && AdjList.cHandles ) // VJ2002
               {
                  ADDAdjunct.Add_Unit.ADDHandle  = gRSCHandle;
                  ADDAdjunct.Add_Unit.UnitHandle = gUT.nLastEntry+1;

                  RMUpdateAdjunct( (HDRIVER)  hRMDriver,
                                   (HDEVICE)  AdjList.Adj[0].hAdapter,
                                   (USHORT)   AdjList.Adj[0].AdjIndex, 
                                   (PADJUNCT) &ADDAdjunct   );         
               }

               BuildIORB(npUCB, IOCC_UNIT_CONTROL, IOCM_CHANGE_UNITINFO, 0, 0);

               InitSubmitIORB_Wait ((NPIORB)pIORB, npUCB);

               if (!(pIORB->Status&IORB_ERROR))
               {
                  CHAR  VendorID[MAX_VENDOR_ID_SIZE+1];
                  CHAR  ProductID[MAX_PRODUCT_ID_SIZE+1];
                  CHAR  Revision[MAX_REVISION_SIZE+1];
                  CHAR  AdapterName[MAXADAPTERNAMELEN+1];
                  CHAR  DCName[MAXDEVCLASSNAMELEN+1];


                  // execute SCSI INQUIRY to obtain device IDs
#ifdef DEBUG     
                  DBGPrint1( "Unit %xh allocated\r\n", (USHORT)gUT.nLastEntry+1);
#endif

                  gUT.npUCB[gUT.nLastEntry++] = npUCB;

                  // build ADAPTER_PASSTHRU with SCSI INQUIRY CDB
                  BuildIORB( npUCB, 
                             IOCC_ADAPTER_PASSTHRU, 
                             IOCM_EXECUTE_CDB, 
                             (ULONG)(PVOID)&SCSIInquiry, 
                             (ULONG)sizeof(SCSIInquiry));
#ifdef DEBUG
                  DBGPrint2( "INQUIRY IORB=%lxh status %xh\r\n", 
                             (ULONG)(PIORB)pIORB, 
                             pIORB->Status);
#endif
                  // Call the downstream component with EXECUTE_CDB
                  InitSubmitIORB_Wait (pIORB, npUCB);

#ifdef DEBUG
                  DBGPrint2( "INQUIRY status=%xh error=%xh\r\n",
                             pIORB->Status,
                             pIORB->ErrorCode );
#endif

                  if (!pIORB->ErrorCode)
                  {
                     PINQDATA pInq = (PINQDATA)&npUCB->Buffer;
#ifdef DEBUG
                     DBGPrint4("INQUIRY Success. VendorID=\"%s\" ProductID=\"%s\" Revision=\"%s\" DClass=\"%s\"\r\n",
                               (ULONG)pInq->VendorID,
                               (ULONG)pInq->ProductID,
                               (ULONG)pInq->Revision,
                               (ULONG)pDriverTable->DCTableEntries[i].DCName);
#endif
                     // copy names from the INQUIRY buffer to the local buffers
                     CopyBytes((PBYTE)pInq->VendorID,  (PBYTE)VendorID,  MAX_VENDOR_ID_SIZE);
                     CopyBytes((PBYTE)pInq->ProductID, (PBYTE)ProductID, MAX_PRODUCT_ID_SIZE);
                     CopyBytes((PBYTE)pInq->Revision,  (PBYTE)Revision,  MAX_REVISION_SIZE);

                  }
                  else
                  {
                     CopyBytes(ID_UNKNOWN, VendorID, sizeof(ID_UNKNOWN));
                     CopyBytes(ID_UNKNOWN, ProductID, sizeof(ID_UNKNOWN));
                     CopyBytes("    ", Revision, MAX_REVISION_SIZE);
                  }

                  CopyBytes((PBYTE)pAdapterInfo->AdapterName, (PBYTE)AdapterName, MAXADAPTERNAMELEN);
                  CopyBytes((PBYTE)pDriverTable->DCTableEntries[i].DCName, (PBYTE)DCName, MAXDEVCLASSNAMELEN);

                  // format IDs for the smooth output
                  FormatName(      DCName, sizeof(DCName));
                  FormatName( AdapterName, sizeof(AdapterName));
                  FormatName(    VendorID, sizeof(VendorID));
                  FormatName(   ProductID, sizeof(ProductID));
                  FormatName(    Revision, sizeof(Revision));

                  // output accepted units information
                  VPrint6((PSZ)gVMSGs[VMSG_UNIT_LISTING], 
                          (ULONG)gUT.nLastEntry-1L,
                          (ULONG)(PSZ)AdapterName,
                          (ULONG)(PSZ)DCName,                
                          (ULONG)(PSZ)VendorID,                 
                          (ULONG)(PSZ)ProductID,                
                          (ULONG)(PSZ)Revision);  

                  // determine device type
                  SetDevType(&npUCB->DevType, VendorID, ProductID);

#ifdef DEBUG
                  DBGPrint1("Device type=%xh\r\n", npUCB->DevType);
#endif

               }
               else
               {
                  VPrint(gVMSGs[VMSG_ALLOC_FAILED]);
               }

               BuildIORB(npUCB, IOCC_UNIT_CONTROL, IOCM_DEALLOCATE_UNIT, 0, 0);

               InitSubmitIORB_Wait( pIORB, npUCB );

               if (gUT.nLastEntry==MAX_UNITS)
                  return;

            }  // end of "if ( !(pIORB->iorbh.Status & IORB_ERROR) )"
         }  // end unit loop
      }  // end adapter loop 
   }// end Driver loop

   return;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  ProcessVerbose                                   */
/*                                                                    */
/* DESCRIPTIVE NAME:  ProcessVerbose                                  */
/*                                                                    */
/* FUNCTION:  Search command line  for accepted parameters            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:  ProcessVerbose                                       */
/*     LINKAGE:  NEAR                                                 */
/*                                                                    */
/* INPUT: PCHAR pCmdStr - pointer to the CONFIG.SYS parameters        */
/*                                                                    */
/* EXIT-NORMAL: always                                                */
/*                                                                    */
/* EXIT-ERROR:                                                        */
/*                                                                    */
/* EFFECTS: gpVRB->VerboseMode is set according the command lines keys*/
/*                                                                    */
/* INTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID ProcessVerbose(PCHAR pCmdStr)
{
   while (*pCmdStr && *(pCmdStr+1)) // string ends with double '0'
   {
      if (*pCmdStr++=='/')
      {
         if (*pCmdStr=='V')
            gpVRB->VerboseMode|=VERBOSE_MODE;

         if (*pCmdStr=='W')
            gpVRB->VerboseMode|=VERBOSE_WAIT_MODE;
      }
   }

#ifdef DEBUG
   DBGPrint1("ProcessVerbose VERBOSE mode = %d\r\n", gpVRB->VerboseMode);
#endif
   return;

} // ProcessVerbose END

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:   RSCInit                                         */
/*                                                                    */
/* DESCRIPTIVE NAME: RSCInit                                          */
/*                                                                    */
/* FUNCTION:  IBMRSCSI initialization routine                         */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: init                                                      */
/*                                                                    */
/* ENTRY POINT:  RSCInit                                              */
/*     LINKAGE:  FAR                                                  */
/*                                                                    */
/* INPUT: none                                                        */
/*                                                                    */
/* EXIT-NORMAL: IBMRSCSI is initialized, rc value set to 0            */
/*                                                                    */
/* EXIT-ERROR:  IBMRSCSI init failed. rc contains error code          */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:        ProcessVerbose                                 */
/*                     RSCBuildCBs                                    */
/*                                                                    */
/*                                                                    */
/* EXTERNAL REFERENCES:                                               */
/*    ROUTINES:        RMCreateDriver                                 */
/*                     RMDestroyDriver                                */
/*                     VPrint                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT FAR RSCInit( PRPINITIN pRP )
{

   USHORT     rc;
   PRPINITOUT pRPO = (PRPINITOUT) pRP;  /* Output for Init RP */
   PSZ        cmdLine;

   /* Initialize variables */

#ifdef DEBUG
   DBGPrint1( "RSCInit entry gRSCFlags=%xh\r\n", gRSCFlags); // VJ2002
#endif

   if (gRSCFlags & FF_INIT_COMPLETE)
      return (STDON + STERR + ERROR_I24_QUIET_INIT_FAIL); // VJ2002


   // process CONFIG.SYS BASEDEV= line parameters
   cmdLine=(PSZ) MAKEP( SELECTOROF(pRP->InitArgs),
                        OFFSETOF(((PDDD_PARM_LIST)pRP->InitArgs)->cmd_line_args) );


   ProcessVerbose((PCHAR)cmdLine);

   Device_Help = pRP->DevHlpEP;  /* Save DevHlp Entry Point at init */

   // rc =                                           // VJ2002 
   RMCreateDriver( (PDRIVERSTRUCT) &gRMDriverStr,    
                   (PHDRIVER)      &hRMDriver    );                 

   RSCBuildCBs(); // Find SCSI Removables units and build corresponding Control Blocks. 

   if (gUT.nLastEntry == 0)
   { // If no units, then deinstall. 
      if ( hRMDriver)                         // VJ2002
         RMDestroyDriver( (HDRIVER) hRMDriver );
      // Init Request Packet OUT is the return state of Init RequestPacket IN. 
      pRPO->Unit = 0;
      pRPO->CodeEnd = 0;
      pRPO->DataEnd = 0;

      rc = STDON + STERR + ERROR_I24_QUIET_INIT_FAIL;

      VPrint(gVMSGs[VMSG_BLANK]);
      VPrint(gVMSGs[VMSG_INIT_FAILED]);


   }
   else
   {

      pRPO->Unit = 0;
      pRPO->CodeEnd = (USHORT) &RSCInit - 1;
      pRPO->DataEnd = (USHORT) gpEndOfData;

#ifdef DEBUG
      pRPO->DataEnd = (USHORT)&gpEndOfData;
#endif 

      rc = STDON;

   }

#ifdef DEBUG                  
   DBGPrint3( "RSCInit exit rc=%xh CodeEnd=%xh DataEnd=%xh\r\n", 
              rc, 
              pRPO->CodeEnd, 
              pRPO->DataEnd);
#endif

   VPrint(gVMSGs[VMSG_BLANK]);

   if (gpVRB->VerboseMode&VERBOSE_WAIT_MODE) // verbose wait mode
      VPrint(gVMSGs[VMSG_WAIT_MODE]);

   VPrint(gVMSGs[VMSG_END_OF_OUTPUT]);

   gRSCFlags |= FF_INIT_COMPLETE;

   return (rc);  

}  // RSCInit END

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  FormatName                                       */
/*                                                                    */
/* DESCRIPTIVE NAME: FormatName                                       */
/*                                                                    */
/* FUNCTION:  Formats the string to match the length by replacing 0's */
/*            with blanks                                             */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT:  FormatName                                           */
/*     LINKAGE:  NEAR                                                 */
/*                                                                    */
/* INPUT: PSZ pString - pointer to the string                         */
/*        USHORT StrLen - string length                               */
/*                                                                    */
/* EXIT-NORMAL:  Always                                               */
/*                                                                    */
/* EXIT-ERROR:  never                                                 */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID FormatName(PSZ pString, USHORT StrLen)
{
   USHORT i;

   for (i=0; i<(StrLen-1); i++)
   {
      if (*pString==0)
         *pString=' ';

      pString++;
   }

   *pString = 0;

   return;
} // FormatName END

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  CompareIDs                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:                                                  */
/*                                                                    */
/* FUNCTION: Compare n number of characters in 2 strings, return      */
/*           TRUE if = If s1 is in lower case, convert to upper       */
/*           prior to comparing.                                      */ 
/*                                                                    */
/*                                                                    */
/* NOTES: Does not require length match.                              */
/*        Replaces zerro bytes with blanks.                           */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT: CompareIDs                                            */
/*     LINKAGE: NEAR                                                  */
/*                                                                    */
/* INPUT: PSZ s1 - string 1                                           */
/*        PSZ s2 - string 2                                           */
/*        USHORT n - no of bytes to compare                           */
/*                                                                    */
/* EXIT-NORMAL: TRUE is returned, strings match                       */
/*                                                                    */
/* EXIT-ERROR:  FALSE is returned, string don't match                 */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES: none                                          */
/*    ROUTINES:                                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL NEAR CompareIDs( PSZ s1, PSZ s2, USHORT n )                        
{
   USHORT i;
   CHAR temp;

#ifdef DEBUG
   DBGPrint3("CompareIDs ENTRY s1=\"%s\" s2=\"%s\" len=%d\r\n", (ULONG)s1, (ULONG)s2, n);
#endif

   for ( i=0; i < n; i++ )
   {
      if ( *s1 != *s2 )
      {
         if (( *s1 >= 'a' ) && ( *s1 <= 'z' ))
         {
            temp = (CHAR)*s1 - (CHAR)' ';
            if ( temp == (CHAR)*s2 )
               continue;
         }
         else
            if ((*s1==' ' && *s2==0) || (*s1==0 && *s2==' '))
            continue;

#ifdef DEBUG
         DBGPrint1("CompareIDs EXIT. Strings not match at position i=%d\r\n", i);
#endif
         return (FALSE);
      }

      s1++, s2++;
   }

#ifdef DEBUG
   DBGPrint("CompareIDs EXIT. Strings match\r\n");
#endif

   return (TRUE);
}

