home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2DASD / DMINIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  54.2 KB  |  1,444 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12.  /*static char *SCCSID = "%w% %e%";*/
  13. #define SCCSID  "%w% %e%"
  14. /**************************************************************************
  15.  *
  16.  * SOURCE FILE NAME = DMINIT.C
  17.  *
  18.  * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
  19.  *
  20.  *
  21.  *
  22.  * VERSION = V2.0
  23.  *
  24.  * DATE
  25.  *
  26.  * DESCRIPTION : Initialization routines for OS/2 DASD Device Mgr
  27.  *
  28.  *
  29.  *
  30. */
  31.  
  32. #include "infoseg.h"
  33. #include "dmh.h"
  34. #include "devclass.h"
  35. #include "dskinit.h"
  36.  
  37. VOID   NEAR Build_UnitCBs (void);
  38. VOID   NEAR Build_VolCBs (void);
  39. VOID   NEAR InitDCS_VCS (void);
  40. VOID   NEAR InitCBPool (void);
  41. VOID   FAR  InitPost (PIORBH);
  42. VOID   NEAR Setup_Partition_VolCBs (void);
  43. USHORT NEAR Build_Next_VolCB (NPVOLCB, ULONG);
  44. VOID   NEAR Setup_Extended_Volumes (void);
  45. USHORT NEAR Read_Sector (NPVOLCB, ULONG);
  46. VOID   NEAR Init_Trace (void);
  47. VOID   NEAR GetInitParms (PRPINITIN);
  48. USHORT NEAR IsTraceNeeded(VOID);
  49. VOID   NEAR InitRMInfo(VOID);
  50.  
  51. VOID NEAR memset( PSZ d, USHORT Value, USHORT n );
  52.  
  53. typedef struct InfoSegGDT FAR *PInfoSegGDT;
  54.  
  55. /*--------------------------------------------------------------*/
  56. /* Init data allocated at the end of the data segment.          */
  57. /*--------------------------------------------------------------*/
  58.  
  59.  
  60. USHORT          InitData=0;
  61. UCHAR           InitTimeIORB[MAX_IORB_SIZE]={0};       /* Init time IORB   */
  62. RP_RWV          InitTimeRP={0};                        /* Init time RP     */
  63. PARTITIONTABLE  PartitionTables[MAX_FIXED_DISKS]={0};  /* Partition tables */
  64.  
  65. /* Perfview init time data */
  66. USHORT          PerfViewInstalled = 0;                               /*@V81576*/
  67.  
  68. #define NumTimerCounters  7                                          /*@V53225*/
  69.  
  70. UCHAR    GroupName[] = "DISK 01";
  71. UCHAR    str1[] = "ctRD";        /* Read Counter       */
  72. UCHAR    str2[] = "qlRD";        /* Read Queue Counter */            /*       */
  73. UCHAR    str3[] = "blRD";        /* Read Block Count   */
  74. UCHAR    str4[] = "ctWR";        /* Write Counter      */
  75. UCHAR    str5[] = "qlWR";         /* Write Queue Counters */         /*       */
  76. UCHAR    str6[] = "blWR";        /* Write Block Count  */
  77. UCHAR    str7[] = "tmBUSY";      /* Write Block Count  */            /*@V53225*/
  78.  
  79.  
  80. TBN      NameBlock[]  =
  81. {
  82.    {PVW_CT_CNT, sizeof(CNT), 0 , str1},
  83.    {PVW_CT_QLEN, sizeof(QLEN),0, str2},                              /*       */
  84.    {PVW_CT_CNT, sizeof(CNT), 0 , str3},
  85.    {PVW_CT_CNT, sizeof(CNT), 0 , str4},
  86.    {PVW_CT_QLEN, sizeof(QLEN), 0 , str5},                            /*       */
  87.    {PVW_CT_CNT, sizeof(CNT), 0 , str6},
  88.    {PVW_CT_TIMR, sizeof(TIMR), 0 , str7}                             /*       */
  89. };
  90.  
  91. TBH PerfViewTB = {
  92.    TBH_VER_2_0_0_0,             /* Version Number */
  93.    0,0,                         /* Block Instance ID, Block Group ID */
  94.    0,0,0,GroupName,             /* Text Block Group Name */
  95.    0,0,0,0,                     /* Text Block Instance Name */
  96.    0,                           /* Message File Name */
  97.    0,                           /* Help file name */
  98.    NumTimerCounters,            /* Number of Timers + Counters */
  99.    &NameBlock[0],               /* Pointer to array of Name Blocks */
  100. };
  101.  
  102. #define MAX_DT_ADAPTERS  8
  103. #define MAX_DT_UNITS     56
  104. #define MAX_DT_SIZE (sizeof(DEVICETABLE) + ((MAX_DT_ADAPTERS-1) * 2) +        \
  105.               (MAX_DT_ADAPTERS * (sizeof(ADAPTERINFO)-sizeof(UNITINFO))) +    \
  106.               (MAX_DT_UNITS * sizeof(UNITINFO))  )
  107.  
  108. UCHAR           ScratchBuffer2[MAX_DT_SIZE]={0};       /*Scratch buffer */
  109.  
  110. /*-----------------------------------------------------*/
  111. /* DriveInit  - Initialization for OS2DASD.DMD         */
  112. /*-----------------------------------------------------*/
  113. USHORT near DriveInit(pRP, pVolCB)
  114.  
  115. PRPINITIN  pRP;
  116. NPVOLCB    pVolCB;
  117. {
  118.   USHORT     rc, i, NumBPBArrayEntries, NumExtraVolCBs;
  119.   NPVOLCB    pVolCBx;
  120.   PRPINITOUT pRPO = (PRPINITOUT) pRP;   /* Output for Init RP           */
  121.   PVOID      pScratchBuffer;
  122.  
  123.   extern USHORT (near *Strat1Near[])();
  124.  
  125.   /* Initialize various variables */
  126.  
  127.   DDFlags |= DDF_INIT_TIME;            /* Turn off init time flag */
  128.  
  129.   Device_Help = pRP->DevHlpEP;         /* Save ptr to devhelp function   */
  130.  
  131.   pDataSeg = (PVOID) &pDataSeg;        /* Set up pointer to data segment */
  132.   OFFSETOF(pDataSeg) = 0;
  133.  
  134.   /* Get the init parms specified on the BASEDEV= command line */
  135.  
  136.   GetInitParms(pRP);
  137.  
  138.   /* Save away the physical and linear addresses of our data segment */
  139.  
  140.   rc = DevHelp_VirtToPhys(pDataSeg, (PULONG) &ppDataSeg);
  141.  
  142.   rc = DevHelp_VirtToLin((USHORT) (SELECTOROF(pDataSeg)),
  143.                          (ULONG) (OFFSETOF(pDataSeg)),
  144.                          (PLIN) &plDataSeg);  /* Save lin addr of data seg    */
  145.  
  146.   /* Save away the physical address of the scratch read buffer      */
  147.  
  148.   SELECTOROF(pScratchBuffer) = SELECTOROF(pDataSeg);
  149.   OFFSETOF(pScratchBuffer) = (USHORT) &ScratchBuffer[0];
  150.  
  151.   rc = DevHelp_VirtToPhys(pScratchBuffer, (PULONG) &ppScratchBuffer);
  152.  
  153.   RMCreateDriver(&RMDASDDesc, &hRMOS2DASD );
  154.  
  155.   /* Put init data at end of _DATA since it'll get discarded later     */
  156.  
  157.   PoolSize = INIT_POOL_SIZE;
  158.  
  159.   FreePoolSpace = INIT_POOL_SIZE;
  160.  
  161.   Build_UnitCBs();                      /* Build unit control blocks   */
  162.  
  163.  
  164.   if (NumUnitCBs == 0)                  /* Handle no_media case */
  165.   {
  166.      /* Setup the return parameters for the no media case */
  167.  
  168.      DDFlags |= DDF_NO_MEDIA;
  169.      pRPO->Unit = 2;                                                 /*@V63867*/
  170.  
  171.      pRPO->BPBArray = (PVOID) InitBPBArray;
  172.  
  173.      InitBPBArray[0] = &(BPB_144MB);
  174.      InitBPBArray[1] = &(BPB_144MB);
  175.  
  176.      pRPO->CodeEnd = (USHORT) DriveInit;
  177.      pRPO->DataEnd = (USHORT) CBPool;
  178.   }
  179.   else  /* Media exists which is the typical case */
  180.   {
  181.      Build_VolCBs();                    /* Build Volume control blocks */
  182.  
  183.      InitDCS_VCS();                     /* Initialize the DCS and VCS strucs */
  184.  
  185.      InitCBPool ();                     /* Initialize the Control Block pool */
  186.  
  187.      Init_Trace();                      /* Initialize tracing */
  188.  
  189.      /* Set up the return parameters for the INIT packet. */
  190.  
  191.      NumLogDrives = NumRemovableDisks + NumPartitions;
  192.      if (pVolCB_DriveA->Flags & vf_AmMult)
  193.         NumLogDrives++;                    /* Add the psuedo drive */
  194.      else if (NumRemovableDisks == 0)
  195.         NumLogDrives += 2;                 /* No floppy case */
  196.      else if (pVolCB_DriveA->PhysDriveNum == -1)
  197.         NumLogDrives += 2;                 /* Removable, but no A: or B: */
  198.  
  199.      pRP->Unit = (CHAR) NumLogDrives;      /* Return number of logical drives */
  200.  
  201.  
  202.      /* Setup the return BPB array */
  203.  
  204.      NumExtraVolCBs = NumRemovableDisks;
  205.  
  206.      if (NumRemovableDisks == 0)
  207.         NumExtraVolCBs++;
  208.  
  209.      NumBPBArrayEntries = NumLogDrives + NumExtraVolCBs;
  210.  
  211.      if (NumBPBArrayEntries > MAX_DRIVE_LETTERS)
  212.        NumBPBArrayEntries = MAX_DRIVE_LETTERS;
  213.  
  214.      pRPO->BPBArray = (PVOID) InitBPBArray;
  215.  
  216.      InitBPBArray[0] = &(pVolCB_DriveA->MediaBPB);
  217.      InitBPBArray[1] = &(pVolCB_DriveB->MediaBPB);
  218.  
  219.      pVolCBx = pVolCB_DriveC;
  220.      for (i = 2; i < NumLogDrives; i++, pVolCBx = pVolCBx->pNextVolCB)
  221.         InitBPBArray[i] = &(pVolCBx->MediaBPB);
  222.  
  223.      /* Return the end of the code and data segments */
  224.  
  225.      pRPO->DataEnd =  (USHORT) pNextFreeCB;
  226.  
  227.      pRPO->CodeEnd = (DDFlags & DDF_DISCARD_TRACE)   ? (USHORT) IsTraceNeeded /*@V81586*/
  228.                                                      : (USHORT) DriveInit;    /*@V81586*/
  229.   }
  230.  
  231.   InitRMInfo();
  232.  
  233.   /* Dont allow another INIT command to come in */
  234.  
  235.   Strat1Near[CMDInitBase] = CmdErr;   /* Patch strat1 table to disable inits */
  236.   DDFlags &= ~DDF_INIT_TIME;          /* Turn off init time flag */
  237.  
  238.   return(STDON);                      /* Done with init, so return */
  239.  
  240. }
  241.  
  242.  
  243. /********************** START OF SPECIFICATIONS *****************************
  244. *                                                                           *
  245. * SUBROUTINE NAME: Build_UnitCBs                                            *
  246. *                                                                           *
  247. * DESCRIPTIVE NAME: Build Unit Control Blocks  (UnitCBs)                    *
  248. *                                                                           *
  249. * FUNCTION:  This routine issues the GetAdapterDeviceTable command          *
  250. *            to each Adapter Device Driver and builds the unit control      *
  251. *            blocks from each Adapter Device Table returned.  Each unit     *
  252. *            control block (UnitCB) represents a physical device unit       *
  253. *            (i.e. drive numbers 0x80,0x81, etc.) which the adapter         *
  254. *            device driver manages.                                         *
  255. *                                                                           *
  256. * ENTRY POINT: Build_UnitCBs                                                *
  257. *                                                                           *
  258. * LINKAGE: Call Near                                                        *
  259. *                                                                           *
  260. * INPUT:                                                                    *
  261. *                                                                           *
  262. * EXIT-NORMAL: UnitCBs built for each physical unit.                        *
  263. *              NumUnitCBs = Number of UnitCBs built                         *
  264. *                                                                           *
  265. * EXIT-ERROR: None                                                          *
  266. *                                                                           *
  267. *********************** END OF SPECIFICATIONS *******************************/
  268.  
  269. void Build_UnitCBs()
  270.  
  271. {
  272.   USHORT                rc;
  273.   NPUNITCB              pUnitCB;         /* Pointer to current UnitCB    */
  274.   NPIORB_CONFIGURATION  pIORB;           /* ptr to IORB                  */
  275.   DEVICETABLE           *pDeviceTable;   /* ptr to device table          */
  276.   NPADAPTERINFO         pAdapterInfo;    /* near ptr to AdapterInfo      */
  277.   USHORT                i, j, k;         /* Index pointers               */
  278.   USHORT                FilterADDHandle; /* Filter Handle                */
  279.   struct DevClassTableStruc far *pDriverTable;  /*  ptr to registered ADD EPs*/
  280.   VOID (FAR * DriverEP) ();                  /* Driver entry point           */
  281.   VOID (FAR * DriverEPF)();             /* Filter Driver entry point */ /*@V736405*/
  282.  
  283.   (NPUNITCB)pNextFreeCB = FirstUnitCB;  /* Next free is first unit CB   */
  284.   UnitCB_Head = FirstUnitCB;            /* Init UnitCB head pointer     */
  285.   pUnitCB = UnitCB_Head;                /* Point to first UnitCB        */
  286.   NumUnitCBs = 0;                       /* Init UnitCB count            */
  287.  
  288.   /*--------------------------------------------------------------------*/
  289.   /* Get the adapter device tables for each adapter driver and create   */
  290.   /* the unit control blocks (UnitCBs) from the returned tables.        */
  291.   /*--------------------------------------------------------------------*/
  292.  
  293.   rc = DevHelp_GetDOSVar((USHORT) DHGETDOSV_DEVICECLASSTABLE, 1,
  294.                          (PPVOID) &pDriverTable);
  295.  
  296.   NumDrivers = pDriverTable->DCCount;
  297.  
  298.   pDeviceTable = (DEVICETABLE *) ScratchBuffer2;
  299.  
  300.   for (i = 0; i < NumDrivers; i++)
  301.   {
  302.      pIORB = (NPIORB_CONFIGURATION) InitTimeIORB;
  303.      pIORB->iorbh.Length = sizeof(IORB_CONFIGURATION);
  304.      pIORB->iorbh.CommandCode = IOCC_CONFIGURATION;
  305.      pIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
  306.      pIORB->iorbh.Status = 0;
  307.      pIORB->iorbh.ErrorCode = 0;                                     /*@V56638*/
  308.      pIORB->iorbh.RequestControl = IORB_ASYNC_POST;
  309.      pIORB->iorbh.NotifyAddress = &InitPost;
  310.      pIORB->pDeviceTable = (PVOID) pDeviceTable;
  311.      pIORB->DeviceTableLen = sizeof(ScratchBuffer2);
  312.  
  313.      OFFSETOF(DriverEP) =  pDriverTable->DCTableEntries[i].DCOffset;
  314.      SELECTOROF(DriverEP) = pDriverTable->DCTableEntries[i].DCSelector;
  315.  
  316.      f_ZeroCB((PBYTE)pDeviceTable, sizeof(ScratchBuffer2));
  317.  
  318.      (*DriverEP) ((PVOID)(pIORB));
  319.  
  320.      while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  321.      ;
  322.  
  323.      for (j = 0; j < pDeviceTable->TotalAdapters; j++)
  324.      {
  325.         pAdapterInfo =  pDeviceTable->pAdapter[j];
  326.  
  327.         for (k = 0; k < pAdapterInfo->AdapterUnits; k++)
  328.         {
  329.  
  330.            /* Only allocate DISK type devices which are not defective */
  331.            /* and which dont suppress DASD manager support.           */
  332.  
  333.            if ( (pAdapterInfo->UnitInfo[k].UnitType == UIB_TYPE_DISK) &&
  334.                 ! (pAdapterInfo->UnitInfo[k].UnitFlags &
  335.                         (UF_NODASD_SUPT | UF_DEFECTIVE)) )
  336.            {
  337.               /* Allocate the unit if it's not already allocated */
  338.               /* Wait until the request comes back from ADD.     */
  339.  
  340.               pIORB->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
  341.               pIORB->iorbh.CommandCode = IOCC_UNIT_CONTROL;
  342.               pIORB->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  343.               pIORB->iorbh.Status = 0;
  344.               pIORB->iorbh.ErrorCode = 0;                            /*@V56638*/
  345.               pIORB->iorbh.UnitHandle = pAdapterInfo->UnitInfo[k].UnitHandle;
  346.               pIORB->iorbh.RequestControl = IORB_ASYNC_POST;
  347.               pIORB->iorbh.NotifyAddress = &InitPost;
  348.               ((NPIORB_UNIT_CONTROL)pIORB)->Flags = 0;
  349.               ((NPIORB_UNIT_CONTROL)pIORB)->pUnitInfo = 0;
  350.               ((NPIORB_UNIT_CONTROL)pIORB)->UnitInfoLen = 0;
  351.                                                                     /*@V736405*/
  352.               FilterADDHandle = pAdapterInfo->UnitInfo[k].FilterADDHandle;
  353.                                                                     /*@V736405*/
  354.               if ( !FilterADDHandle )                               /*@V736405*/
  355.               {
  356.                  (*DriverEP) ((PVOID)(pIORB));
  357.               }                                                     /*@V736405*/
  358.               else                                                  /*@V736405*/
  359.               {                                                     /*@V736405*/
  360.                  OFFSETOF(DriverEPF) =                              /*@V736405*/
  361.                       pDriverTable->DCTableEntries[FilterADDHandle-1].DCOffset;
  362.                  SELECTOROF(DriverEPF) =                            /*@V736405*/
  363.                       pDriverTable->DCTableEntries[FilterADDHandle-1].DCSelector;
  364.                                                                     /*@V736405*/
  365.                  (*DriverEPF) ((PVOID)(pIORB));                     /*@V736405*/
  366.               }                                                     /*@V736405*/
  367.  
  368.               while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  369.               ;
  370.  
  371.               /* If allocation succeeded then add unit to unit tables */
  372.  
  373.               if ( !(pIORB->iorbh.Status & IORB_ERROR) )
  374.               {
  375.                  NumUnitCBs ++;                        /* update unit count */
  376.                  pUnitCB->UnitInfo = pAdapterInfo->UnitInfo[k];
  377.  
  378.                  /* Save the callable entry point of the adapter driver. If */
  379.                  /* the unit is being filtered, use the entry point of the  */
  380.                  /* filter driver.                                          */
  381.  
  382.                  if (FilterADDHandle == 0)
  383.                  {
  384.                      pUnitCB->AdapterDriverEP = DriverEP;
  385.                      pUnitCB->ADDHandle       = i+1;
  386.                  }
  387.                  else
  388.                  {                                                  /*@V736405*/
  389.                     pUnitCB->ADDHandle = FilterADDHandle;
  390.  
  391.                     OFFSETOF(pUnitCB->AdapterDriverEP)   = OFFSETOF(DriverEPF);
  392.                     SELECTOROF(pUnitCB->AdapterDriverEP) = SELECTOROF(DriverEPF);
  393.                  }
  394.  
  395.                  pUnitCB->AdapterNumber = NumAdapters + j;
  396.  
  397.                  pUnitCB->MaxHWSGList = pAdapterInfo->MaxHWSGList;
  398.  
  399.                  if (pAdapterInfo->AdapterFlags & AF_HW_SCATGAT)
  400.                     pUnitCB->Flags |= UCF_HW_SCATGAT;
  401.  
  402.                  if (pAdapterInfo->AdapterFlags & AF_16M)
  403.                     pUnitCB->Flags |= UCF_16M;
  404.  
  405.                  if (pAdapterInfo->AdapterFlags & AF_CHS_ADDRESSING)
  406.                     pUnitCB->Flags |= UCF_CHS_ADDRESSING;
  407.  
  408.                  pUnitCB->SortMethod  = DefaultSortMethod;              /*@V74404*/
  409.                  pUnitCB->QueueMethod = DefaultQueueMethod;             /*@V74404*/
  410.                  pUnitCB->QueueDepth  = pUnitCB->UnitInfo.QueuingCount; /*@V74404*/
  411.  
  412.                  if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  413.                  {
  414.                     pUnitCB->PhysDriveNum = NumRemovableDisks;
  415.                     NumRemovableDisks++;
  416.                     if ((pAdapterInfo->AdapterDevBus & 0x00FF)
  417.                                                        != AI_DEVBUS_FLOPPY)
  418.                        pUnitCB->Flags |= UCF_REMOVABLE_NON_FLOPPY;
  419.                  }
  420.                  else
  421.                  {
  422.                     pUnitCB->PhysDriveNum = NumFixedDisks + 0x80;
  423.                     NumFixedDisks++;
  424.                  }
  425.                  pUnitCB->pNextUnitCB = pUnitCB + 1;
  426.                  pUnitCB++;
  427.               }
  428.            }
  429.         }  /* end unit loop */
  430.      }  /* end adapter loop */
  431.      NumAdapters += pDeviceTable->TotalAdapters;
  432.   }  /* end driver loop */
  433.  
  434.   (NPUNITCB) pNextFreeCB = pUnitCB;     /* Update next free control blk ptr */
  435.   (pUnitCB-1)->pNextUnitCB = 0;
  436. }
  437.  
  438.  
  439. /********************** START OF SPECIFICATIONS *****************************
  440. *                                                                           *
  441. * SUBROUTINE NAME: Build_VolCBs                                             *
  442. *                                                                           *
  443. * DESCRIPTIVE NAME: Build Volume Control Blocks  (VolCBs)                   *
  444. *                                                                           *
  445. * FUNCTION:  This routine builds the physical and logical volume            *
  446. *            control blocks for each volume.                                *
  447. *                                                                           *
  448. * ENTRY POINT: Build_VolCBs                                                 *
  449. *                                                                           *
  450. * LINKAGE: Call Near                                                        *
  451. *                                                                           *
  452. * INPUT:                                                                    *
  453. *                                                                           *
  454. * EXIT-NORMAL: VolCBs built for each volume.                                *
  455. *              NumVolCBs = Number of VolCBs built                           *
  456. *                                                                           *
  457. * EXIT-ERROR: None                                                          *
  458. *                                                                           *
  459. *********************** END OF SPECIFICATIONS *******************************/
  460.  
  461. void Build_VolCBs()
  462.  
  463. {
  464.   NPVOLCB         pVolCB;
  465.   NPUNITCB        pUnitCB;
  466.   USHORT          iUnit;
  467.   USHORT          iVol;
  468.   NPIORB_GEOMETRY pIORB;                /* ptr to IORB                     */
  469.  
  470.   BOOL A_Found = FALSE;                 /* A: drive found                  */
  471.   BOOL B_Found = FALSE;                 /* B: drive found                  */
  472.   UCHAR PseudoB = NO;
  473.   USHORT ReChain = NO;
  474.  
  475.  
  476.   /*-----------------------------------------------*/
  477.   /* Create Volume Controls Blocks for units       */
  478.   /* managing A: and B:                            */
  479.   /*-----------------------------------------------*/
  480.  
  481.   /* The VolCB chain starts with Drive A: and Drive B:  */
  482.   /* and are placed right after the UnitCBs             */
  483.  
  484.   VolCB_Head = (NPVOLCB)pNextFreeCB;
  485.  
  486.   pVolCB_DriveA = VolCB_Head;
  487.   pVolCB_DriveA->LogDriveNum = 0;          /* LogDriveNum for A: is 0  */
  488.   pVolCB_DriveA->pNextVolCB = pVolCB_DriveA + 1;
  489.  
  490.   pVolCB_DriveB = VolCB_Head + 1;
  491.   pVolCB_DriveB->LogDriveNum = 1;       /* LogDriveNum for B: is 1  */
  492.   pVolCB_DriveB->pNextVolCB = pVolCB_DriveB + 1;
  493.  
  494.  
  495.   pUnitCB = UnitCB_Head;                /* Point back to head UnitCB       */
  496.   for (iUnit=0; iUnit < NumUnitCBs; iUnit++, pUnitCB++)
  497.   {
  498.      if (A_Found && B_Found)
  499.         break;
  500.  
  501.      if ((pUnitCB->UnitInfo.UnitFlags & UF_A_DRIVE) && !(A_Found))
  502.      {
  503.         A_Found = TRUE;                          /* Indicate A: found        */
  504.         pVolCB_DriveA->pUnitCB = pUnitCB;        /* Link VolCB to UnitCB     */
  505.         pVolCB_DriveA->PhysDriveNum = 0;         /* PhysDriveNum for A: is 0 */
  506.         pVolCB_DriveA->Flags |= vf_OwnPhysical;  /* Owns physical drive      */
  507.         pUnitCB->pCurrentVolCB = pVolCB_DriveA;
  508.  
  509.         if ((pUnitCB->UnitInfo.UnitFlags & UF_B_DRIVE) && !(B_Found))
  510.         {
  511.            B_Found = TRUE;                       /* Indicate B: found   */
  512.            PseudoB = YES;                        /* Indicate Pseudo B drive */
  513.         }
  514.      }
  515.      else if ((pUnitCB->UnitInfo.UnitFlags & UF_B_DRIVE) && !(B_Found))
  516.      {
  517.         B_Found = TRUE;                          /* Indicate B: found        */
  518.         pVolCB_DriveB->pUnitCB = pUnitCB;        /* Link VolCB to UnitCB     */
  519.         pVolCB_DriveB->PhysDriveNum = 1;         /* PhysDriveNum for B: is 1 */
  520.         pVolCB_DriveB->Flags |= vf_OwnPhysical;  /* Owns physical drive      */
  521.         pUnitCB->pCurrentVolCB = pVolCB_DriveB;
  522.      }
  523.   }
  524.  
  525.   /* If PseudoB drive found, or found A: but not B: */
  526.  
  527.   if ( (PseudoB == YES) || (A_Found && !B_Found) )
  528.   {
  529.      PseudoB = YES;                                                  /*@V50363*/
  530.      pVolCB_DriveA->Flags |= vf_AmMult;      /* Mult VolCBs mapped to unit  */
  531.      pVolCB_DriveB->Flags |= vf_AmMult;      /* Mult VolCBs mapped to unit */
  532.      pVolCB_DriveB->pUnitCB = pVolCB_DriveA->pUnitCB;
  533.      pVolCB_DriveB->PhysDriveNum = 0;
  534.   }
  535.  
  536.   /* If found B:, but not A: */
  537.  
  538.   else if (!A_Found && B_Found)
  539.   {
  540.      pVolCB_DriveA->PhysDriveNum = 0;
  541.      pVolCB_DriveA->pUnitCB = pVolCB_DriveB->pUnitCB;
  542.      pVolCB_DriveA->Flags |= vf_AmMult + vf_OwnPhysical;
  543.      pVolCB_DriveA->pUnitCB->pCurrentVolCB = pVolCB_DriveA;
  544.  
  545.      pVolCB_DriveB->PhysDriveNum = 0;
  546.      pVolCB_DriveB->Flags |= vf_AmMult;      /* Mult VolCBs mapped to unit */
  547.      pVolCB_DriveB->Flags & ~vf_OwnPhysical;
  548.   }
  549.  
  550.   /* If no A: or B:           */
  551.  
  552.   else if (!A_Found && !B_Found)
  553.   {
  554.      pVolCB_DriveA->PhysDriveNum = -1;
  555.      pVolCB_DriveA->LogDriveNum = -1;
  556.      pVolCB_DriveA->MediaBPB = BPB_144MB;
  557.  
  558.      pVolCB_DriveB->PhysDriveNum = -1;
  559.      pVolCB_DriveB->LogDriveNum = -1;
  560.      pVolCB_DriveB->MediaBPB = BPB_144MB;
  561.   }
  562.  
  563.  
  564.   NumVolCBs = 2;
  565.   pVolCB = VolCB_Head + 2;
  566.  
  567.   /*-----------------------------------------------*/
  568.   /* Create volume control blocks for removable    */
  569.   /* disk devices which were not assigned A: or B: */
  570.   /*-----------------------------------------------*/
  571.  
  572.  
  573.   for (iUnit=0, pUnitCB = UnitCB_Head; iUnit < NumUnitCBs; iUnit++, pUnitCB++)
  574.   {
  575.      if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE &&
  576.          pUnitCB->UnitInfo.UnitType == UIB_TYPE_DISK &&
  577.          !(pUnitCB->UnitInfo.UnitFlags & (UF_A_DRIVE | UF_B_DRIVE) ) )
  578.      {
  579.         pVolCB->pUnitCB = pUnitCB;
  580.         pVolCB->LogDriveNum = -1;
  581.         pVolCB->PhysDriveNum = pUnitCB->PhysDriveNum;
  582.         pVolCB->Flags |= vf_OwnPhysical;         /* Owns physical drive      */
  583.         pUnitCB->pCurrentVolCB = pVolCB;
  584.         pVolCB->pNextVolCB = pVolCB + 1;
  585.         pVolCB++;
  586.         NumVolCBs++;
  587.      }
  588.   }
  589.  
  590.   pLastLogVolCB = pVolCB-1;
  591.  
  592.   /*------------------------------------------------*/
  593.   /* Create volume control blocks for non-removable */
  594.   /* disk devices.                                  */
  595.   /*------------------------------------------------*/
  596.  
  597.   pVolCB_80 = pVolCB;
  598.   for (iUnit=0, pUnitCB = UnitCB_Head; iUnit < NumUnitCBs; iUnit++, pUnitCB++)
  599.   {
  600.      if ( !(pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) &&
  601.          pUnitCB->UnitInfo.UnitType == UIB_TYPE_DISK)
  602.      {
  603.         pVolCB->pUnitCB = pUnitCB;
  604.         pVolCB->LogDriveNum = pUnitCB->PhysDriveNum;  /* Assign Logical same */
  605.         pVolCB->PhysDriveNum = pUnitCB->PhysDriveNum;  /*  as physical       */
  606.         pVolCB->Flags |= vf_OwnPhysical;         /* Owns physical drive      */
  607.         pUnitCB->pCurrentVolCB = pVolCB;
  608.         pVolCB->pNextVolCB = pVolCB + 1;
  609.         pVolCB++;
  610.         NumVolCBs++;
  611.      }
  612.    }
  613.    (pVolCB-1)->pNextVolCB = (NPVOLCB) NULL;          /* Terminate VolCB chain */
  614.  
  615.  
  616.   /*------------------------------------------------*/
  617.   /* We now have all the physical VolCB's created.  */
  618.   /* Fill in the BPB and other various device       */
  619.   /* parameters in the VolCB.                       */
  620.   /*------------------------------------------------*/
  621.  
  622.   pIORB = (NPIORB_GEOMETRY) InitTimeIORB;
  623.  
  624.   for (iVol = 0, pVolCB = VolCB_Head; iVol < NumVolCBs; iVol++, pVolCB++)
  625.   {
  626.      if (pVolCB->Flags & vf_OwnPhysical)
  627.      {
  628.         pIORB->iorbh.Length = sizeof(IORB_GEOMETRY);
  629.         pIORB->iorbh.CommandCode = IOCC_GEOMETRY;
  630.         pIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_GEOMETRY;
  631.         pIORB->iorbh.UnitHandle = pVolCB->pUnitCB->UnitInfo.UnitHandle;
  632.         pIORB->iorbh.RequestControl = IORB_ASYNC_POST;
  633.         pIORB->iorbh.Status = 0;
  634.         pIORB->iorbh.ErrorCode = 0;                                  /*@V58430*/
  635.         pIORB->iorbh.NotifyAddress = &InitPost;
  636.         pIORB->pGeometry = (GEOMETRY *) ScratchBuffer2;
  637.         pIORB->GeometryLen = sizeof(struct _GEOMETRY);
  638.  
  639.         f_ZeroCB((PBYTE)pIORB->pGeometry, pIORB->GeometryLen);
  640.  
  641.         pUnitCB = pVolCB->pUnitCB;
  642.  
  643.         (*pUnitCB->AdapterDriverEP) ((PVOID) (pIORB));
  644.  
  645.         while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  646.         ;
  647.  
  648.         if (pIORB->iorbh.Status & IORB_ERROR)                        /*@V63867*/
  649.         {                                                            /*@V63867*/
  650.           f_ZeroCB((PBYTE)pIORB->pGeometry, sizeof(GEOMETRY) );      /*@V63867*/
  651.         }                                                            /*@V63867*/
  652.  
  653.         f_BPBFromGeom( pVolCB, &(pVolCB->RecBPB), pIORB->pGeometry); /*@V63867*/
  654.  
  655.         pVolCB->MediaBPB = pVolCB->RecBPB;     /* Copy Rec BPB to media BPB */
  656.      }
  657.   }
  658.  
  659.   /* Fill in the BPB for the Psuedo B: if there is one */
  660.  
  661.   if (PseudoB == YES)
  662.   {
  663.      pVolCB_DriveB->MediaBPB = pVolCB_DriveA->MediaBPB;
  664.      pVolCB_DriveB->RecBPB = pVolCB_DriveA->RecBPB;
  665.      pVolCB_DriveB->NumPhysCylinders = pVolCB_DriveA->NumPhysCylinders; /*@V59959*/
  666.   }
  667.  
  668.   (NPVOLCB)pNextFreeCB = pVolCB;
  669.  
  670.   if (NumFixedDisks > 0)
  671.      Setup_Partition_VolCBs();         /* Setup VolCBs for partitions       */
  672.  
  673.   /* Go back and fill in the logical drive number for those volumes         */
  674.   /* we assign at the end (i.e. removable drives which are not A: or B:     */
  675.   /* Also, rearrage the VolCB chain pointers to have these VolCBs           */
  676.   /* chained after the last fixed disk logical VolCB.                       */
  677.  
  678.   pVolCB = VolCB_Head;
  679.   ReChain = NO;
  680.   for (iVol = 0; iVol < NumVolCBs; iVol++, pVolCB = pVolCB->pNextVolCB)
  681.   {
  682.      if ( (pVolCB->LogDriveNum == -1) && (pVolCB->PhysDriveNum != -1) )
  683.      {
  684.         ReChain = YES;
  685.         pVolCB->LogDriveNum = NextLogDriveNum++;
  686.      }
  687.   }
  688.  
  689.   if (ReChain == YES)
  690.   {
  691.      pLastLogVolCB->pNextVolCB = pVolCB_DriveB->pNextVolCB;
  692.      pVolCB_DriveB->pNextVolCB = pVolCB_DriveC;
  693.      (pVolCB_80-1)->pNextVolCB = pVolCB_80;
  694.   }
  695.  
  696.  
  697.   /* Reserve 1 extra VolCB for each removable unit so drive aliasing */
  698.   /* via the DEVICE=EXTDSKDD command can be supported.               */
  699.  
  700.   if (NumRemovableDisks != 0)
  701.   {
  702.      pExtraVolCBs = (NPVOLCB) pNextFreeCB;
  703.      NumExtraVolCBs = NumRemovableDisks;
  704.      pNextFreeCB = pNextFreeCB + (NumRemovableDisks * sizeof(VOLCB));
  705.   }
  706.  
  707. }
  708.  
  709.  
  710. /********************** START OF SPECIFICATIONS *****************************
  711. *                                                                           *
  712. * SUBROUTINE NAME: Setup_Partition_VolCBs                                   *
  713. *                                                                           *
  714. * DESCRIPTIVE NAME: Installs a VolCB for each OS/2 partition found          *
  715. *                   on every fixed disks.                                   *
  716. *                                                                           *
  717. * FUNCTION:  This routine searches all fixed disks (80H - 86H) looking      *
  718. *            for a primary partition and extended volumes on each           *
  719. *            disk.                                                          *
  720. *                                                                           *
  721. *            A VolCB is installed for every primary partition, then VolCBs  *   *
  722. *            are installed for all extended volumes. If drive 80H did       *
  723. *            not have a primary partition, it will not be searched for      *
  724. *            extended volumes.  All following fixed drives will always      *
  725. *            be searched for extended volumes whether it had a primary      *
  726. *            partition or not.                                              *
  727. *                                                                           *
  728. * NOTES: The VolCBs for all physical fixed drives must be set up            *
  729. *        and NumFixedDisks must be set to the number of fixed disks         *
  730. *        prior to calling this routine.                                     *
  731. *                                                                           *
  732. * ENTRY POINT: Setup_Partition_VolCBs                                       *
  733. *                                                                           *
  734. * LINKAGE: Call Near                                                        *
  735. *                                                                           *
  736. * INPUT: None                                                               *
  737. *                                                                           *
  738. * EXIT-NORMAL: VolCBs installed for all partitions found                    *
  739. *                                                                           *
  740. * EXIT-ERROR: None                                                          *
  741. *                                                                           *
  742. * EFFECTS: Modifies NumPartitions                                           *
  743. *                                                                           *
  744. *********************** END OF SPECIFICATIONS *******************************/
  745.  
  746.  
  747. void near Setup_Partition_VolCBs()
  748.  
  749. {
  750.    NPVOLCB pPhysVolCB, pVolCB;
  751.    ULONG   NumSectors;
  752.    USHORT  iDisk, i;
  753.    MBR     near *pMBR = (MBR near *) ScratchBuffer; /* Ptr to buffer for MBR */
  754.    NPVOLCB pLogVolCB = (NPVOLCB) pNextFreeCB;
  755.  
  756.    /*-----------------------------------------------*/
  757.    /*  Allocate VolCBs for all Primary Partitions   */
  758.    /*-----------------------------------------------*/
  759.  
  760.    NextLogDriveNum = 2;
  761.    pVolCB_DriveC = pLogVolCB;
  762.  
  763.    for (iDisk=0,pPhysVolCB=pVolCB_80; iDisk<NumFixedDisks; iDisk++,pPhysVolCB++)
  764.    {
  765.  
  766.       /*** added by WKP - start */
  767.       NumSectors = pPhysVolCB->MediaBPB.NumHeads *
  768.                    pPhysVolCB->MediaBPB.SectorsPerTrack *
  769.                    pPhysVolCB->NumPhysCylinders;
  770.  
  771.       if (NumSectors > 0xFFFF)
  772.       {
  773.          pPhysVolCB->MediaBPB.BigTotalSectors = NumSectors;
  774.          pPhysVolCB->MediaBPB.TotalSectors = 0;
  775.          pPhysVolCB->RecBPB.BigTotalSectors = NumSectors;
  776.          pPhysVolCB->RecBPB.TotalSectors = 0;
  777.       }
  778.       else
  779.       {
  780.          pPhysVolCB->MediaBPB.TotalSectors = (USHORT)NumSectors;
  781.          pPhysVolCB->RecBPB.TotalSectors = (USHORT)NumSectors;
  782.       }
  783.       /*** added by WKP -end */
  784.  
  785.       /* Read the Master Boot Record (MBR) and copy the partition table */
  786.       /* into a temporary buffer for later use.                         */
  787.  
  788.       if (Read_Sector(pPhysVolCB,0L) == ERROR) /* Read MBR & check for error*/
  789.           PartitionTables[iDisk].Bad_MBR=1;                          /*@V88662*/
  790.       else
  791.       {
  792.          for (i = 0; i < 4; i++)
  793.             PartitionTables[iDisk].PartitionTable[i]
  794.                                              = pMBR->PartitionTable[i];
  795.          if (Build_Next_VolCB(pPhysVolCB,0L) == ERROR)
  796.             PartitionTables[iDisk].No_PrimPart=1;                    /*@V88662*/
  797.       }
  798.    }
  799.    /*------------------------------------------------*/
  800.    /*  Allocate VolCBs for all Extended Partitions   */
  801.    /*------------------------------------------------*/
  802.  
  803.    Setup_Extended_Volumes();
  804.  
  805.    NumPartitions = NumPartitions - NumFTPartitions;
  806. }
  807.  
  808. /*--------------------------------------------------------------------------
  809. ;
  810. ;** BuildNextVolCB - Build a VolCB for the next logical drive
  811. ;
  812. ;   This routine attempts to build a VolCB for a logical
  813. ;   fixed disk partition.  It is passed a pointer to the
  814. ;   physical VolCB (80H - 86H) of the disk containing the
  815. ;   partition and the offset in sectors of that
  816. ;   partition sector from the begining of the disk.
  817. ;
  818. ;   Process_Partition is then called to validate the
  819. ;   partition sector and see if there is a DOS partition.
  820. ;   If one is found, this VolCB is added to the chain and
  821. ;   initialized. The DOS boot sector for the partition
  822. ;   is then read in and Process_Boot is called to examine
  823. ;   it and build the BPB in the VolCB.
  824. ;
  825. ;   If there was no valid DOS partition, the VolCB will
  826. ;   remain available.
  827. ;
  828. ;   USHORT Build_Next_VolCB (NPVOLCB pPhysVolCB, ULONG PartitionOffset)
  829. ;
  830. ;   ENTRY:    pPhysVolCB       - Pointer to VolCB for Physical drive
  831. ;             PartitionOffset  - Partition sector offset
  832. ;
  833. ;   RETURN:   USHORT           - Result Code (NO_ERROR if valid partition)
  834. ;
  835. --------------------------------------------------------------------------*/
  836.  
  837. USHORT Build_Next_VolCB(pPhysVolCB,PartitionOffset)
  838.  
  839. NPVOLCB pPhysVolCB;
  840. ULONG   PartitionOffset;
  841. {
  842.    ULONG  SectorsInPartition, rba, VolBootRBA, CylinderSize;
  843.    ULONG  SectorsInBootRec;                                          /*@V88662*/
  844.  
  845.    NPVOLCB pLogVolCB = (NPVOLCB) pNextFreeCB;
  846.    USHORT rc = ERROR;
  847.  
  848.    if (NumPartitions < MAX_PARTITIONS)
  849.    {
  850.       pLogVolCB->PartitionOffset = PartitionOffset;
  851.       pLogVolCB->MediaBPB.SectorsPerTrack=pPhysVolCB->MediaBPB.SectorsPerTrack;
  852.       pLogVolCB->MediaBPB.NumHeads = pPhysVolCB->MediaBPB.NumHeads;
  853.  
  854.       /* If a valid partition is found, initialize the rest of the  */
  855.       /* Logical Volume Control Block.                              */
  856.  
  857.       if (Process_Partition(pLogVolCB, (PULONG) &VolBootRBA,
  858.                            (PULONG) &SectorsInBootRec) == NO_ERROR)  /*@V88662*/
  859.       {
  860.  
  861. /* defer CylinderSize calculation until media BPB is complete */     /*@V88662*/
  862.          /* Link new VolCB after last logical VolCB  */
  863.          /*  and before physical Drive 80 VolCB      */
  864.  
  865.          pLogVolCB->pNextVolCB = pVolCB_80;
  866.          pLastLogVolCB->pNextVolCB = pLogVolCB;
  867.          pLastLogVolCB = pLogVolCB;
  868.  
  869.          /* Copy over applicable fields from the Physical VolCB */
  870.  
  871.          pLogVolCB->pUnitCB = pPhysVolCB->pUnitCB;
  872.          pLogVolCB->pVolChar = pPhysVolCB->pVolChar;
  873.  
  874.          if (pLogVolCB->Flags & vf_FTPartition)
  875.            pLogVolCB->LogDriveNum = MAX_DRIVE_LETTERS + NumFTPartitions;
  876.          else
  877.            pLogVolCB->LogDriveNum = NextLogDriveNum++;
  878.  
  879.          pLogVolCB->PhysDriveNum = pPhysVolCB->PhysDriveNum;
  880.          pLogVolCB->NumPhysCylinders = pPhysVolCB->NumPhysCylinders;
  881.  
  882.          /* Setup default BPB fields for FORMAT */
  883.  
  884.          pLogVolCB->MediaBPB.MediaType = MEDIA_FIXED_DISK;
  885.          pLogVolCB->MediaBPB.BytesPerSector = 512;
  886.          pLogVolCB->MediaBPB.ReservedSectors = 1;
  887.          pLogVolCB->MediaBPB.NumFATs = 2;
  888.  
  889.          pLogVolCB->RecBPB.MediaType = MEDIA_FIXED_DISK;
  890.          pLogVolCB->RecBPB.BytesPerSector = 512;
  891.          pLogVolCB->RecBPB.ReservedSectors = 1;
  892.          pLogVolCB->RecBPB.NumFATs = 2;
  893.  
  894.          /* Read the DOS boot record into the ScratchBuffer */
  895.  
  896.          rba = pLogVolCB->PartitionOffset + pLogVolCB->MediaBPB.HiddenSectors;
  897.          rc  = Read_Sector (pPhysVolCB, rba);  /* Read DOS boot sector */
  898.          rc |= Is_BPB_Boot(pLogVolCB,(VOID _far *)&ScratchBuffer);    /*@V88662*//*@V64818*/
  899.          if (!rc)                       /* Is boot sector valid ?      */
  900.          {
  901.             /* copy boot bpb to media bpb */
  902.             BootBPB_To_MediaBPB (pLogVolCB, (DOSBOOTREC FAR *) &ScratchBuffer);
  903.          }
  904.  
  905.          /* Call Process_Boot to examine the boot sector and build the BPB */
  906.  
  907.          if (pLogVolCB->MediaBPB.TotalSectors != 0)
  908.             SectorsInPartition = pLogVolCB->MediaBPB.TotalSectors;
  909.          else
  910.             SectorsInPartition = pLogVolCB->MediaBPB.BigTotalSectors;
  911.  
  912.          CylinderSize = pLogVolCB->MediaBPB.SectorsPerTrack *        /*@V88662*/
  913.                         pLogVolCB->MediaBPB.NumHeads;                /*@V88662*/
  914.                                                                      /*@V88662*/
  915.          pLogVolCB->NumLogCylinders =                                /*@V89787*/
  916.                       (VolBootRBA + SectorsInBootRec)/CylinderSize;  /*@V89787*/                                               /*@V88662*/
  917.                                                                      /*@V88662*/
  918.          pLogVolCB->BootRecCyl =                                     /*@V89787*/
  919.                       VolBootRBA/CylinderSize;                       /*@V89787*/                                               /*@V88662*/
  920.                                                                      /*@V88662*/
  921.          Process_Boot (pLogVolCB, SectorsInPartition);
  922.  
  923.          NumPartitions++;
  924.          pLogVolCB++;
  925.          NumVolCBs++;
  926.          (NPVOLCB) pNextFreeCB = pLogVolCB;
  927.          rc = NO_ERROR;
  928.       }
  929.    }
  930.    return(rc);
  931. }
  932.  
  933. /*********************** Start of Specifications **********************
  934. *                                                                     *
  935. * Subroutine Name: Setup_Extended_Volumes                             *
  936. *                                                                     *
  937. * Function: Sets up the VolCB entries for all extended volumes        *
  938. *           found on a given fixed disk.                              *
  939. *                                                                     *
  940. * Entry Point: Setup_Extended_Volumes                                 *
  941. *                                                                     *
  942. * Linkage:  CALL near                                                 *
  943. *                                                                     *
  944. * Input: Physical BDS,                                                *
  945. *        ScratchBuffer containing Master Boot Record                  *
  946. *                                                                     *
  947. * Exit-Normal:                                                        *
  948. *                                                                     *
  949. * Exit-Error:                                                         *
  950. *                                                                     *
  951. ************************* End of Specifications ***********************/
  952.  
  953. void Setup_Extended_Volumes ()
  954.  
  955. {
  956.    ULONG   rba, Nextrba, MBRExtRBA;
  957.    MBR     *pMBR;
  958.    NPVOLCB pPhysVolCB;
  959.    USHORT  i, j, found;
  960.    PARTITIONENTRY *pPartitionEntry;
  961.  
  962.    pMBR = (MBR *) ScratchBuffer;
  963.    pPhysVolCB = pVolCB_80;
  964.  
  965.  
  966.    /* Search all disks for extended partitions, and setup a VolCB */
  967.    /* for each extended partition found.                          */
  968.  
  969.    for (i = 0; i < NumFixedDisks; i++, pPhysVolCB++)
  970.    {
  971.       if (PartitionTables[i].Bad_MBR == 0)
  972.       {
  973.          found = FALSE;
  974.          for  (j = 0; j < 4 && found == FALSE; j++)
  975.          {
  976.            pPartitionEntry = &(PartitionTables[i].PartitionTable[j]);
  977.            if (pPartitionEntry->SysIndicator == PARTITION_EBR)
  978.            {
  979.               rba = pPartitionEntry->RelativeSectors;
  980.               MBRExtRBA = rba;
  981.               found = TRUE;
  982.            }
  983.          }
  984.  
  985.          /* If the Master Boot Record contained an Extended Partition Type, */
  986.          /* then read in the Extended Boot Record                           */
  987.  
  988.          while (found == TRUE)
  989.          {
  990.             found = FALSE;
  991.             if (Read_Sector(pPhysVolCB, rba) == NO_ERROR)
  992.             {
  993.                for  (j = 0; j < 4 && found == FALSE; j++)
  994.                {
  995.                   pPartitionEntry = &(pMBR->PartitionTable[j]);
  996.                   if (pPartitionEntry->SysIndicator == PARTITION_EBR)
  997.                   {
  998.                      Nextrba = pPartitionEntry->RelativeSectors + MBRExtRBA;
  999.                      found = TRUE;
  1000.                   }
  1001.                }
  1002.                Build_Next_VolCB(pPhysVolCB, rba);
  1003.                rba = Nextrba;
  1004.             }
  1005.          }
  1006.       }
  1007.    }
  1008. }
  1009.  
  1010. /*---------------------------------------------------------------
  1011. ;
  1012. ;** Read_Sector - performs disk reads during initialization
  1013. ;
  1014. ;   Reads a sector from a fixed disk into ScratchBuffer.
  1015. ;   This routine sets up a hard coded read request packet
  1016. ;   and calls the Adapter Driver to perform the read.
  1017. ;
  1018. ;   USHORT Read_Sector (NPVOLCB pPhysVolCB, ULONG rba)
  1019. ;
  1020. ;   ENTRY:    pPhysVolCB       - Physical VolCB of disk to read
  1021. ;             rba              - RBA of sector to read
  1022. ;
  1023. ;   RETURN:   USHORT           - Result Code (NO_ERROR if successful)
  1024. ;
  1025. ;   EFFECTS:  Reads a sector into global variable ScratchBuffer.
  1026. ;
  1027. ;   NOTES:    This routine is DISCARDED after init time.
  1028. ;--------------------------------------------------------------*/
  1029.  
  1030. USHORT  Read_Sector(pPhysVolCB, rba)
  1031.  
  1032. NPVOLCB  pPhysVolCB;
  1033. ULONG    rba;
  1034.  
  1035. {
  1036.    PRP_RWV  pRP;
  1037.    NPIORB   pIORB;
  1038.    NPUNITCB pUnitCB;
  1039.    USHORT   rc;
  1040.  
  1041.  
  1042.    /* Set up the request packet for the read */
  1043.  
  1044.    pRP = &InitTimeRP;
  1045.    pRP->rph.Unit = pPhysVolCB->PhysDriveNum;
  1046.    pRP->rph.Cmd = CMDINPUT;
  1047.    pRP->rph.Status = 0;
  1048.    pRP->MediaDescr = MEDIA_FIXED_DISK;
  1049.    pRP->XferAddr = ppScratchBuffer;      /* Point to scratch buffer */
  1050.    pRP->NumSectors = 1;                  /* Read 1 sector */
  1051.    pRP->rba = rba;                       /* Store rba */
  1052.    pRP->sfn = 512;                       /* Use sfn field for SectorSize */
  1053.  
  1054.    pUnitCB = pPhysVolCB->pUnitCB;
  1055.  
  1056.    pIORB = (NPIORB) InitTimeIORB;
  1057.    f_ZeroCB((PBYTE)pIORB, MAX_IORB_SIZE);
  1058.  
  1059.    SetupIORB(pUnitCB, (PBYTE) pRP, pIORB);
  1060.  
  1061.    (pUnitCB->AdapterDriverEP) ((PVOID) pIORB);
  1062.  
  1063.    DISABLE;
  1064.    while ( !(pRP->rph.Status & STDON) )    /* Loop until I/O done   */
  1065.    {
  1066.       DevHelp_ProcBlock ((ULONG)pRP, -1L, 1);  /* Block: No timeout,non-interruptible*/
  1067.       DISABLE;                          /* Block does an enable  */
  1068.    }
  1069.    ENABLE;
  1070.  
  1071.    if (pRP->rph.Status & STERR)          /* Check for error */
  1072.       rc = ERROR;
  1073.    else
  1074.       rc = NO_ERROR;
  1075.  
  1076.    return(rc);
  1077. }
  1078.  
  1079. /*--------------------------------------------------------------------------
  1080. ;
  1081. ;** InitDCS_VCS
  1082. ;
  1083. ;   Initialize the DCS and VCS control blocks
  1084. ;
  1085. ;   This function will initialize the statically allocated
  1086. ;   DriverCapabilities Structure (DCS). It will also dynamically
  1087. ;   allocate one Volume Characteristics Structure (VCS) for each unit
  1088. ;   and initialize it.
  1089. ;
  1090. ;   VOID InitDCS_VCS ()
  1091. ;
  1092. ;   ENTRY:
  1093. ;
  1094. ;   RETURN:   VOID
  1095. ;---------------------------------------------------------------------------*/
  1096.  
  1097. VOID InitDCS_VCS()
  1098.  
  1099. {
  1100.    VolChars *pVCS;
  1101.    NPUNITCB pUnitCB;
  1102.    USHORT   i;
  1103.    NPVOLCB  pVolCB;
  1104.  
  1105.    /* Initialize the Driver Capabilites Structure */
  1106.  
  1107.    DriverCapabilities.VerMajor = 1;
  1108.    DriverCapabilities.VerMinor = 0;
  1109.    DriverCapabilities.Capabilities = GDC_DD_Mirror   | GDC_DD_Duplex |
  1110.                                      GDC_DD_No_Block | GDC_DD_16M;
  1111.    DriverCapabilities.Strategy2   = (PVOID) DMStrat2;
  1112.    DriverCapabilities.SetFSDInfo  = (PVOID) DD_SetFSDInfo;
  1113.    DriverCapabilities.ChgPriority = (PVOID) DD_ChgPriority_asm;
  1114.    DriverCapabilities.SetRestPos  = 0;
  1115.    DriverCapabilities.GetBoundary = 0;
  1116.  
  1117.  
  1118.    /* Allocate and initialize a VCS for each volume */
  1119.  
  1120.    pVCS = (VolChars *) pNextFreeCB;
  1121.    pVolCB = pVolCB_DriveA;
  1122.  
  1123.    for (i = 0; i < NumVolCBs; i++)
  1124.    {
  1125.       pVolCB->pVolChar = pVCS;
  1126.  
  1127.       pVCS->VolDescriptor = 0;
  1128.       pVCS->AvgSeekTime = -1;
  1129.       pVCS->AvgLatency =  -1;
  1130.       pVCS->TrackMinBlocks = pVolCB->RecBPB.SectorsPerTrack;
  1131.       pVCS->TrackMaxBlocks = pVolCB->RecBPB.SectorsPerTrack;
  1132.       pVCS->HeadsPerCylinder = pVolCB->RecBPB.NumHeads;
  1133.       pVCS->VolCylinderCount = pVolCB->NumLogCylinders;
  1134.  
  1135.       if (pVolCB->pUnitCB != 0)
  1136.       {
  1137.          pUnitCB = pVolCB->pUnitCB;
  1138.  
  1139.          pVCS->VolMedianBlock = pUnitCB->LastRBA / 2;
  1140.          pVCS->MaxSGList = pUnitCB->MaxHWSGList;
  1141.          if (pUnitCB->MaxHWSGList == 0)
  1142.             pVCS->MaxSGList = -1;
  1143.  
  1144.          if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  1145.             pVCS->VolDescriptor |= VC_REMOVABLE_MEDIA;
  1146.  
  1147.          if (pUnitCB->UnitInfo.UnitFlags & UF_PREFETCH)
  1148.             pVCS->VolDescriptor |= VC_PREFETCH;
  1149.  
  1150.          if (pUnitCB->Flags & UCF_HW_SCATGAT)
  1151.             pVCS->VolDescriptor |= VC_SCB;
  1152.  
  1153.          if (pUnitCB->UnitInfo.UnitType == UIB_TYPE_CDROM)
  1154.             pVCS->VolDescriptor |= VC_READ_ONLY;
  1155.       }
  1156.       pVCS++;
  1157.       pVolCB = pVolCB->pNextVolCB;
  1158.    }
  1159.    pNextFreeCB = (NPBYTE) pVCS;
  1160. }
  1161.  
  1162.  
  1163. /* Dummy notification callout for ADDs during init processing */
  1164.  
  1165. VOID FAR InitPost(pIORB)
  1166.  
  1167. PIORB pIORB;
  1168. {
  1169.  
  1170. }
  1171. /*--------------------------------------------------------------------------
  1172. ;
  1173. ;** GetInitParms - Get init parms from BASEDEV command line
  1174. ;
  1175. ;   VOID GetInitParms (PRPINITIN pRP);
  1176. ;
  1177. ;   ENTRY:    pRP              - Pointer to init request packet
  1178. ;
  1179. ;   RETURN:   VOID
  1180. ;
  1181. ;   EFFECTS:  Turns on Queueing flags in global DDFlags.
  1182. ;
  1183. ;---------------------------------------------------------------------------*/
  1184. VOID GetInitParms (pRP)
  1185.  
  1186. PRPINITIN pRP;
  1187.  
  1188. {
  1189.    PSZ    pCmdString;
  1190.    USHORT i;
  1191.  
  1192.    pCmdString = pRP->InitArgs;
  1193.    OFFSETOF(pCmdString) = ((PDDD_PARM_LIST)pRP->InitArgs)->cmd_line_args;
  1194.  
  1195.    DefaultSortMethod  = SORT_METHOD_ELEVATOR;                        /*@V74404*/
  1196.    DefaultQueueMethod = QUEUE_METHOD_PRIORITY;                       /*@V74404*/
  1197.  
  1198.    for (i = 0; *pCmdString != 0 && i < 40; i++, pCmdString++)
  1199.    {
  1200.       if (*pCmdString == '/')
  1201.       {
  1202.          if ( ( *(pCmdString+1) == 'Q' || *(pCmdString+1) == 'q' ) &&
  1203.               ( *(pCmdString+2) == 'F' || *(pCmdString+2) == 'f' ) )
  1204.          {
  1205.             if ( *(pCmdString + 3) == ':' )
  1206.             {
  1207.                switch ( *(pCmdString + 4) )
  1208.                {
  1209.                   case '1':
  1210.                       DefaultSortMethod  = SORT_METHOD_FIFO;         /*@V74404*/
  1211.                       break;
  1212.  
  1213.                   case '2':
  1214.                       DefaultQueueMethod = QUEUE_METHOD_NOPRIORITY;  /*@V74404*/
  1215.                       break;
  1216.  
  1217.                   case '3':
  1218.                       DefaultSortMethod  = SORT_METHOD_FIFO;         /*@V74404*/
  1219.                       DefaultQueueMethod = QUEUE_METHOD_NOPRIORITY;  /*@V74404*/
  1220.                       break;
  1221.                }
  1222.             }
  1223.          }
  1224.          else
  1225.          {
  1226.             if ( ( *(pCmdString+1) == 'T' || *(pCmdString+1) == 't' ) &&
  1227.                  ( *(pCmdString+2) == 'R' || *(pCmdString+2) == 'r' ) )
  1228.  
  1229.             TraceFlags |= TF_INTERNAL;
  1230.          }
  1231.       }
  1232.    }
  1233. }
  1234.  
  1235. /*--------------------------------------------------------------------------
  1236. ;
  1237. ;** Init_Trace -  Initialize RAS, DEKKO, PERFVIEW and Internal tracing
  1238. ;
  1239. ;   VOID Init_Trace ()
  1240. ;
  1241. ;   ENTRY:
  1242. ;
  1243. ;   RETURN:   VOID
  1244. ;---------------------------------------------------------------------------*/
  1245. VOID Init_Trace()
  1246. {
  1247.  
  1248.    PPVOID   ppSysInfoSeg;
  1249.    NPUNITCB pUnitCB;
  1250.    USHORT   i;
  1251.  
  1252.    /* Get pointer to RAS Major Event Code Table */
  1253.  
  1254.    DevHelp_GetDOSVar(DHGETDOSV_SYSINFOSEG, 0, (PPVOID) &ppSysInfoSeg);
  1255.  
  1256.    SELECTOROF(pSysInfoSeg) = (USHORT) *ppSysInfoSeg;
  1257.    OFFSETOF(pSysInfoSeg) = 0;
  1258.  
  1259.    pSIS_mec_table = ((PInfoSegGDT)pSysInfoSeg)->SIS_mec_table;
  1260.  
  1261.  
  1262.    /* Register PerfView Data and Text Blocks for each Non-Removable */
  1263.    /* physical unit.                                                */
  1264.  
  1265.    PerfViewInstalled = 1;                                            /*@V81576*/
  1266.  
  1267.    pUnitCB = UnitCB_Head;
  1268.    for (i = 0; i < NumUnitCBs; i++, pUnitCB++)
  1269.    {
  1270.       if ( !(pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE) )
  1271.       {
  1272.          pUnitCB->PerfViewDB.pfdbh.dbh_ulTotLen = sizeof(PVDB);
  1273.          pUnitCB->PerfViewDB.pfdbh.dbh_flFlags = RPC_FL_16BIT | RPC_FL_DD;
  1274.  
  1275.          PerfViewTB.tbh_bidID.bid_usInstance = 0;
  1276.          PerfViewTB.tbh_bidID.bid_usGroup = 0;
  1277.  
  1278.          if ( DevHelp_RegisterPerfCtrs( (NPBYTE)&pUnitCB->PerfViewDB,        /*@V81576*/
  1279.                                         (NPBYTE)&PerfViewTB, RPC_FL_16BIT ) )/*@V81576*/
  1280.          {                                                            /*@V81576*/
  1281.            PerfViewInstalled = 0;                                     /*@V81576*/
  1282.            break;                                                     /*@V81576*/
  1283.          }                                                            /*@V81576*/
  1284.  
  1285.          if (GroupName[6] == '9')
  1286.          {
  1287.             GroupName[6]='0';
  1288.             GroupName[5]++;
  1289.          }
  1290.          else
  1291.             GroupName[6]++;
  1292.       }
  1293.    }
  1294.  
  1295.    /* If internal tracing enabled, then allocate trace buffer  */
  1296.    /* Note: Always will be enough since init data is > 1 K.    */
  1297.  
  1298.    if ( IsTraceNeeded() )                                            /*@V81576*/
  1299.    {                                                                 /*@V81576*/
  1300.       pDMTraceBuf  = pNextFreeCB;
  1301.       pNextFreeCB += TRACEBUF_SIZE;
  1302.       pDMTraceHead = pDMTraceBuf;
  1303.       pDMTraceEnd  =  pDMTraceBuf + TRACEBUF_SIZE;
  1304.    }                                                                 /*@V81576*/
  1305.    else                                                              /*@V81576*/
  1306.    {                                                                 /*@V81576*/
  1307.      DDFlags |= DDF_DISCARD_TRACE;                                   /*@V81576*/
  1308.    }                                                                 /*@V81576*/
  1309. }
  1310.  
  1311.  
  1312. VOID NEAR InitRMInfo()
  1313. {
  1314.   NPVOLCB       pVolCB;
  1315.   NPUNITCB      pUnitCB;
  1316.  
  1317.   HDEVICE       hRMDevice;
  1318.   HLDEV         hRMLDev;
  1319.   HSYSNAME      hRMSysName;
  1320.  
  1321.   LDEVSTRUCT    RMLDevStr;
  1322.   SYSNAMESTRUCT RMSysNameStr;
  1323.  
  1324.   ADJUNCT       RMAdjunct;
  1325.  
  1326.   PSZ           s;
  1327.  
  1328.   USHORT        cRemove = 0;
  1329.   USHORT        cFixed  = 0;
  1330.   USHORT        cDskt   = 0;
  1331.  
  1332.   USHORT        UnitFlags;
  1333.   USHORT        rc;
  1334.  
  1335.   memset( (PSZ) &RMLDevStr, 0, sizeof(LDEVSTRUCT) );
  1336.  
  1337.   RMLDevStr.LDevClass        = LDEV_CLASS_DASD;
  1338.   RMLDevStr.pAdjunctList     = &RMAdjunct;
  1339.   RMAdjunct.AdjType          = ADJ_DEVICE_NUMBER;
  1340.   RMAdjunct.AdjLength        = sizeof(ADJUNCT);
  1341.   RMAdjunct.pNextAdj         = NULL;
  1342.  
  1343.   pUnitCB = UnitCB_Head;
  1344.   while ( pUnitCB )
  1345.   {
  1346.     UnitFlags = pUnitCB->UnitInfo.UnitFlags;
  1347.  
  1348.     if ( UnitFlags & (UF_A_DRIVE | UF_B_DRIVE) )
  1349.     {
  1350.       RMLDevStr.LDevDescriptName = RMDskt_Txt;
  1351.       RMAdjunct.Device_Number = cDskt;
  1352.     }
  1353.     else if ( UnitFlags & UF_REMOVABLE )
  1354.     {
  1355.       RMLDevStr.LDevDescriptName = RMRemovable_Txt;
  1356.       RMAdjunct.Device_Number = cRemove++;
  1357.     }
  1358.     else
  1359.     {
  1360.       RMLDevStr.LDevDescriptName = RMFixed_Txt;
  1361.       RMAdjunct.Device_Number = cFixed++;
  1362.     }
  1363.  
  1364.     rc = RMADDToHDEVICE( (PHDEVICE) &hRMDevice,
  1365.                          (USHORT)   pUnitCB->ADDHandle,
  1366.                          (USHORT)   pUnitCB->UnitInfo.UnitHandle );
  1367.  
  1368.     if ( !rc && (hRMDevice != -1L) )
  1369.     {
  1370.       if ( !(rc = RMCreateLDev( (HDRIVER)     hRMOS2DASD,
  1371.                                 (PHLDEV)      &hRMLDev,
  1372.                                 (HDEVICE)     hRMDevice,
  1373.                                 (PLDEVSTRUCT) &RMLDevStr  )) )
  1374.       {
  1375.         if ( hRMLDev != -1L )
  1376.         {
  1377.           pUnitCB->hRMLDev = hRMLDev;
  1378.         }
  1379.       }
  1380.     }
  1381.  
  1382.     pUnitCB = pUnitCB->pNextUnitCB;
  1383.   }
  1384.  
  1385.   pVolCB = VolCB_Head;
  1386.  
  1387.   memset( (PSZ) &RMSysNameStr, 0, sizeof(SYSNAMESTRUCT) );
  1388.  
  1389.   RMSysNameStr.SysDescriptName = RMSysName_Txt;
  1390.   RMSysNameStr.pAdjunctList    = &RMAdjunct;
  1391.  
  1392.   RMAdjunct.AdjType            = ADJ_DASD_VOL;
  1393.   RMAdjunct.pNextAdj           = 0;
  1394.   RMAdjunct.AdjLength          = sizeof(ADJUNCT);
  1395.  
  1396.   while ( pVolCB )
  1397.   {
  1398.     pUnitCB = pVolCB->pUnitCB;
  1399.  
  1400.     if (pVolCB->LogDriveNum < 26 )
  1401.     {
  1402.       RMSysName_Txt[0] = pVolCB->LogDriveNum + 'A';
  1403.  
  1404.       if ( pVolCB->RecBPB.TotalSectors )
  1405.       {
  1406.         RMAdjunct.Dasd_Vol.VolSize = pVolCB->RecBPB.TotalSectors;
  1407.       }
  1408.       else
  1409.       {
  1410.         RMAdjunct.Dasd_Vol.VolSize = pVolCB->RecBPB.BigTotalSectors;
  1411.       }
  1412.  
  1413.       RMAdjunct.Dasd_Vol.VolIFSType = pVolCB->PartitionType;
  1414.  
  1415.       if ( hRMLDev = pUnitCB->hRMLDev )
  1416.       {
  1417.         if ( !(rc = RMCreateSysName( (HDRIVER)        hRMOS2DASD,
  1418.                                      (PHSYSNAME)      &hRMSysName,
  1419.                                      (HDEVICE)        pUnitCB->hRMLDev,
  1420.                                      (PSYSNAMESTRUCT) &RMSysNameStr  )) )
  1421.         {
  1422.           if ( hRMSysName != -1L )
  1423.           {
  1424.             pVolCB->hRMSysName = hRMSysName;
  1425.           }
  1426.         }
  1427.       }
  1428.     }
  1429.  
  1430.     pVolCB = pVolCB->pNextVolCB;
  1431.   }
  1432. }
  1433.  
  1434.  
  1435. VOID NEAR memset( PSZ d, USHORT Value, USHORT n )
  1436. {
  1437.   USHORT        i;
  1438.  
  1439.   for ( i=0; i < n; i++ )
  1440.   {
  1441.     *d++ = (UCHAR) Value;
  1442.   }
  1443. }
  1444.