home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2DASD / DMFAULT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  31.4 KB  |  1,077 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 = "src/dev/dasd/os2dasd/dmfault.c, dsdm, ddk_subset, b_bdd.032 93/03/19";*/
  13. #define SCCSID  "src/dev/dasd/os2dasd/dmfault.c, dsdm, ddk_subset, b_bdd.032 93/03/19"
  14.  
  15. /**************************************************************************
  16.  *
  17.  * SOURCE FILE NAME = DMFAULT.C
  18.  *
  19.  * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
  20.  *
  21.  *
  22.  *
  23.  *
  24.  * VERSION = V2.0
  25.  *
  26.  * DATE
  27.  *
  28.  * DESCRIPTION : Drive Mirroring Support for Fault Tolerant Lan
  29.  *               Subsystem
  30.  *
  31.  *
  32. */
  33.  
  34. #include "dmh.h"
  35. #include "dmfault.h"
  36.  
  37.  
  38. VOID   FT_PutDeferredQueue  (PBYTE);                                 /*@V99999*/
  39. #pragma alloc_text(SwapCode, FT_PutDeferredQueue)                    /*@V99999*/
  40.  
  41. USHORT   FT_PullDeferredQueue (PBYTE FAR *);                         /*@V99999*/
  42. #pragma alloc_text(SwapCode, FT_PullDeferredQueue)                   /*@V99999*/
  43.  
  44. VOID   FT_PutDeferredRequest (PBYTE);                                /*@V99999*/
  45. #pragma alloc_text(SwapCode, FT_PutDeferredRequest)                  /*@V99999*/
  46.  
  47. USHORT FT_LockFTCode(VOID);
  48. #pragma alloc_text(SwapCode, FT_LockFTCode)
  49.  
  50. VOID   FT_CodeSegEnd(VOID);
  51. #pragma alloc_text(SwapCode, FT_CodeSegEnd)
  52.  
  53. /*------------------------------------------------------------------------
  54. ;
  55. ;** GIO_FaultTolerance - IOCTL to enable fault tolerance support
  56. ;
  57. ;   IOCTL to enable fault tolerance support
  58. ;
  59. ;   USHORT GIO_RWVTrack (NPCWA pCWA)
  60. ;
  61. ;   ENTRY:    pCWA             - CWA
  62. ;
  63. ;   RETURN:   USHORT           - Packet Status word
  64. ;
  65. ------------------------------------------------------------------------*/
  66. USHORT GIO_FaultTolerance (pCWA)
  67.  
  68. NPCWA pCWA;
  69. {
  70.    PFT_IOCTL_param pParmPkt;
  71.    PPDT   pPDT;
  72.    USHORT TotalPartitions, i, rc;
  73.    NPVOLCB pVolCB;
  74.  
  75.    if ((rc = CheckFTPacket(pCWA)) & STDON)
  76.       return(rc);
  77.  
  78.    pParmPkt = (PFT_IOCTL_param) pCWA->pParmPkt;
  79.    pPDT = pParmPkt->pPDT;
  80.  
  81.    TotalPartitions = NumPartitions + NumFTPartitions;
  82.  
  83.  
  84.    /* Fill in the partition descriptor table header */
  85.  
  86.    ((PPDTH)pPDT)->NumControllers = (UCHAR) NumAdapters;
  87.    ((PPDTH)pPDT)->NumPhysDisks =  (UCHAR) NumFixedDisks;
  88.    ((PPDTH)pPDT)->NumPartitions = (UCHAR) TotalPartitions;
  89.    ((PPDTH)pPDT)->NumLogUnits = (UCHAR) NumPartitions;
  90.    ((PPDTH)pPDT)->PartNumOffset = 0;
  91.    ((PPDTH)pPDT)->Reserved_1 = 0;
  92.    ((PPDTH)pPDT)->Reserved_2 = 0;
  93.    ((PPDTH)pPDT)->Reserved_3 = 0;
  94.    ((PPDTH)pPDT)->Reserved_4 = 0;
  95.  
  96.  
  97.    /* Fill in the partition decriptor entries for each logical drive */
  98.  
  99.    OFFSETOF (pPDT) = OFFSETOF (pPDT) + sizeof(PDTH);
  100.  
  101.    pVolCB = pVolCB_DriveC;
  102.  
  103.    for (i = 0; i < TotalPartitions; i++, pVolCB = pVolCB->pNextVolCB, pPDT++)
  104.    {
  105.       pPDT->Controller = (UCHAR) pVolCB->pUnitCB->AdapterNumber;
  106.       pPDT->PhysDisk = (UCHAR) pVolCB->pUnitCB->PhysDriveNum;
  107.       pPDT->PartitionType = pVolCB->PartitionType;
  108.       pPDT->LogUnit = (UCHAR) pVolCB->LogDriveNum;
  109.       if (pVolCB->Flags & vf_FTPartition)
  110.          pPDT->LogUnit = -1;
  111.  
  112.       pPDT->StartSec = pVolCB->PartitionOffset+pVolCB->MediaBPB.HiddenSectors;
  113.  
  114.       if (pVolCB->MediaBPB.TotalSectors != 0)
  115.          pPDT->EndSec = pPDT->StartSec + pVolCB->MediaBPB.TotalSectors - 1;
  116.       else
  117.          pPDT->EndSec = pPDT->StartSec + pVolCB->MediaBPB.BigTotalSectors - 1;
  118.  
  119.       pPDT->Reserved = 0;
  120.  
  121.       pVolCB->FT_PartitionNumber = i + 1;
  122.    }
  123.  
  124.  
  125.    /* Fill in the partition decriptor entries for each physical drive */
  126.  
  127.    for (i = 0; i < NumFixedDisks; i++, pVolCB = pVolCB->pNextVolCB, pPDT++)
  128.    {
  129.       pPDT->Controller = (UCHAR) pVolCB->pUnitCB->AdapterNumber;
  130.       pPDT->PhysDisk = (UCHAR) pVolCB->pUnitCB->PhysDriveNum;
  131.       pPDT->PartitionType = 0;
  132.       pPDT->LogUnit = 0;
  133.       pPDT->StartSec = 0;
  134.       pPDT->EndSec = 0;
  135.       pPDT->Reserved = 0;
  136.    }
  137.  
  138.    if (pParmPkt->Command == FT_ENABLE)
  139.    {
  140.       pDiskFT_Request = (PVOID) pParmPkt->FT_Request;
  141.       pDiskFT_Done = (PVOID) pParmPkt->FT_Done;
  142.       DiskFT_DS = pParmPkt->FT_ProtDS;
  143.       DDFlags |= DDF_FT_ENABLED;
  144.    }
  145.    else if (pParmPkt->Command == FT_DISABLE)
  146.       DDFlags &= ~DDF_FT_ENABLED;
  147.  
  148. }
  149.  
  150. /*------------------------------------------------------------------------
  151. ;
  152. ;** CheckFTPacket - Check Fault Tolerance packets
  153. ;
  154. ;   USHORT CheckFTPacket (NPCWA pCWA)
  155. ;
  156. ;   ENTRY:    pCWA             - CWA
  157. ;
  158. ;   RETURN:   USHORT           - Packet Status word
  159. ;
  160. ------------------------------------------------------------------------*/
  161. USHORT CheckFTPacket (pCWA)
  162.  
  163. NPCWA pCWA;
  164. {
  165.    USHORT rc, MaxPDTsize;
  166.    PFT_IOCTL_param pParmPkt;
  167.    PFT_IOCTL_data pDataPkt;
  168.    PPDT pPDT;
  169.  
  170.    pParmPkt = (PFT_IOCTL_param) pCWA->pParmPkt;
  171.    pDataPkt = (PFT_IOCTL_data) pCWA->pDataPkt;
  172.  
  173.    /* Verify access to the data and parameter packets */
  174.  
  175.    if ((rc = LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
  176.                             sizeof(FT_IOCTL_data))) & STERR)
  177.  
  178.       return(rc);
  179.  
  180.  
  181.    if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
  182.                             sizeof(FT_IOCTL_param))) & STERR)
  183.  
  184.       return(rc);
  185.  
  186.  
  187.    /* Lock the FT Code in the swap segment if FT not already locked */
  188.  
  189.    if ( !(DDFlags & DDF_FT_LOCKED) )
  190.    {
  191.       if ((rc = FT_LockFTCode()) & STERR)
  192.          return(rc);
  193.       else
  194.          DDFlags |= DDF_FT_LOCKED;
  195.    }
  196.  
  197.    /* Verify Access to the data block for the partition table         */
  198.    /* Max number of PDT entries is: 1 for PDT header + max 24 logical */
  199.    /* drives + number of fixed disks.                                 */
  200.  
  201.    pPDT = pParmPkt->pPDT;
  202.  
  203.    MaxPDTsize = (1 + 24 + NumFixedDisks) * sizeof (PDT);
  204.  
  205.    if (DevHelp_VerifyAccess
  206.            (SELECTOROF(pPDT), MaxPDTsize, OFFSETOF(pPDT), 1) != 0)
  207.  
  208.       return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  209.  
  210.  
  211.    /* Check the signature, version and if any FT partitions exist */
  212.  
  213.    pDataPkt->FT_SigDD = FT_SIG_DD;
  214.  
  215.    if (pParmPkt->FT_SigFT != FT_SIG)
  216.    {
  217.       pDataPkt->SupportCode = FT_INVALID_SIGNATURE;
  218.       return(STDON);
  219.    }
  220.  
  221.    if (pParmPkt->FT_Version != FT_VERSION)
  222.    {
  223.       pDataPkt->SupportCode = FT_VERSION_INCOMPAT;
  224.       return(STDON);
  225.    }
  226.  
  227.    if (NumFTPartitions == 0)
  228.       pDataPkt->SupportCode = FT_NO_FT_PARTITIONS;
  229.  
  230.    else
  231.       pDataPkt->SupportCode = FT_SUPPORTED;
  232.  
  233.    return(0);
  234. }
  235.  
  236. /*------------------------------------------------------------------------
  237. ;
  238. ;** FT_ExecReqList - Fault Tolerance Execute Strategy2 Request List
  239. ;
  240. ;   Executes Strategy2 request lists
  241. ;
  242. ;   USHORT FT_ExecReqList    (PReq_List_Header pRLH, pUnitCB);
  243. ;
  244. ;   ENTRY:    pRLH         - Request List Header
  245. ;             pUnitCB      - Pointer to UnitCB
  246. ;
  247. ;   RETURN:   VOID
  248. ;
  249. ------------------------------------------------------------------------*/
  250. VOID FAR f_FT_ExecReqList (pRLH, pUnitCB)
  251.  
  252. PReq_List_Header pRLH;
  253. NPUNITCB pUnitCB;
  254. {
  255.    FT_ExecReqList (pRLH, pUnitCB);
  256. }
  257.  
  258. VOID NEAR FT_ExecReqList (pRLH, pUnitCB)
  259.  
  260. PReq_List_Header pRLH;
  261. NPUNITCB pUnitCB;
  262. {
  263.    USHORT  i;
  264.    PPB_Read_Write pRLE;
  265.    NPUNITCB pUnitCB1  = 0;
  266.    NPUNITCB pUnitCB2  = 0;
  267.    NPUNITCB pUnitCB1t = 0;
  268.    NPUNITCB pUnitCB2t = 0;
  269.  
  270.    (PReq_List_Header) pRLE = pRLH + 1;
  271.  
  272.    pUnitCB1 = pUnitCB;
  273.  
  274.    /* Loop through the list */
  275.  
  276.    for (i = 0; i < pRLH->Count; i++)
  277.    {
  278.       if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
  279.       {
  280.          if (FT_CheckFTSupport(pUnitCB, (PBYTE) pRLE) == NO)
  281.          {
  282.              f_PutPriorityQueue_RLE (pUnitCB, pRLE);
  283.              pUnitCB1 = pUnitCB;
  284.          }
  285.          else
  286.          {
  287.             FT_PutPriorityQueue(pUnitCB, (PBYTE) pRLE,
  288.                      (NPUNITCB FAR *) &pUnitCB1t, (NPUNITCB FAR *) &pUnitCB2t);
  289.  
  290.             if (pUnitCB1t != 0)
  291.                pUnitCB1 = pUnitCB1t;
  292.  
  293.             if (pUnitCB2t != 0)
  294.                pUnitCB2 = pUnitCB2t;
  295.          }
  296.  
  297.          /* Only queue one at a time if Execute in Sequence specified */
  298.  
  299.          if (pRLH->Request_Control & RLH_Exe_Req_Seq)
  300.             break;
  301.       }
  302.  
  303.       OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
  304.    }
  305.  
  306.    pRLH->Lst_Status &= ~RLH_Req_Not_Queued;
  307.    pRLH->Lst_Status |= RLH_All_Req_Queued;
  308.  
  309.    if (pUnitCB1 != 0)
  310.       f_SubmitRequestsToADD(pUnitCB1);
  311.  
  312.    if (pUnitCB2 != 0)
  313.       f_SubmitRequestsToADD(pUnitCB2);
  314. }
  315.  
  316.  
  317. /*------------------------------------------------------------------------
  318. ;
  319. ;** FT_PutPriorityQueue - Put a request on a priority queue.
  320. ;
  321. ;   Put a Request Packet or Request List Entry on one of the priority
  322. ;   queues in the Unit Control Block for the specified unit.
  323. ;
  324. ;   VOID PutPriorityQueue  (NPUNITCB pUnitCB, PBYTE pRequest, pUnitCB1,
  325. ;                                                            pUnitCB2)
  326. ;
  327. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  328. ;             pRequest         - Pointer to Request Packet or Request List Entry
  329. ;             pUnitCB1         - returned pointer to UnitCB1
  330. ;             pUnitCB2         - returned pointer to UnitCB2
  331. ;
  332. ;
  333. ;   RETURN:   VOID
  334. ;
  335. ;   EFFECTS:
  336. ;
  337. ------------------------------------------------------------------------*/
  338. VOID FAR f_FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2)
  339.  
  340. NPUNITCB pUnitCBin;
  341. PBYTE    pRequest;
  342. NPUNITCB FAR *pUnitCB1;
  343. NPUNITCB FAR *pUnitCB2;
  344. {
  345.    FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2);
  346. }
  347.  
  348.  
  349. VOID NEAR FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2)
  350.  
  351. NPUNITCB pUnitCBin;
  352. PBYTE    pRequest;
  353. NPUNITCB FAR *pUnitCB1;
  354. NPUNITCB FAR *pUnitCB2;
  355.  
  356.  
  357. {
  358.    FT_RESULTS FT_Results;
  359.    UCHAR      ActionCode, Cmd, LogDriveNum;
  360.    USHORT     SzReqPkt;
  361.    PBYTE      pShadowReq;
  362.    NPVOLCB    pSecVolCB;
  363.    PFTDB      pFTDB;
  364.    NPVOLCB    pVolCB;
  365.    NPUNITCB   pUnitCB;
  366.    PReq_List_Header pRLH;
  367.  
  368.  
  369.    *pUnitCB1 = 0;                                                    /*@V99999*/
  370.    *pUnitCB2 = 0;                                                    /*@V99999*/
  371.  
  372.    if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  373.    {
  374.       pFTDB = &((PRHFT)pRequest)->ftdb;
  375.       Cmd = ((PPB_Read_Write)pRequest)->RqHdr.Command_Code;
  376.       SzReqPkt = ((((PPB_Read_Write)pRequest)->SG_Desc_Count) << 3) +
  377.                  sizeof(Req_List_Header) + sizeof(PB_Read_Write);
  378.       LogDriveNum = ((PRHFT)pRequest)->Block_Dev_Unit;
  379.    }
  380.    else
  381.    {
  382.       pFTDB = &((PRPFT)pRequest)->ftdb;
  383.       Cmd = ((PRPH)pRequest)->Cmd;
  384.       SzReqPkt = MAXRPSIZE;
  385.       LogDriveNum = ((PRPH)pRequest)->Unit;
  386.    }
  387.  
  388.    f_Get_VolCB_Addr(LogDriveNum, (NPVOLCB FAR *) &pVolCB);
  389.  
  390.    pUnitCB = pVolCB->pUnitCB;
  391.  
  392.    if (f_FT_Request( (pVolCB->FT_PartitionNumber << 8) + Cmd, SzReqPkt,
  393.                (PBYTE FAR *)&FT_Results, (PBYTE FAR *)&ActionCode) != 0)
  394.      /* Handle failure case */
  395.       {                                                              /*@V99999*/
  396.       FT_PutDeferredQueue(pRequest);                                 /*@V99999*/
  397.       return;                                                        /*@V99999*/
  398.       }                                                              /*@V99999*/
  399.  
  400.    if (ActionCode != ACT_PRIMARY)
  401.        FT_Get_VolCB_Addr( (USHORT)FT_Results.SecPartNum,
  402.                           (NPVOLCB FAR *)&pSecVolCB);
  403.  
  404.    /* IF ACT_EITHER, do load balancing and put the request on the queue */
  405.    /* with the least number of requests outstanding.                    */
  406.  
  407.    if (ActionCode == ACT_EITHER)
  408.    {
  409.       if ( (pUnitCB->NumReqsInProgress +
  410.             pUnitCB->NumReqsWaiting)  <=
  411.            (pSecVolCB->pUnitCB->NumReqsInProgress +
  412.             pSecVolCB->pUnitCB->NumReqsWaiting) )
  413.  
  414.         ActionCode = ACT_PRIMARY_FIRST;
  415.  
  416.       else
  417.  
  418.         ActionCode = ACT_SECONDARY_FIRST;
  419.    }
  420.  
  421.    /* Initialize FTDB area within the original request */
  422.  
  423.    pFTDB->FT_Flags = FTF_FT_REQUEST;
  424.    pFTDB->OrigRequest.RequestHandle = FT_Results.RequestHandle;
  425.  
  426.  
  427.    switch (ActionCode)
  428.    {
  429.       case ACT_PRIMARY:
  430.          f_PutPriorityQueue (pUnitCB, pRequest);
  431.          *pUnitCB1 = pUnitCB;
  432.          break;
  433.  
  434.       case ACT_PRIMARY_FIRST:
  435.          pFTDB->AltLogDriveNum = pSecVolCB->LogDriveNum;
  436.          f_PutPriorityQueue (pUnitCB, pRequest);
  437.          *pUnitCB1 = pUnitCB;
  438.          break;
  439.  
  440.       case ACT_SECONDARY:
  441.       case ACT_SECONDARY_FIRST:
  442.          pFTDB->AltLogDriveNum = pVolCB->LogDriveNum;
  443.  
  444.          if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  445.             ((PRHFT)pRequest)->Block_Dev_Unit = pSecVolCB->LogDriveNum;
  446.          else
  447.          {
  448.             ((PRP_RWV)pRequest)->rph.Unit = pSecVolCB->LogDriveNum;
  449.  
  450.             ((PRP_RWV)pRequest)->rba = ((PRP_RWV)pRequest)->rba -
  451.                pVolCB->PartitionOffset - pVolCB->MediaBPB.HiddenSectors +
  452.                pSecVolCB->PartitionOffset + pSecVolCB->MediaBPB.HiddenSectors;
  453.          }
  454.  
  455.          f_PutPriorityQueue (pSecVolCB->pUnitCB, pRequest);
  456.          *pUnitCB2 = pSecVolCB->pUnitCB;
  457.          break;
  458.  
  459.       case ACT_BOTH:
  460.          pFTDB->FT_Flags |= FTF_ACT_BOTH;
  461.          pShadowReq = FT_Results.pShadowReq;
  462.  
  463.          if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  464.          {
  465.             pRLH = (PReq_List_Header)pRequest;
  466.             OFFSETOF(pRLH) = OFFSETOF(pRequest) -
  467.                      (USHORT) (((PPB_Read_Write)pRequest)->RqHdr.Head_Offset);
  468.  
  469.             ((PReq_List_Header)pShadowReq)->Count = 1;
  470.             ((PReq_List_Header)pShadowReq)->Request_Control = RLH_Single_Req;
  471.             if (pRLH->Request_Control & RLH_Exe_Req_Seq)
  472.               ((PReq_List_Header)pShadowReq)->Request_Control |= RLH_Exe_Req_Seq;
  473.  
  474.             ((PReq_List_Header)pShadowReq)->Lst_Status = 0;
  475.             ((PReq_List_Header)pShadowReq)->Block_Dev_Unit =
  476.                                             pSecVolCB->LogDriveNum;
  477.             ((PReq_List_Header)pShadowReq)->y_Done_Count = 0;
  478.             ((PReq_List_Header)pShadowReq)->y_PhysAddr=f_VirtToPhys(pShadowReq);
  479.  
  480.             OFFSETOF(pShadowReq) = OFFSETOF(pShadowReq)+sizeof(Req_List_Header);
  481.             pFTDB = &((PRHFT)pShadowReq)->ftdb;
  482.             f_BlockCopy(pShadowReq, pRequest, SzReqPkt - sizeof(Req_List_Header));
  483.             ((PPB_Read_Write)pShadowReq)->RqHdr.Length = -1;
  484.             ((PRHFT)pShadowReq)->Block_Dev_Unit = pSecVolCB->LogDriveNum;
  485.             ((PPB_Read_Write)pShadowReq)->RqHdr.Head_Offset
  486.                                           = sizeof(Req_List_Header);
  487.             ((PPB_Read_Write)pShadowReq)->RqHdr.Req_Control = 0;
  488.             ((PPB_Read_Write)pShadowReq)->RqHdr.Status = 0;
  489.          }
  490.          else
  491.          {
  492.             pFTDB = &((PRPFT)pShadowReq)->ftdb;
  493.  
  494.             f_BlockCopy(pShadowReq, pRequest, MAXRPSIZE);
  495.             ((PRP_RWV)pShadowReq)->rph.Unit = pSecVolCB->LogDriveNum;
  496.             ((PRP_RWV)pShadowReq)->rba = ((PRP_RWV)pRequest)->rba -
  497.                 pVolCB->PartitionOffset - pVolCB->MediaBPB.HiddenSectors +
  498.                 pSecVolCB->PartitionOffset + pSecVolCB->MediaBPB.HiddenSectors;
  499.          }
  500.          pFTDB->FT_Flags = FTF_FT_REQUEST | FTF_ACT_BOTH | FTF_SHADOW_REQUEST;
  501.          pFTDB->pOrigRequest = pRequest;
  502.  
  503.          f_PutPriorityQueue (pUnitCB, pRequest);
  504.          f_PutPriorityQueue (pSecVolCB->pUnitCB, pShadowReq);
  505.  
  506.          *pUnitCB1 = pUnitCB;
  507.          *pUnitCB2 = pSecVolCB->pUnitCB;
  508.  
  509.    }
  510. }
  511.  
  512.  
  513.  
  514. /*------------------------------------------------------------------------
  515. ;
  516. ;** FT_NotifyDoneIORB_RLE  - Done processing for fault tolerance requests
  517. ;
  518. ;   USHORT FT_NotifyDone (NPIORB pIORB, PPB_Read_Write pRequest,
  519. ;                                       PPB_Read_Write pOrigRequest)
  520. ;
  521. ;   ENTRY:    pIORB            - pointer to completed IORB
  522. ;             pRequest         - pointer to Request List Entry
  523. ;             pOrigRequest     - return pointer to original RLE
  524. ;
  525. ;   RETURN:   USHORT           - packet status word
  526. ;
  527. ;   EFFECTS:
  528. ;
  529. ------------------------------------------------------------------------*/
  530. USHORT FAR f_FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest)
  531.  
  532. NPIORB            pIORB;
  533. PPB_Read_Write    pRequest;
  534. PPB_Read_Write    FAR *pOrigRequest;
  535. {
  536.    return(FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest));
  537. }
  538.  
  539. USHORT NEAR FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest)
  540.  
  541. NPIORB            pIORB;
  542. PPB_Read_Write    pRequest;
  543. PPB_Read_Write    FAR *pOrigRequest;
  544. {
  545.    USHORT  DoneParm1;
  546.    USHORT  RequestHandle;
  547.    USHORT  RC;
  548.    NPVOLCB pVolCB;
  549.    PFTDB   pFTDB;
  550.    PBYTE   pReq;                                                     /*@V99999*/
  551.  
  552.    pFTDB = &((PRHFT)pRequest)->ftdb;
  553.    f_Get_VolCB_Addr ( ((PRHFT)pRequest)->Block_Dev_Unit, (NPVOLCB FAR*)&pVolCB);
  554.    DoneParm1 = pVolCB->FT_PartitionNumber << 8;
  555.  
  556.    if ( (pRequest->RqHdr.Status & 0xF0) == RH_NO_ERROR)
  557.       (UCHAR) DoneParm1 = 0xFF;
  558.    else
  559.       (UCHAR) DoneParm1 = pRequest->RqHdr.Error_Code;
  560.  
  561.    if (pFTDB->FT_Flags & FTF_SHADOW_REQUEST)
  562.    {
  563.       (PBYTE) *pOrigRequest = pFTDB->pOrigRequest;
  564.       RequestHandle = ((PRHFT)(*pOrigRequest))->ftdb.OrigRequest.RequestHandle;
  565.    }
  566.    else
  567.    {
  568.       *pOrigRequest = pRequest;
  569.       RequestHandle = pFTDB->OrigRequest.RequestHandle;
  570.    }
  571.  
  572.    RC = f_FT_Done(DoneParm1, RequestHandle, pRequest->Start_Block);
  573.  
  574.  
  575.    if  (RC & STDON)
  576.    {
  577.       pRequest = *pOrigRequest;
  578.  
  579.       if (RC & STERR)
  580.       {
  581.          pRequest->RqHdr.Status = RH_UNREC_ERROR;
  582.          pRequest->Blocks_Xferred = 0;
  583.  
  584.          if ( (UCHAR)RC >= I24_MIN_RECOV_ERROR )
  585.             pRequest->RqHdr.Status = RH_RECOV_ERROR;
  586.          pRequest->RqHdr.Error_Code = (UCHAR) RC;
  587.       }
  588.       else
  589.       {
  590.          pRequest->RqHdr.Status = RH_NO_ERROR;
  591.          pRequest->Blocks_Xferred = pRequest->Block_Count;
  592.          pRequest->RqHdr.Error_Code = 0;
  593.       }
  594.  
  595.       /*  Check to see if any requests were deferred  */             /*@V99999*/
  596.       if (NumReqsDeferred != 0)                                      /*@V99999*/
  597.       {                                                              /*@V99999*/
  598.          if (FT_PullDeferredQueue( (PBYTE FAR *)&pReq) == NO_ERROR)  /*@V99999*/
  599.             FT_PutDeferredRequest(pReq);                             /*@V99999*/
  600.       }                                                              /*@V99999*/
  601.       return(STDON);
  602.    }
  603.  
  604.   /* Request is not done.  For mirrored writes, no further work is  */
  605.   /* needed. Just wait for the second write to complete.  For reads,*/
  606.   /* re-queue the request to the alternate unit.                    */
  607.  
  608.   if ( !(pFTDB->FT_Flags & FTF_ACT_BOTH) )
  609.   {
  610.      f_Get_VolCB_Addr(pFTDB->AltLogDriveNum, (NPVOLCB FAR *)&pVolCB);
  611.      ((PRHFT)pRequest)->Block_Dev_Unit = (UCHAR) pVolCB->LogDriveNum;
  612.      pRequest->RqHdr.Status = 0;
  613.      f_PutPriorityQueue (pVolCB->pUnitCB, (PBYTE) pRequest);
  614.      f_SubmitRequestsToADD(pVolCB->pUnitCB);
  615.   }
  616.   return(0);
  617. }
  618.  
  619.  
  620. /*------------------------------------------------------------------------
  621. ;
  622. ;** FT_NotifyDoneIORB_RP  - Done processing for fault tolerance requests
  623. ;
  624. ;   USHORT FT_NotifyDoneIORB_RP (NPIORB pIORB,  PBYTE FAR *pRequest,
  625. ;                                               PBYTE FAR *pOrigRequest)
  626. ;
  627. ;   ENTRY:    pIORB            - pointer to completed IORB
  628. ;             pRequest         - pointer to Request Packet
  629. ;             pOrigRequest     - returned pointer to orig shadow RP
  630. ;
  631. ;   RETURN:   USHORT           - packet status word
  632. ;
  633. ;   EFFECTS:
  634. ;
  635. ------------------------------------------------------------------------*/
  636. USHORT FAR f_FT_NotifyDoneIORB_RP  (pIORB, pRequest, pOrigRequest)
  637.  
  638. NPIORB    pIORB;
  639. PRP_RWV   pRequest;
  640. PRP_RWV   FAR *pOrigRequest;
  641. {
  642.    return(FT_NotifyDoneIORB_RP  (pIORB, pRequest, pOrigRequest));
  643. }
  644.  
  645. USHORT NEAR FT_NotifyDoneIORB_RP  (pIORB, pRequest, pOrigRequest)
  646.  
  647. NPIORB    pIORB;
  648. PRP_RWV   pRequest;
  649. PRP_RWV   FAR *pOrigRequest;
  650.  
  651. {
  652.    USHORT  DoneParm1;
  653.    USHORT  RequestHandle;
  654.    ULONG   StartBlock;
  655.    USHORT  RC;
  656.    NPVOLCB pVolCB;
  657.    PFTDB   pFTDB;
  658.    PBYTE   pReq;                                                     /*@V99999*/
  659.  
  660.    pFTDB = &((PRPFT)pRequest)->ftdb;
  661.    f_Get_VolCB_Addr(pRequest->rph.Unit, (NPVOLCB FAR *)&pVolCB);
  662.    DoneParm1 = pVolCB->FT_PartitionNumber << 8;
  663.  
  664.    StartBlock = pRequest->rba - pVolCB->PartitionOffset -
  665.                                 pVolCB->MediaBPB.HiddenSectors;
  666.  
  667.    if (pRequest->rph.Status & STERR)
  668.       (UCHAR) DoneParm1 = (UCHAR) pRequest->rph.Status;
  669.    else
  670.       (UCHAR) DoneParm1 = 0xff;
  671.  
  672.    if (pFTDB->FT_Flags & FTF_SHADOW_REQUEST)
  673.    {
  674.        (PBYTE) *pOrigRequest = pFTDB->pOrigRequest;
  675.        RequestHandle = ((PRPFT)(*pOrigRequest))->ftdb.OrigRequest.RequestHandle;
  676.    }
  677.    else
  678.    {
  679.       *pOrigRequest = pRequest;
  680.       RequestHandle = pFTDB->OrigRequest.RequestHandle;
  681.    }
  682.  
  683.    RC = f_FT_Done(DoneParm1, RequestHandle, StartBlock);
  684.  
  685.    if  (RC & STDON)
  686.    {
  687.       pRequest = *pOrigRequest;
  688.       pRequest->rph.Status = RC;
  689.  
  690.       if (RC & STERR)
  691.         pRequest->NumSectors = 0;
  692.  
  693.       /*  Check to see if any requests were deferred  */             /*@V99999*/
  694.       if (NumReqsDeferred != 0)                                      /*@V99999*/
  695.       {                                                              /*@V99999*/
  696.          if (FT_PullDeferredQueue( (PBYTE FAR *)&pReq) == NO_ERROR)  /*@V99999*/
  697.             FT_PutDeferredRequest(pReq);                             /*@V99999*/
  698.       }                                                              /*@V99999*/
  699.       return(STDON);
  700.    }
  701.  
  702.   /* Request is not done.  For mirrored writes, no further work is  */
  703.   /* needed. Just wait for the second write to complete.  For reads,*/
  704.   /* re-queue the request to the alternate unit.                    */
  705.  
  706.   if ( !(pFTDB->FT_Flags & FTF_ACT_BOTH) )
  707.   {
  708.      f_Get_VolCB_Addr(pFTDB->AltLogDriveNum, (NPVOLCB FAR *)&pVolCB);
  709.      pRequest->rph.Unit = pVolCB->LogDriveNum;
  710.      pRequest->rba = StartBlock + pVolCB->PartitionOffset +
  711.                                   pVolCB->MediaBPB.HiddenSectors;
  712.      f_PutPriorityQueue (pVolCB->pUnitCB, (PBYTE) pRequest);
  713.      f_SubmitRequestsToADD(pVolCB->pUnitCB);
  714.   }
  715.   return(0);
  716. }
  717. /*------------------------------------------------------------------------
  718. ;
  719. ;** FT_CheckFTSupport  - See if request requires fault tolerance support
  720. ;
  721. ;   Check to see if the request requires fault tolerance support
  722. ;
  723. ;   USHORT    FT_CheckFTSupport (NPUNITCB pUnitCB, PBYTE pRequest)
  724. ;
  725. ;   ENTRY     pUnitCB     - Pointer to UnitCB
  726. ;             pRequest    - Pointer to Request Packet or Request List Entry
  727. ;
  728. ;   RETURN:   USHORT      - YES = FT required,
  729. ;                           NO = No FT required
  730. ;   EFFECTS:
  731. ;
  732. ------------------------------------------------------------------------*/
  733. USHORT FAR f_FT_CheckFTSupport (pUnitCB, pRequest)
  734.  
  735. NPUNITCB   pUnitCB;
  736. PBYTE      pRequest;
  737. {
  738.    return(FT_CheckFTSupport (pUnitCB, pRequest));
  739. }
  740.  
  741. USHORT NEAR FT_CheckFTSupport (pUnitCB, pRequest)
  742.  
  743. NPUNITCB   pUnitCB;
  744. PBYTE      pRequest;
  745.  
  746. {
  747.  
  748.    static UCHAR FTCmdTable[] =
  749.    {
  750.       CMDINPUT, CMDOUTPUT, CMDOUTPUTV,
  751.       CMDInputBypass, CMDOutputBypass, CMDOutputBypassV,
  752.       PB_READ_X, PB_WRITE_X, PB_WRITEV_X
  753.    };
  754.  
  755.    UCHAR  Cmd;
  756.    USHORT i;
  757.    PReq_List_Header pRLH;
  758.  
  759.    /* See if FT is enabled */
  760.  
  761.    if ( !(DDFlags & DDF_FT_ENABLED) )
  762.       return(NO);
  763.  
  764.    /* No FT support for removable media                           */
  765.  
  766.    if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  767.       return(NO);
  768.  
  769.    /* No FT support for I/O to physical drives, i.e. 0x80, etc)   */
  770.  
  771.    if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  772.    {
  773.       SELECTOROF(pRLH) = SELECTOROF(pRequest);
  774.       OFFSETOF(pRLH) = OFFSETOF(pRequest) -
  775.               (USHORT) ((PPB_Read_Write)pRequest)->RqHdr.Head_Offset;
  776.  
  777.       if (pRLH->Block_Dev_Unit & 0x80)
  778.          return(NO);
  779.  
  780.       Cmd = ((PPB_Read_Write)pRequest)->RqHdr.Command_Code;
  781.    }
  782.    else
  783.    {
  784.       if ( ((PRPH)pRequest)->Unit & 0x80 )
  785.         return(NO);
  786.  
  787.       Cmd = ((PRPH)pRequest)->Cmd;
  788.    }
  789.  
  790.    /* See if it's a command which requires FT support */
  791.  
  792.    for (i = 0; i < sizeof(FTCmdTable); i++)
  793.    {
  794.       if (Cmd == FTCmdTable[i])
  795.          return(YES);
  796.    }
  797.  
  798.    return(NO);
  799. }
  800.  
  801.  
  802. /*------------------------------------------------------------------------
  803. ;
  804. ;** FT_Get_VolCB_Addr - Return a pointer to a VolCB for the specified Drive
  805. ;
  806. ;   USHORT NEAR FT_Get_VolCB_Addr   (USHORT PartNum, NPVOLCB *pVolCB)
  807. ;
  808. ;   ENTRY:    ParmNum          - FT Partition Number
  809. ;             pVolCB           - returned pointer to VolCB
  810. ;
  811. ;   RETURN:   USHORT           - Result Code (NO_ERROR if VolCB found)
  812. ;
  813. ;   EFFECTS:
  814. ;
  815. ;   NOTES:
  816. ------------------------------------------------------------------------*/
  817. USHORT FAR f_FT_Get_VolCB_Addr (PartNum, pVolCB)
  818.  
  819. USHORT  PartNum;
  820. NPVOLCB FAR *pVolCB;
  821. {
  822.    return(FT_Get_VolCB_Addr (PartNum, pVolCB));
  823. }
  824.  
  825. USHORT FT_Get_VolCB_Addr (PartNum, pVolCB)
  826.  
  827. USHORT  PartNum;
  828. NPVOLCB FAR *pVolCB;
  829. {
  830.    USHORT  found = FALSE;
  831.    NPVOLCB pVolCBx;
  832.  
  833.    if ( !(DDFlags & DDF_NO_MEDIA) )
  834.    {
  835.       pVolCBx = VolCB_Head;
  836.  
  837.       while (pVolCBx != NULL && found == FALSE)
  838.       {
  839.          if (pVolCBx->FT_PartitionNumber == PartNum)
  840.             found = TRUE;
  841.          else
  842.             pVolCBx = pVolCBx->pNextVolCB;
  843.       }
  844.    }
  845.  
  846.    if (found == TRUE)
  847.    {
  848.       *pVolCB = pVolCBx;
  849.       return(NO_ERROR);
  850.    }
  851.    else
  852.       return(ERROR);
  853. }
  854.  
  855.  
  856. /*------------------------------------------------------------------------
  857. ;
  858. ;** FT_LockFTCode - Lock FT Code in swap segment
  859. ;
  860. ;   USHORT NEAR FT_LockFTCode (VOID)
  861. ;
  862. ;   ENTRY:    VOID
  863. ;
  864. ;   RETURN:   USHORT           - Packet Status Word
  865. ;
  866. ;   EFFECTS:
  867. ;
  868. ;   NOTES:
  869. ------------------------------------------------------------------------*/
  870. USHORT FT_LockFTCode()
  871.  
  872. {
  873.    ULONG plFTCode;             /* Linear address of Parm or Data Packet */
  874.    ULONG plLockHandle;
  875.    UCHAR LockHandle[12];
  876.    ULONG PageListCount;
  877.    USHORT Length;
  878.    USHORT rc;
  879.  
  880.    (PVOID) plFTCode = (PVOID) f_FT_ExecReqList;
  881.    rc = DevHelp_VirtToLin(SELECTOROF(plFTCode),
  882.                             (ULONG) OFFSETOF(plFTCode),
  883.                             (PVOID) &plFTCode);
  884.  
  885.    (PVOID) plLockHandle = (PVOID) &LockHandle;
  886.    rc = DevHelp_VirtToLin(SELECTOROF(plLockHandle),
  887.                             (ULONG) OFFSETOF(plLockHandle),
  888.                             (PVOID) &plLockHandle);
  889.  
  890.    Length = (USHORT) FT_CodeSegEnd - (USHORT) f_FT_ExecReqList;
  891.  
  892.    if (DevHelp_VMLock(VMDHL_LONG, plFTCode, Length, -1,
  893.                   plLockHandle, (PULONG) &PageListCount) != 0)
  894.  
  895.       return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
  896.  
  897.  
  898.    return(STDON);
  899.  
  900. }
  901.  
  902. /*  lpq   */
  903. /*------------------------------------------------------------------------
  904. ;
  905. ;** FT_PutDeferredQueue  - Put a Request on a deferred queue.
  906. ;
  907. ;   This routine places an RLE or RP on the apropriate deferred queue when
  908. ;   the call to FT_Request fails (due to lack of resources).
  909. ;
  910. ;   VOID FT_PutDeferredQueue  (PBYTE pRequest)
  911. ;
  912. ;   ENTRY:    pRequest         - Pointer to Request List Entry or Request Pkt
  913. ;
  914. ;   RETURN:   VOID
  915. ;
  916. ;   EFFECTS:
  917. ;
  918. ------------------------------------------------------------------------*/
  919. VOID FT_PutDeferredQueue  (pRequest)
  920.  
  921. PBYTE  pRequest;
  922.  
  923. {
  924.  
  925.    PUSHFLAGS;
  926.    DISABLE;
  927.  
  928.    /* Place on Request List Entry Deferred Queue  */
  929.  
  930.    if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  931.    {
  932.       if (DeferredQRLE.Head == 0)
  933.       {
  934.          DeferredQRLE.Head = pRequest;
  935.          DeferredQRLE.Tail = pRequest;
  936.          ((PPB_Read_Write)pRequest)->RqHdr.Waiting = 0;
  937.       }
  938.       else
  939.       {
  940.          ((PPB_Read_Write)(DeferredQRLE.Tail))->RqHdr.Waiting = (ULONG)pRequest;
  941.          DeferredQRLE.Tail =  pRequest;
  942.       }
  943.    }
  944.    else
  945.    /* Place on Request Packet Deferred Queue  */
  946.    {
  947.       if (DeferredQRP.Head == 0)
  948.       {
  949.          DeferredQRP.Head = pRequest;
  950.          DeferredQRP.Tail = pRequest;
  951.          ((PRPH)pRequest)->Link = 0;
  952.       }
  953.       else
  954.       {
  955.          ((PRPH)(DeferredQRP.Tail))->Link = (PRPH) pRequest;
  956.          DeferredQRP.Tail =  pRequest;
  957.       }
  958.    }
  959.  
  960.    NumReqsDeferred++;
  961.  
  962.    ENABLE;
  963.    POPFLAGS;
  964.  
  965. }
  966.  
  967.  
  968. /*------------------------------------------------------------------------
  969. ;
  970. ;** FT_PullDeferredQueue - Pull a request from a deferred queue.
  971. ;
  972. ;   This routine removes a Request List Entry, or a Request Packet from
  973. ;   the deferred queues.
  974. ;
  975. ;   USHORT    FT_PullDeferredQueue (PBYTE *pReqAddr)
  976. ;
  977. ;   ENTRY:    pReqAddr     - Returned pointer to pulled Request List
  978. ;                            Entry or Request Packet
  979. ;
  980. ;   RETURN:   USHORT       -  =  0,  Request pulled
  981. ;                             <> 0,  No Request pulled, queues empty
  982. ;   EFFECTS:
  983. ;
  984. ------------------------------------------------------------------------*/
  985. USHORT  FT_PullDeferredQueue (pReqAddr)
  986.  
  987.    PBYTE  FAR *pReqAddr;
  988. {
  989.  
  990.    PBYTE    pRequest;
  991.  
  992.    PUSHFLAGS;
  993.    DISABLE;
  994.  
  995.  
  996.    /* Search the Request List Deferred Queue First  */
  997.  
  998.    if (DeferredQRLE.Head != 0)
  999.    {
  1000.       pRequest = DeferredQRLE.Head;
  1001.       DeferredQRLE.Head = (PBYTE) ((PPB_Read_Write)pRequest)->RqHdr.Waiting;
  1002.       ((PPB_Read_Write)pRequest)->RqHdr.Waiting = 0;
  1003.       if (DeferredQRLE.Head == 0)
  1004.          DeferredQRLE.Tail = 0;
  1005.    }
  1006.  
  1007.    /* If it was empty, search the Request Packet Queue   */
  1008.  
  1009.    else if (DeferredQRP.Head != 0)
  1010.    {
  1011.       pRequest = DeferredQRP.Head;
  1012.       DeferredQRP.Head = (PBYTE) (((PRPH)pRequest)->Link);
  1013.       ((PRPH)pRequest)->Link = 0;
  1014.       if (DeferredQRP.Head == 0)
  1015.          DeferredQRP.Tail = 0;
  1016.    }
  1017.    else
  1018.       return(ERROR);
  1019.  
  1020.    *pReqAddr = pRequest;
  1021.    NumReqsDeferred--;
  1022.  
  1023.    ENABLE;
  1024.    POPFLAGS;
  1025.    return(NO_ERROR);
  1026. }
  1027.  
  1028. /*------------------------------------------------------------------------
  1029. ;
  1030. ;** FT_PutDeferredRequest   - Put a deferred request on a priority queue
  1031. ;
  1032. ;   This routine takes a request that was pulled from the deferred
  1033. ;   queue and attempts to queue it on a priority queue by calling
  1034. ;   FT_PutPriorityqueue.
  1035. ;
  1036. ;   VOID   FT_PutDeferredRequest (pRequest);
  1037. ;
  1038. ;   ENTRY:    pRequest     - Pointer to Request List Entry or Request Pkt
  1039. ;
  1040. ;   RETURN:   VOID
  1041. ;
  1042. ------------------------------------------------------------------------*/
  1043.  
  1044. VOID   FT_PutDeferredRequest (pRequest)
  1045.  
  1046. PBYTE   pRequest;
  1047.  
  1048. {
  1049.    UCHAR      LogDriveNum;
  1050.    NPVOLCB    pVolCB;
  1051.    NPUNITCB   pUnitCB1  = 0;
  1052.    NPUNITCB   pUnitCB2  = 0;
  1053.  
  1054.  
  1055.    /*  Get the Unit number and retrieve the Volume Control Block  */
  1056.    if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  1057.       LogDriveNum = ((PRHFT)pRequest)->Block_Dev_Unit;
  1058.    else
  1059.       LogDriveNum = ((PRPH)pRequest)->Unit;
  1060.  
  1061.    f_Get_VolCB_Addr(LogDriveNum, (NPVOLCB FAR *) &pVolCB);
  1062.  
  1063.  
  1064.    FT_PutPriorityQueue(pVolCB->pUnitCB,  pRequest, (NPUNITCB FAR *) &pUnitCB1,
  1065.                                                    (NPUNITCB FAR *) &pUnitCB2);
  1066.  
  1067.    if (pUnitCB1 != 0)
  1068.       f_SubmitRequestsToADD(pUnitCB1);
  1069.  
  1070.    if (pUnitCB2 != 0)
  1071.       f_SubmitRequestsToADD(pUnitCB2);
  1072. }
  1073.  
  1074. VOID FT_CodeSegEnd()
  1075. {
  1076. }
  1077.