home *** CD-ROM | disk | FTP | other *** search
- /*DDK*************************************************************************/
- /* */
- /* COPYRIGHT Copyright (C) 1995 IBM Corporation */
- /* */
- /* The following IBM OS/2 WARP source code is provided to you solely for */
- /* the purpose of assisting you in your development of OS/2 WARP device */
- /* drivers. You may use this code in accordance with the IBM License */
- /* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
- /* Copyright statement may not be removed. */
- /* */
- /*****************************************************************************/
- /*static char *SCCSID = "src/dev/dasd/os2dasd/dmfault.c, dsdm, ddk_subset, b_bdd.032 93/03/19";*/
- #define SCCSID "src/dev/dasd/os2dasd/dmfault.c, dsdm, ddk_subset, b_bdd.032 93/03/19"
-
- /**************************************************************************
- *
- * SOURCE FILE NAME = DMFAULT.C
- *
- * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
- *
- *
- *
- *
- * VERSION = V2.0
- *
- * DATE
- *
- * DESCRIPTION : Drive Mirroring Support for Fault Tolerant Lan
- * Subsystem
- *
- *
- */
-
- #include "dmh.h"
- #include "dmfault.h"
-
-
- VOID FT_PutDeferredQueue (PBYTE); /*@V99999*/
- #pragma alloc_text(SwapCode, FT_PutDeferredQueue) /*@V99999*/
-
- USHORT FT_PullDeferredQueue (PBYTE FAR *); /*@V99999*/
- #pragma alloc_text(SwapCode, FT_PullDeferredQueue) /*@V99999*/
-
- VOID FT_PutDeferredRequest (PBYTE); /*@V99999*/
- #pragma alloc_text(SwapCode, FT_PutDeferredRequest) /*@V99999*/
-
- USHORT FT_LockFTCode(VOID);
- #pragma alloc_text(SwapCode, FT_LockFTCode)
-
- VOID FT_CodeSegEnd(VOID);
- #pragma alloc_text(SwapCode, FT_CodeSegEnd)
-
- /*------------------------------------------------------------------------
- ;
- ;** GIO_FaultTolerance - IOCTL to enable fault tolerance support
- ;
- ; IOCTL to enable fault tolerance support
- ;
- ; USHORT GIO_RWVTrack (NPCWA pCWA)
- ;
- ; ENTRY: pCWA - CWA
- ;
- ; RETURN: USHORT - Packet Status word
- ;
- ------------------------------------------------------------------------*/
- USHORT GIO_FaultTolerance (pCWA)
-
- NPCWA pCWA;
- {
- PFT_IOCTL_param pParmPkt;
- PPDT pPDT;
- USHORT TotalPartitions, i, rc;
- NPVOLCB pVolCB;
-
- if ((rc = CheckFTPacket(pCWA)) & STDON)
- return(rc);
-
- pParmPkt = (PFT_IOCTL_param) pCWA->pParmPkt;
- pPDT = pParmPkt->pPDT;
-
- TotalPartitions = NumPartitions + NumFTPartitions;
-
-
- /* Fill in the partition descriptor table header */
-
- ((PPDTH)pPDT)->NumControllers = (UCHAR) NumAdapters;
- ((PPDTH)pPDT)->NumPhysDisks = (UCHAR) NumFixedDisks;
- ((PPDTH)pPDT)->NumPartitions = (UCHAR) TotalPartitions;
- ((PPDTH)pPDT)->NumLogUnits = (UCHAR) NumPartitions;
- ((PPDTH)pPDT)->PartNumOffset = 0;
- ((PPDTH)pPDT)->Reserved_1 = 0;
- ((PPDTH)pPDT)->Reserved_2 = 0;
- ((PPDTH)pPDT)->Reserved_3 = 0;
- ((PPDTH)pPDT)->Reserved_4 = 0;
-
-
- /* Fill in the partition decriptor entries for each logical drive */
-
- OFFSETOF (pPDT) = OFFSETOF (pPDT) + sizeof(PDTH);
-
- pVolCB = pVolCB_DriveC;
-
- for (i = 0; i < TotalPartitions; i++, pVolCB = pVolCB->pNextVolCB, pPDT++)
- {
- pPDT->Controller = (UCHAR) pVolCB->pUnitCB->AdapterNumber;
- pPDT->PhysDisk = (UCHAR) pVolCB->pUnitCB->PhysDriveNum;
- pPDT->PartitionType = pVolCB->PartitionType;
- pPDT->LogUnit = (UCHAR) pVolCB->LogDriveNum;
- if (pVolCB->Flags & vf_FTPartition)
- pPDT->LogUnit = -1;
-
- pPDT->StartSec = pVolCB->PartitionOffset+pVolCB->MediaBPB.HiddenSectors;
-
- if (pVolCB->MediaBPB.TotalSectors != 0)
- pPDT->EndSec = pPDT->StartSec + pVolCB->MediaBPB.TotalSectors - 1;
- else
- pPDT->EndSec = pPDT->StartSec + pVolCB->MediaBPB.BigTotalSectors - 1;
-
- pPDT->Reserved = 0;
-
- pVolCB->FT_PartitionNumber = i + 1;
- }
-
-
- /* Fill in the partition decriptor entries for each physical drive */
-
- for (i = 0; i < NumFixedDisks; i++, pVolCB = pVolCB->pNextVolCB, pPDT++)
- {
- pPDT->Controller = (UCHAR) pVolCB->pUnitCB->AdapterNumber;
- pPDT->PhysDisk = (UCHAR) pVolCB->pUnitCB->PhysDriveNum;
- pPDT->PartitionType = 0;
- pPDT->LogUnit = 0;
- pPDT->StartSec = 0;
- pPDT->EndSec = 0;
- pPDT->Reserved = 0;
- }
-
- if (pParmPkt->Command == FT_ENABLE)
- {
- pDiskFT_Request = (PVOID) pParmPkt->FT_Request;
- pDiskFT_Done = (PVOID) pParmPkt->FT_Done;
- DiskFT_DS = pParmPkt->FT_ProtDS;
- DDFlags |= DDF_FT_ENABLED;
- }
- else if (pParmPkt->Command == FT_DISABLE)
- DDFlags &= ~DDF_FT_ENABLED;
-
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** CheckFTPacket - Check Fault Tolerance packets
- ;
- ; USHORT CheckFTPacket (NPCWA pCWA)
- ;
- ; ENTRY: pCWA - CWA
- ;
- ; RETURN: USHORT - Packet Status word
- ;
- ------------------------------------------------------------------------*/
- USHORT CheckFTPacket (pCWA)
-
- NPCWA pCWA;
- {
- USHORT rc, MaxPDTsize;
- PFT_IOCTL_param pParmPkt;
- PFT_IOCTL_data pDataPkt;
- PPDT pPDT;
-
- pParmPkt = (PFT_IOCTL_param) pCWA->pParmPkt;
- pDataPkt = (PFT_IOCTL_data) pCWA->pDataPkt;
-
- /* Verify access to the data and parameter packets */
-
- if ((rc = LockUserPacket(pCWA, LOCK_DATAPKT + LOCK_VERIFYONLY,
- sizeof(FT_IOCTL_data))) & STERR)
-
- return(rc);
-
-
- if ((rc = LockUserPacket(pCWA, LOCK_PARMPKT + LOCK_VERIFYONLY,
- sizeof(FT_IOCTL_param))) & STERR)
-
- return(rc);
-
-
- /* Lock the FT Code in the swap segment if FT not already locked */
-
- if ( !(DDFlags & DDF_FT_LOCKED) )
- {
- if ((rc = FT_LockFTCode()) & STERR)
- return(rc);
- else
- DDFlags |= DDF_FT_LOCKED;
- }
-
- /* Verify Access to the data block for the partition table */
- /* Max number of PDT entries is: 1 for PDT header + max 24 logical */
- /* drives + number of fixed disks. */
-
- pPDT = pParmPkt->pPDT;
-
- MaxPDTsize = (1 + 24 + NumFixedDisks) * sizeof (PDT);
-
- if (DevHelp_VerifyAccess
- (SELECTOROF(pPDT), MaxPDTsize, OFFSETOF(pPDT), 1) != 0)
-
- return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
-
-
- /* Check the signature, version and if any FT partitions exist */
-
- pDataPkt->FT_SigDD = FT_SIG_DD;
-
- if (pParmPkt->FT_SigFT != FT_SIG)
- {
- pDataPkt->SupportCode = FT_INVALID_SIGNATURE;
- return(STDON);
- }
-
- if (pParmPkt->FT_Version != FT_VERSION)
- {
- pDataPkt->SupportCode = FT_VERSION_INCOMPAT;
- return(STDON);
- }
-
- if (NumFTPartitions == 0)
- pDataPkt->SupportCode = FT_NO_FT_PARTITIONS;
-
- else
- pDataPkt->SupportCode = FT_SUPPORTED;
-
- return(0);
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_ExecReqList - Fault Tolerance Execute Strategy2 Request List
- ;
- ; Executes Strategy2 request lists
- ;
- ; USHORT FT_ExecReqList (PReq_List_Header pRLH, pUnitCB);
- ;
- ; ENTRY: pRLH - Request List Header
- ; pUnitCB - Pointer to UnitCB
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID FAR f_FT_ExecReqList (pRLH, pUnitCB)
-
- PReq_List_Header pRLH;
- NPUNITCB pUnitCB;
- {
- FT_ExecReqList (pRLH, pUnitCB);
- }
-
- VOID NEAR FT_ExecReqList (pRLH, pUnitCB)
-
- PReq_List_Header pRLH;
- NPUNITCB pUnitCB;
- {
- USHORT i;
- PPB_Read_Write pRLE;
- NPUNITCB pUnitCB1 = 0;
- NPUNITCB pUnitCB2 = 0;
- NPUNITCB pUnitCB1t = 0;
- NPUNITCB pUnitCB2t = 0;
-
- (PReq_List_Header) pRLE = pRLH + 1;
-
- pUnitCB1 = pUnitCB;
-
- /* Loop through the list */
-
- for (i = 0; i < pRLH->Count; i++)
- {
- if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
- {
- if (FT_CheckFTSupport(pUnitCB, (PBYTE) pRLE) == NO)
- {
- f_PutPriorityQueue_RLE (pUnitCB, pRLE);
- pUnitCB1 = pUnitCB;
- }
- else
- {
- FT_PutPriorityQueue(pUnitCB, (PBYTE) pRLE,
- (NPUNITCB FAR *) &pUnitCB1t, (NPUNITCB FAR *) &pUnitCB2t);
-
- if (pUnitCB1t != 0)
- pUnitCB1 = pUnitCB1t;
-
- if (pUnitCB2t != 0)
- pUnitCB2 = pUnitCB2t;
- }
-
- /* Only queue one at a time if Execute in Sequence specified */
-
- if (pRLH->Request_Control & RLH_Exe_Req_Seq)
- break;
- }
-
- OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
- }
-
- pRLH->Lst_Status &= ~RLH_Req_Not_Queued;
- pRLH->Lst_Status |= RLH_All_Req_Queued;
-
- if (pUnitCB1 != 0)
- f_SubmitRequestsToADD(pUnitCB1);
-
- if (pUnitCB2 != 0)
- f_SubmitRequestsToADD(pUnitCB2);
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_PutPriorityQueue - Put a request on a priority queue.
- ;
- ; Put a Request Packet or Request List Entry on one of the priority
- ; queues in the Unit Control Block for the specified unit.
- ;
- ; VOID PutPriorityQueue (NPUNITCB pUnitCB, PBYTE pRequest, pUnitCB1,
- ; pUnitCB2)
- ;
- ; ENTRY: pUnitCB - Pointer to UnitCB
- ; pRequest - Pointer to Request Packet or Request List Entry
- ; pUnitCB1 - returned pointer to UnitCB1
- ; pUnitCB2 - returned pointer to UnitCB2
- ;
- ;
- ; RETURN: VOID
- ;
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- VOID FAR f_FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2)
-
- NPUNITCB pUnitCBin;
- PBYTE pRequest;
- NPUNITCB FAR *pUnitCB1;
- NPUNITCB FAR *pUnitCB2;
- {
- FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2);
- }
-
-
- VOID NEAR FT_PutPriorityQueue (pUnitCBin, pRequest, pUnitCB1, pUnitCB2)
-
- NPUNITCB pUnitCBin;
- PBYTE pRequest;
- NPUNITCB FAR *pUnitCB1;
- NPUNITCB FAR *pUnitCB2;
-
-
- {
- FT_RESULTS FT_Results;
- UCHAR ActionCode, Cmd, LogDriveNum;
- USHORT SzReqPkt;
- PBYTE pShadowReq;
- NPVOLCB pSecVolCB;
- PFTDB pFTDB;
- NPVOLCB pVolCB;
- NPUNITCB pUnitCB;
- PReq_List_Header pRLH;
-
-
- *pUnitCB1 = 0; /*@V99999*/
- *pUnitCB2 = 0; /*@V99999*/
-
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- {
- pFTDB = &((PRHFT)pRequest)->ftdb;
- Cmd = ((PPB_Read_Write)pRequest)->RqHdr.Command_Code;
- SzReqPkt = ((((PPB_Read_Write)pRequest)->SG_Desc_Count) << 3) +
- sizeof(Req_List_Header) + sizeof(PB_Read_Write);
- LogDriveNum = ((PRHFT)pRequest)->Block_Dev_Unit;
- }
- else
- {
- pFTDB = &((PRPFT)pRequest)->ftdb;
- Cmd = ((PRPH)pRequest)->Cmd;
- SzReqPkt = MAXRPSIZE;
- LogDriveNum = ((PRPH)pRequest)->Unit;
- }
-
- f_Get_VolCB_Addr(LogDriveNum, (NPVOLCB FAR *) &pVolCB);
-
- pUnitCB = pVolCB->pUnitCB;
-
- if (f_FT_Request( (pVolCB->FT_PartitionNumber << 8) + Cmd, SzReqPkt,
- (PBYTE FAR *)&FT_Results, (PBYTE FAR *)&ActionCode) != 0)
- /* Handle failure case */
- { /*@V99999*/
- FT_PutDeferredQueue(pRequest); /*@V99999*/
- return; /*@V99999*/
- } /*@V99999*/
-
- if (ActionCode != ACT_PRIMARY)
- FT_Get_VolCB_Addr( (USHORT)FT_Results.SecPartNum,
- (NPVOLCB FAR *)&pSecVolCB);
-
- /* IF ACT_EITHER, do load balancing and put the request on the queue */
- /* with the least number of requests outstanding. */
-
- if (ActionCode == ACT_EITHER)
- {
- if ( (pUnitCB->NumReqsInProgress +
- pUnitCB->NumReqsWaiting) <=
- (pSecVolCB->pUnitCB->NumReqsInProgress +
- pSecVolCB->pUnitCB->NumReqsWaiting) )
-
- ActionCode = ACT_PRIMARY_FIRST;
-
- else
-
- ActionCode = ACT_SECONDARY_FIRST;
- }
-
- /* Initialize FTDB area within the original request */
-
- pFTDB->FT_Flags = FTF_FT_REQUEST;
- pFTDB->OrigRequest.RequestHandle = FT_Results.RequestHandle;
-
-
- switch (ActionCode)
- {
- case ACT_PRIMARY:
- f_PutPriorityQueue (pUnitCB, pRequest);
- *pUnitCB1 = pUnitCB;
- break;
-
- case ACT_PRIMARY_FIRST:
- pFTDB->AltLogDriveNum = pSecVolCB->LogDriveNum;
- f_PutPriorityQueue (pUnitCB, pRequest);
- *pUnitCB1 = pUnitCB;
- break;
-
- case ACT_SECONDARY:
- case ACT_SECONDARY_FIRST:
- pFTDB->AltLogDriveNum = pVolCB->LogDriveNum;
-
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- ((PRHFT)pRequest)->Block_Dev_Unit = pSecVolCB->LogDriveNum;
- else
- {
- ((PRP_RWV)pRequest)->rph.Unit = pSecVolCB->LogDriveNum;
-
- ((PRP_RWV)pRequest)->rba = ((PRP_RWV)pRequest)->rba -
- pVolCB->PartitionOffset - pVolCB->MediaBPB.HiddenSectors +
- pSecVolCB->PartitionOffset + pSecVolCB->MediaBPB.HiddenSectors;
- }
-
- f_PutPriorityQueue (pSecVolCB->pUnitCB, pRequest);
- *pUnitCB2 = pSecVolCB->pUnitCB;
- break;
-
- case ACT_BOTH:
- pFTDB->FT_Flags |= FTF_ACT_BOTH;
- pShadowReq = FT_Results.pShadowReq;
-
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- {
- pRLH = (PReq_List_Header)pRequest;
- OFFSETOF(pRLH) = OFFSETOF(pRequest) -
- (USHORT) (((PPB_Read_Write)pRequest)->RqHdr.Head_Offset);
-
- ((PReq_List_Header)pShadowReq)->Count = 1;
- ((PReq_List_Header)pShadowReq)->Request_Control = RLH_Single_Req;
- if (pRLH->Request_Control & RLH_Exe_Req_Seq)
- ((PReq_List_Header)pShadowReq)->Request_Control |= RLH_Exe_Req_Seq;
-
- ((PReq_List_Header)pShadowReq)->Lst_Status = 0;
- ((PReq_List_Header)pShadowReq)->Block_Dev_Unit =
- pSecVolCB->LogDriveNum;
- ((PReq_List_Header)pShadowReq)->y_Done_Count = 0;
- ((PReq_List_Header)pShadowReq)->y_PhysAddr=f_VirtToPhys(pShadowReq);
-
- OFFSETOF(pShadowReq) = OFFSETOF(pShadowReq)+sizeof(Req_List_Header);
- pFTDB = &((PRHFT)pShadowReq)->ftdb;
- f_BlockCopy(pShadowReq, pRequest, SzReqPkt - sizeof(Req_List_Header));
- ((PPB_Read_Write)pShadowReq)->RqHdr.Length = -1;
- ((PRHFT)pShadowReq)->Block_Dev_Unit = pSecVolCB->LogDriveNum;
- ((PPB_Read_Write)pShadowReq)->RqHdr.Head_Offset
- = sizeof(Req_List_Header);
- ((PPB_Read_Write)pShadowReq)->RqHdr.Req_Control = 0;
- ((PPB_Read_Write)pShadowReq)->RqHdr.Status = 0;
- }
- else
- {
- pFTDB = &((PRPFT)pShadowReq)->ftdb;
-
- f_BlockCopy(pShadowReq, pRequest, MAXRPSIZE);
- ((PRP_RWV)pShadowReq)->rph.Unit = pSecVolCB->LogDriveNum;
- ((PRP_RWV)pShadowReq)->rba = ((PRP_RWV)pRequest)->rba -
- pVolCB->PartitionOffset - pVolCB->MediaBPB.HiddenSectors +
- pSecVolCB->PartitionOffset + pSecVolCB->MediaBPB.HiddenSectors;
- }
- pFTDB->FT_Flags = FTF_FT_REQUEST | FTF_ACT_BOTH | FTF_SHADOW_REQUEST;
- pFTDB->pOrigRequest = pRequest;
-
- f_PutPriorityQueue (pUnitCB, pRequest);
- f_PutPriorityQueue (pSecVolCB->pUnitCB, pShadowReq);
-
- *pUnitCB1 = pUnitCB;
- *pUnitCB2 = pSecVolCB->pUnitCB;
-
- }
- }
-
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_NotifyDoneIORB_RLE - Done processing for fault tolerance requests
- ;
- ; USHORT FT_NotifyDone (NPIORB pIORB, PPB_Read_Write pRequest,
- ; PPB_Read_Write pOrigRequest)
- ;
- ; ENTRY: pIORB - pointer to completed IORB
- ; pRequest - pointer to Request List Entry
- ; pOrigRequest - return pointer to original RLE
- ;
- ; RETURN: USHORT - packet status word
- ;
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- USHORT FAR f_FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest)
-
- NPIORB pIORB;
- PPB_Read_Write pRequest;
- PPB_Read_Write FAR *pOrigRequest;
- {
- return(FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest));
- }
-
- USHORT NEAR FT_NotifyDoneIORB_RLE (pIORB, pRequest, pOrigRequest)
-
- NPIORB pIORB;
- PPB_Read_Write pRequest;
- PPB_Read_Write FAR *pOrigRequest;
- {
- USHORT DoneParm1;
- USHORT RequestHandle;
- USHORT RC;
- NPVOLCB pVolCB;
- PFTDB pFTDB;
- PBYTE pReq; /*@V99999*/
-
- pFTDB = &((PRHFT)pRequest)->ftdb;
- f_Get_VolCB_Addr ( ((PRHFT)pRequest)->Block_Dev_Unit, (NPVOLCB FAR*)&pVolCB);
- DoneParm1 = pVolCB->FT_PartitionNumber << 8;
-
- if ( (pRequest->RqHdr.Status & 0xF0) == RH_NO_ERROR)
- (UCHAR) DoneParm1 = 0xFF;
- else
- (UCHAR) DoneParm1 = pRequest->RqHdr.Error_Code;
-
- if (pFTDB->FT_Flags & FTF_SHADOW_REQUEST)
- {
- (PBYTE) *pOrigRequest = pFTDB->pOrigRequest;
- RequestHandle = ((PRHFT)(*pOrigRequest))->ftdb.OrigRequest.RequestHandle;
- }
- else
- {
- *pOrigRequest = pRequest;
- RequestHandle = pFTDB->OrigRequest.RequestHandle;
- }
-
- RC = f_FT_Done(DoneParm1, RequestHandle, pRequest->Start_Block);
-
-
- if (RC & STDON)
- {
- pRequest = *pOrigRequest;
-
- if (RC & STERR)
- {
- pRequest->RqHdr.Status = RH_UNREC_ERROR;
- pRequest->Blocks_Xferred = 0;
-
- if ( (UCHAR)RC >= I24_MIN_RECOV_ERROR )
- pRequest->RqHdr.Status = RH_RECOV_ERROR;
- pRequest->RqHdr.Error_Code = (UCHAR) RC;
- }
- else
- {
- pRequest->RqHdr.Status = RH_NO_ERROR;
- pRequest->Blocks_Xferred = pRequest->Block_Count;
- pRequest->RqHdr.Error_Code = 0;
- }
-
- /* Check to see if any requests were deferred */ /*@V99999*/
- if (NumReqsDeferred != 0) /*@V99999*/
- { /*@V99999*/
- if (FT_PullDeferredQueue( (PBYTE FAR *)&pReq) == NO_ERROR) /*@V99999*/
- FT_PutDeferredRequest(pReq); /*@V99999*/
- } /*@V99999*/
- return(STDON);
- }
-
- /* Request is not done. For mirrored writes, no further work is */
- /* needed. Just wait for the second write to complete. For reads,*/
- /* re-queue the request to the alternate unit. */
-
- if ( !(pFTDB->FT_Flags & FTF_ACT_BOTH) )
- {
- f_Get_VolCB_Addr(pFTDB->AltLogDriveNum, (NPVOLCB FAR *)&pVolCB);
- ((PRHFT)pRequest)->Block_Dev_Unit = (UCHAR) pVolCB->LogDriveNum;
- pRequest->RqHdr.Status = 0;
- f_PutPriorityQueue (pVolCB->pUnitCB, (PBYTE) pRequest);
- f_SubmitRequestsToADD(pVolCB->pUnitCB);
- }
- return(0);
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_NotifyDoneIORB_RP - Done processing for fault tolerance requests
- ;
- ; USHORT FT_NotifyDoneIORB_RP (NPIORB pIORB, PBYTE FAR *pRequest,
- ; PBYTE FAR *pOrigRequest)
- ;
- ; ENTRY: pIORB - pointer to completed IORB
- ; pRequest - pointer to Request Packet
- ; pOrigRequest - returned pointer to orig shadow RP
- ;
- ; RETURN: USHORT - packet status word
- ;
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- USHORT FAR f_FT_NotifyDoneIORB_RP (pIORB, pRequest, pOrigRequest)
-
- NPIORB pIORB;
- PRP_RWV pRequest;
- PRP_RWV FAR *pOrigRequest;
- {
- return(FT_NotifyDoneIORB_RP (pIORB, pRequest, pOrigRequest));
- }
-
- USHORT NEAR FT_NotifyDoneIORB_RP (pIORB, pRequest, pOrigRequest)
-
- NPIORB pIORB;
- PRP_RWV pRequest;
- PRP_RWV FAR *pOrigRequest;
-
- {
- USHORT DoneParm1;
- USHORT RequestHandle;
- ULONG StartBlock;
- USHORT RC;
- NPVOLCB pVolCB;
- PFTDB pFTDB;
- PBYTE pReq; /*@V99999*/
-
- pFTDB = &((PRPFT)pRequest)->ftdb;
- f_Get_VolCB_Addr(pRequest->rph.Unit, (NPVOLCB FAR *)&pVolCB);
- DoneParm1 = pVolCB->FT_PartitionNumber << 8;
-
- StartBlock = pRequest->rba - pVolCB->PartitionOffset -
- pVolCB->MediaBPB.HiddenSectors;
-
- if (pRequest->rph.Status & STERR)
- (UCHAR) DoneParm1 = (UCHAR) pRequest->rph.Status;
- else
- (UCHAR) DoneParm1 = 0xff;
-
- if (pFTDB->FT_Flags & FTF_SHADOW_REQUEST)
- {
- (PBYTE) *pOrigRequest = pFTDB->pOrigRequest;
- RequestHandle = ((PRPFT)(*pOrigRequest))->ftdb.OrigRequest.RequestHandle;
- }
- else
- {
- *pOrigRequest = pRequest;
- RequestHandle = pFTDB->OrigRequest.RequestHandle;
- }
-
- RC = f_FT_Done(DoneParm1, RequestHandle, StartBlock);
-
- if (RC & STDON)
- {
- pRequest = *pOrigRequest;
- pRequest->rph.Status = RC;
-
- if (RC & STERR)
- pRequest->NumSectors = 0;
-
- /* Check to see if any requests were deferred */ /*@V99999*/
- if (NumReqsDeferred != 0) /*@V99999*/
- { /*@V99999*/
- if (FT_PullDeferredQueue( (PBYTE FAR *)&pReq) == NO_ERROR) /*@V99999*/
- FT_PutDeferredRequest(pReq); /*@V99999*/
- } /*@V99999*/
- return(STDON);
- }
-
- /* Request is not done. For mirrored writes, no further work is */
- /* needed. Just wait for the second write to complete. For reads,*/
- /* re-queue the request to the alternate unit. */
-
- if ( !(pFTDB->FT_Flags & FTF_ACT_BOTH) )
- {
- f_Get_VolCB_Addr(pFTDB->AltLogDriveNum, (NPVOLCB FAR *)&pVolCB);
- pRequest->rph.Unit = pVolCB->LogDriveNum;
- pRequest->rba = StartBlock + pVolCB->PartitionOffset +
- pVolCB->MediaBPB.HiddenSectors;
- f_PutPriorityQueue (pVolCB->pUnitCB, (PBYTE) pRequest);
- f_SubmitRequestsToADD(pVolCB->pUnitCB);
- }
- return(0);
- }
- /*------------------------------------------------------------------------
- ;
- ;** FT_CheckFTSupport - See if request requires fault tolerance support
- ;
- ; Check to see if the request requires fault tolerance support
- ;
- ; USHORT FT_CheckFTSupport (NPUNITCB pUnitCB, PBYTE pRequest)
- ;
- ; ENTRY pUnitCB - Pointer to UnitCB
- ; pRequest - Pointer to Request Packet or Request List Entry
- ;
- ; RETURN: USHORT - YES = FT required,
- ; NO = No FT required
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- USHORT FAR f_FT_CheckFTSupport (pUnitCB, pRequest)
-
- NPUNITCB pUnitCB;
- PBYTE pRequest;
- {
- return(FT_CheckFTSupport (pUnitCB, pRequest));
- }
-
- USHORT NEAR FT_CheckFTSupport (pUnitCB, pRequest)
-
- NPUNITCB pUnitCB;
- PBYTE pRequest;
-
- {
-
- static UCHAR FTCmdTable[] =
- {
- CMDINPUT, CMDOUTPUT, CMDOUTPUTV,
- CMDInputBypass, CMDOutputBypass, CMDOutputBypassV,
- PB_READ_X, PB_WRITE_X, PB_WRITEV_X
- };
-
- UCHAR Cmd;
- USHORT i;
- PReq_List_Header pRLH;
-
- /* See if FT is enabled */
-
- if ( !(DDFlags & DDF_FT_ENABLED) )
- return(NO);
-
- /* No FT support for removable media */
-
- if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
- return(NO);
-
- /* No FT support for I/O to physical drives, i.e. 0x80, etc) */
-
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- {
- SELECTOROF(pRLH) = SELECTOROF(pRequest);
- OFFSETOF(pRLH) = OFFSETOF(pRequest) -
- (USHORT) ((PPB_Read_Write)pRequest)->RqHdr.Head_Offset;
-
- if (pRLH->Block_Dev_Unit & 0x80)
- return(NO);
-
- Cmd = ((PPB_Read_Write)pRequest)->RqHdr.Command_Code;
- }
- else
- {
- if ( ((PRPH)pRequest)->Unit & 0x80 )
- return(NO);
-
- Cmd = ((PRPH)pRequest)->Cmd;
- }
-
- /* See if it's a command which requires FT support */
-
- for (i = 0; i < sizeof(FTCmdTable); i++)
- {
- if (Cmd == FTCmdTable[i])
- return(YES);
- }
-
- return(NO);
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_Get_VolCB_Addr - Return a pointer to a VolCB for the specified Drive
- ;
- ; USHORT NEAR FT_Get_VolCB_Addr (USHORT PartNum, NPVOLCB *pVolCB)
- ;
- ; ENTRY: ParmNum - FT Partition Number
- ; pVolCB - returned pointer to VolCB
- ;
- ; RETURN: USHORT - Result Code (NO_ERROR if VolCB found)
- ;
- ; EFFECTS:
- ;
- ; NOTES:
- ------------------------------------------------------------------------*/
- USHORT FAR f_FT_Get_VolCB_Addr (PartNum, pVolCB)
-
- USHORT PartNum;
- NPVOLCB FAR *pVolCB;
- {
- return(FT_Get_VolCB_Addr (PartNum, pVolCB));
- }
-
- USHORT FT_Get_VolCB_Addr (PartNum, pVolCB)
-
- USHORT PartNum;
- NPVOLCB FAR *pVolCB;
- {
- USHORT found = FALSE;
- NPVOLCB pVolCBx;
-
- if ( !(DDFlags & DDF_NO_MEDIA) )
- {
- pVolCBx = VolCB_Head;
-
- while (pVolCBx != NULL && found == FALSE)
- {
- if (pVolCBx->FT_PartitionNumber == PartNum)
- found = TRUE;
- else
- pVolCBx = pVolCBx->pNextVolCB;
- }
- }
-
- if (found == TRUE)
- {
- *pVolCB = pVolCBx;
- return(NO_ERROR);
- }
- else
- return(ERROR);
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_LockFTCode - Lock FT Code in swap segment
- ;
- ; USHORT NEAR FT_LockFTCode (VOID)
- ;
- ; ENTRY: VOID
- ;
- ; RETURN: USHORT - Packet Status Word
- ;
- ; EFFECTS:
- ;
- ; NOTES:
- ------------------------------------------------------------------------*/
- USHORT FT_LockFTCode()
-
- {
- ULONG plFTCode; /* Linear address of Parm or Data Packet */
- ULONG plLockHandle;
- UCHAR LockHandle[12];
- ULONG PageListCount;
- USHORT Length;
- USHORT rc;
-
- (PVOID) plFTCode = (PVOID) f_FT_ExecReqList;
- rc = DevHelp_VirtToLin(SELECTOROF(plFTCode),
- (ULONG) OFFSETOF(plFTCode),
- (PVOID) &plFTCode);
-
- (PVOID) plLockHandle = (PVOID) &LockHandle;
- rc = DevHelp_VirtToLin(SELECTOROF(plLockHandle),
- (ULONG) OFFSETOF(plLockHandle),
- (PVOID) &plLockHandle);
-
- Length = (USHORT) FT_CodeSegEnd - (USHORT) f_FT_ExecReqList;
-
- if (DevHelp_VMLock(VMDHL_LONG, plFTCode, Length, -1,
- plLockHandle, (PULONG) &PageListCount) != 0)
-
- return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
-
-
- return(STDON);
-
- }
-
- /* lpq */
- /*------------------------------------------------------------------------
- ;
- ;** FT_PutDeferredQueue - Put a Request on a deferred queue.
- ;
- ; This routine places an RLE or RP on the apropriate deferred queue when
- ; the call to FT_Request fails (due to lack of resources).
- ;
- ; VOID FT_PutDeferredQueue (PBYTE pRequest)
- ;
- ; ENTRY: pRequest - Pointer to Request List Entry or Request Pkt
- ;
- ; RETURN: VOID
- ;
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- VOID FT_PutDeferredQueue (pRequest)
-
- PBYTE pRequest;
-
- {
-
- PUSHFLAGS;
- DISABLE;
-
- /* Place on Request List Entry Deferred Queue */
-
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- {
- if (DeferredQRLE.Head == 0)
- {
- DeferredQRLE.Head = pRequest;
- DeferredQRLE.Tail = pRequest;
- ((PPB_Read_Write)pRequest)->RqHdr.Waiting = 0;
- }
- else
- {
- ((PPB_Read_Write)(DeferredQRLE.Tail))->RqHdr.Waiting = (ULONG)pRequest;
- DeferredQRLE.Tail = pRequest;
- }
- }
- else
- /* Place on Request Packet Deferred Queue */
- {
- if (DeferredQRP.Head == 0)
- {
- DeferredQRP.Head = pRequest;
- DeferredQRP.Tail = pRequest;
- ((PRPH)pRequest)->Link = 0;
- }
- else
- {
- ((PRPH)(DeferredQRP.Tail))->Link = (PRPH) pRequest;
- DeferredQRP.Tail = pRequest;
- }
- }
-
- NumReqsDeferred++;
-
- ENABLE;
- POPFLAGS;
-
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_PullDeferredQueue - Pull a request from a deferred queue.
- ;
- ; This routine removes a Request List Entry, or a Request Packet from
- ; the deferred queues.
- ;
- ; USHORT FT_PullDeferredQueue (PBYTE *pReqAddr)
- ;
- ; ENTRY: pReqAddr - Returned pointer to pulled Request List
- ; Entry or Request Packet
- ;
- ; RETURN: USHORT - = 0, Request pulled
- ; <> 0, No Request pulled, queues empty
- ; EFFECTS:
- ;
- ------------------------------------------------------------------------*/
- USHORT FT_PullDeferredQueue (pReqAddr)
-
- PBYTE FAR *pReqAddr;
- {
-
- PBYTE pRequest;
-
- PUSHFLAGS;
- DISABLE;
-
-
- /* Search the Request List Deferred Queue First */
-
- if (DeferredQRLE.Head != 0)
- {
- pRequest = DeferredQRLE.Head;
- DeferredQRLE.Head = (PBYTE) ((PPB_Read_Write)pRequest)->RqHdr.Waiting;
- ((PPB_Read_Write)pRequest)->RqHdr.Waiting = 0;
- if (DeferredQRLE.Head == 0)
- DeferredQRLE.Tail = 0;
- }
-
- /* If it was empty, search the Request Packet Queue */
-
- else if (DeferredQRP.Head != 0)
- {
- pRequest = DeferredQRP.Head;
- DeferredQRP.Head = (PBYTE) (((PRPH)pRequest)->Link);
- ((PRPH)pRequest)->Link = 0;
- if (DeferredQRP.Head == 0)
- DeferredQRP.Tail = 0;
- }
- else
- return(ERROR);
-
- *pReqAddr = pRequest;
- NumReqsDeferred--;
-
- ENABLE;
- POPFLAGS;
- return(NO_ERROR);
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** FT_PutDeferredRequest - Put a deferred request on a priority queue
- ;
- ; This routine takes a request that was pulled from the deferred
- ; queue and attempts to queue it on a priority queue by calling
- ; FT_PutPriorityqueue.
- ;
- ; VOID FT_PutDeferredRequest (pRequest);
- ;
- ; ENTRY: pRequest - Pointer to Request List Entry or Request Pkt
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
-
- VOID FT_PutDeferredRequest (pRequest)
-
- PBYTE pRequest;
-
- {
- UCHAR LogDriveNum;
- NPVOLCB pVolCB;
- NPUNITCB pUnitCB1 = 0;
- NPUNITCB pUnitCB2 = 0;
-
-
- /* Get the Unit number and retrieve the Volume Control Block */
- if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
- LogDriveNum = ((PRHFT)pRequest)->Block_Dev_Unit;
- else
- LogDriveNum = ((PRPH)pRequest)->Unit;
-
- f_Get_VolCB_Addr(LogDriveNum, (NPVOLCB FAR *) &pVolCB);
-
-
- FT_PutPriorityQueue(pVolCB->pUnitCB, pRequest, (NPUNITCB FAR *) &pUnitCB1,
- (NPUNITCB FAR *) &pUnitCB2);
-
- if (pUnitCB1 != 0)
- f_SubmitRequestsToADD(pUnitCB1);
-
- if (pUnitCB2 != 0)
- f_SubmitRequestsToADD(pUnitCB2);
- }
-
- VOID FT_CodeSegEnd()
- {
- }
-