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/dmstrat2.c, dsdm, r206, 6a.585 93/07/15";*/
- #define SCCSID "src/dev/dasd/os2dasd/dmstrat2.c, dsdm, r206, 6a.585 93/07/15"
-
- /**************************************************************************
- *
- * SOURCE FILE NAME = DMSTRAT2.C
- *
- * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
- * Strategy 2 interface for OS/2 DASD Manager
- *
- *
- * VERSION = V2.0
- *
- * DATE
- *
- * DESCRIPTION Provides validation and routing of Strategy 2 requests
- * received from the OS/2 Kernel and/or Installable File
- * Systems.
- *
- *
- */
- #include "dmh.h"
- #include "dmfault.h"
-
-
- /*---------------------------------------------------*/
- /* Forward Function References and pragma statements */
- /*---------------------------------------------------*/
-
- VOID NEAR ValidateReqList (PReq_List_Header, NPVOLCB FAR *);
- VOID ExecReqList (PReq_List_Header, NPUNITCB);
-
-
- /*------------------------------------------------------------------------
- ;
- ;** DMStrat2 - Strategy2 Request List Entry Point
- ;
- ; Processes Strategy2 request lists
- ;
- ; USHORT DMStrat2 (PReq_List_Header pRLH)
- ;
- ; ENTRY: pRLH - Request List Header
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID _loadds FAR DMStrat2 ()
-
- {
- PReq_List_Header pRLH;
- NPVOLCB pVolCB;
-
- _asm { mov word ptr pRLH[0], bx };
- _asm { mov word ptr pRLH[2], es };
-
- pRLH->Lst_Status = 0;
- pRLH->y_Done_Count = 0; /* Zero out request done count */
-
- /* Validate the request list */
-
- ValidateReqList(pRLH, (NPVOLCB FAR *) &pVolCB);
-
- /* If request list not aborted from validate, then execute the list */
-
- if ( !(pRLH->Lst_Status & RLH_All_Req_Done) )
- {
- if ( IsTraceOn() )
- Trace(TRACE_STRAT2 | TRACE_ENTRY, pRLH, pVolCB);
-
- pVolCB->Flags &= ~vf_ForceRdWrt;
- pRLH->y_PhysAddr = VirtToPhys((PBYTE)pRLH); /* Store phys addr of RLH */
-
- /* See if Fault Tolerance is enabled */
-
- if (DDFlags & DDF_FT_ENABLED)
- f_FT_ExecReqList (pRLH, pVolCB->pUnitCB);
- else
- ExecReqList (pRLH, pVolCB->pUnitCB);
- }
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** ExecReqList - Execute Strategy2 Request List
- ;
- ; Executes Strategy2 request lists
- ;
- ; USHORT ExecReqList (PReq_List_Header pRLHIn, pUnitCB);
- ;
- ; ENTRY: pRLHIn - Request List Header
- ; pUnitCB - Pointer to UnitCB
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID ExecReqList (pRLHIn, pUnitCB)
-
- PReq_List_Header pRLHIn;
- NPUNITCB pUnitCB;
- {
- USHORT i, Count;
-
- _segment ReqSeg;
- Req_List_Header _based(ReqSeg) *pRLH;
- PB_Read_Write _based(ReqSeg) *pRLE;
-
- ReqSeg = SELECTOROF(pRLHIn);
-
- (USHORT) pRLH = OFFSETOF(pRLHIn);
- (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
-
- /* Loop through the list */
-
- Count = pRLH->Count;
- for (i = 0; i < Count; i++)
- {
- if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
- {
- PutPriorityQueue_RLE (pUnitCB, pRLE);
-
- /* 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;
-
- SubmitRequestsToADD(pUnitCB);
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** ValidateReqList - Validate a Strategy-2 request list
- ;
- ; Verify the Request List Header has a valid unit number. Verify
- ; each Request List Entry has a valid command code and that the
- ; I/O is within the partition boundaries.
- ;
- ; USHORT ValidateReqList (PReq_List_Header pRLHIn, NPVOLCB *pVolCB_Addr)
- ;
- ; ENTRY: pRLHIn - Request List Header
- ; pVolCB_Addr - returned pointer to VolCB
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID ValidateReqList (pRLHIn, pVolCB_Addr)
-
- PReq_List_Header pRLHIn;
- NPVOLCB FAR *pVolCB_Addr;
-
- {
- USHORT rc, i, Count;
- NPVOLCB pVolCB;
-
- _segment ReqSeg;
- Req_List_Header _based(ReqSeg) *pRLH;
- PB_Read_Write _based(ReqSeg) *pRLE;
-
- ReqSeg = SELECTOROF(pRLHIn);
- (USHORT) pRLH = OFFSETOF(pRLHIn);
-
- /* First validate the Request List Header. Make sure the header */
- /* contains a valid unit number. If the unit is for a floppy drive,*/
- /* make sure the floppy disk doesnt need to be changed. */
-
- rc = 0;
- if (Get_VolCB_Addr(pRLH->Block_Dev_Unit, (NPVOLCB FAR *) pVolCB_Addr)
- == ERROR)
-
- rc = STDON + STERR + ERROR_I24_BAD_UNIT;
-
- else
- {
- pVolCB = *pVolCB_Addr;
-
- /*--------------------------------------------------------------*/
- /* If it's for a psuedo-drive which is not currently mapped to */
- /* it's associated unit, then a disk swap is needed. */
- /*--------------------------------------------------------------*/
-
- if (pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
- {
- if (CheckPseudoChange(pRLH->Block_Dev_Unit, pVolCB) == -1)
- rc = STDON + STERR + ERROR_I24_DISK_CHANGE;
-
- else if ( (!(pVolCB->Flags & vf_ForceRdWrt)) &&
- (pVolCB->Flags & vf_UncertainMedia) )
- {
- rc = STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA;
- }
- }
- }
-
- /* If the Request List Header had an error, then return an error for */
- /* all entries in the list. */
-
- if (rc & STERR)
- {
- pRLH->Lst_Status |= RLH_Unrec_Error;
-
- (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
- Count = pRLH->Count;
- for (i = 0; i < Count; i++)
- {
- pRLE->Blocks_Xferred = 0;
- pRLE->RqHdr.Status = RH_UNREC_ERROR;
- pRLE->RqHdr.Error_Code = (UCHAR) rc;
- NotifyRLE(pRLE);
- OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
- }
- return;
- }
-
- /* The Request List Header is ok. Make sure each request in the */
- /* list has a valid command code and the I/O fails within the */
- /* partition boundary. */
-
- (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
- Count = pRLH->Count;
-
- for (i = 0; i < Count; i++)
- {
- rc = 0;
-
- /* Copy the Block_Dev_Unit from the RLH to each RLE */
- ((PRHFT)pRLE)->Block_Dev_Unit = pRLH->Block_Dev_Unit;
- ((PRHFT)pRLE)->ftdb.FT_Flags = 0;
-
- if (pRLE->RqHdr.Command_Code == PB_READ_X ||
- pRLE->RqHdr.Command_Code == PB_WRITE_X ||
- pRLE->RqHdr.Command_Code == PB_WRITEV_X)
- ;
- else if (pRLE->RqHdr.Command_Code == PB_PREFETCH_X)
- {
- if ( !(pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_PREFETCH) )
- rc = ERROR_I24_BAD_COMMAND;
- }
- else
- rc = ERROR_I24_BAD_COMMAND;
-
- if (rc == 0)
- {
- if (CheckWithinPartition(pVolCB, pRLE->Start_Block,
- pRLE->Block_Count) & STERR)
- rc = ERROR_I24_SECTOR_NOT_FOUND;
- }
-
- /* If the Request List Entry had an error notify the file system */
-
- if (rc != 0)
- {
- pRLE->RqHdr.Status = RH_UNREC_ERROR;
- pRLE->RqHdr.Error_Code = (UCHAR) rc;
- pRLE->Blocks_Xferred = 0;
- NotifyRLE(pRLE);
-
- /* Abort the list and return if Abort_Err specified */
-
- if (pRLH->Request_Control & RLH_Abort_Err)
- {
- AbortReqList(pRLH);
- return;
- }
- }
- OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
- } /* end for */
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** AbortReqList - Abort the request list
- ;
- ; Abort the reqeust list when Abort on Error is specified.
- ;
- ; VOID AbortReqList (PReq_List_Header pRLHIn)
- ;
- ; ENTRY: pRLH - Request List Header
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID AbortReqList (pRLHIn)
-
- PReq_List_Header pRLHIn;
-
- {
- USHORT i, Count;
-
- _segment ReqSeg;
- Req_List_Header _based(ReqSeg) *pRLH;
- PB_Read_Write _based(ReqSeg) *pRLE;
-
- ReqSeg = SELECTOROF(pRLHIn);
- (USHORT) pRLH = OFFSETOF(pRLHIn);
-
- pRLH->Lst_Status |= RLH_Unrec_Error;
-
- (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
- Count = pRLH->Count;
-
- for (i = 0; i < Count; i++)
- {
- if ( !(pRLE->RqHdr.Status & RH_DONE) )
- {
- pRLE->Blocks_Xferred = 0;
- pRLE->RqHdr.Status |= RH_ABORTED;
- pRLE->RqHdr.Error_Code = 0;
- NotifyRLE(pRLE);
- }
- OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
- }
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** NotifyRLE - Notification callout for Request Lists
- ;
- ; Perform notification callouts to the filesystem when a
- ; Request List Entry is done. Also, do the final Request List
- ; notification callout when the entire list is complete.
- ;
- ; USHORT NotifyRLE (PB_Read_Write pRLEIn)
- ;
- ; ENTRY: pRLEIn - Request List Entry
- ;
- ; RETURN: VOID
- ;
- ------------------------------------------------------------------------*/
- VOID NotifyRLE (pRLEIn)
-
- PPB_Read_Write pRLEIn;
-
- {
- _segment ReqSeg;
- Req_List_Header _based(ReqSeg) *pRLH;
- PB_Read_Write _based(ReqSeg) *pRLE;
-
- ReqSeg = SELECTOROF(pRLEIn);
- (USHORT) pRLE = OFFSETOF(pRLEIn);
-
- /* Make sure this request is not already done */
-
- DISABLE;
- if (pRLE->RqHdr.Status & (RH_DONE | RH_ABORTED) )
- {
- ENABLE;
- return;
- }
-
- /* Set the status field to RH_DONE and do notification callouts */
- /* if required. */
-
- pRLE->RqHdr.Status |= RH_DONE;
-
- ENABLE;
-
- pRLH = (PReq_List_Header) pRLE;
- OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) pRLE->RqHdr.Head_Offset;
-
- /* If there's an error, see if we should notify on errors */
-
- if ( (pRLE->RqHdr.Status & RH_RECOV_ERROR) &&
- ( !(pRLH->Lst_Status & RLH_Unrec_Error) ) )
- pRLH->Lst_Status |= RLH_Rec_Error;
-
- if (TraceFlags != 0) /*@V85908*/
- Trace((USHORT) (TRACE_STRAT2 | TRACE_ASYNCDONE | TRACE_RLE), /*@V85908*/
- (PBYTE) pRLE, /*@V85908*/
- (NPVOLCB) 0); /*@V85908*/
-
- if (pRLE->RqHdr.Status & RH_UNREC_ERROR)
- {
- /* Notify with error */
-
- pRLH->Lst_Status |= RLH_Unrec_Error;
- if (pRLE->RqHdr.Req_Control & (RH_NOTIFY_ERROR | RH_NOTIFY_DONE) )
- FSD_Notify((PBYTE)pRLE, pRLE->RqHdr.Notify_Address, 1);
- }
- else if (pRLE->RqHdr.Req_Control & RH_NOTIFY_DONE)
-
- /* Notify with no with error */
-
- FSD_Notify((PBYTE)pRLE, pRLE->RqHdr.Notify_Address, 0);
-
- /* Increment the requests completed count in the request list header. */
- /* If all the requests in the list are done, or an error occurred, */
- /* then call the list notification routine if required. */
-
- pRLH->y_Done_Count ++;
-
- if (pRLH->y_Done_Count == pRLH->Count)
- { /*@V85908*/
- pRLH->Lst_Status &= ~(RLH_Req_Not_Queued | RLH_All_Req_Queued);
- pRLH->Lst_Status |= RLH_All_Req_Done;
-
- if (TraceFlags != 0) /*@V85908*/
- Trace((USHORT) (TRACE_STRAT2 | TRACE_ASYNCDONE), /*@V85908*/
- (PBYTE) pRLH, /*@V85908*/
- (NPVOLCB) 0); /*@V85908*/
-
- if (pRLH->Request_Control & RLH_Notify_Done)
- {
- /* List notify when done */
-
- FSD_Notify((PBYTE)pRLH, /*@V71660*/
- pRLH->Notify_Address,
- (pRLH->Lst_Status & RLH_Unrec_Error) ? 1 : 0 );
-
- }
- else if ( (pRLH->Lst_Status & RLH_Unrec_Error) && /*@V71660*/
- (pRLH->Request_Control & RLH_Notify_Err) )
- {
- /* List notify on error */
-
- FSD_Notify((PBYTE)pRLH, pRLH->Notify_Address, 1);
- }
- } /*@V85908*/
- }
-
-
- /*------------------------------------------------------------------------
- ;
- ;** DD_ChgPriority - Change the priority of a Request List Entry
- ;
- ; Change the priority of a Request List Entry
- ;
- ; USHORT DD_ChgPriority (PPB_ReadWrite pRLE, UCHAR Priority)
- ;
- ; ENTRY: pRLE - Request List Entry
- ; Priority - Priority
- ;
- ; RETURN: USHORT - Return Code
- ; 0 = No error, priority changed
- ; 1 = Error, priority not changed since
- ; request no longer on queue
- ; ------------------------------------------------------------------------*/
- USHORT DD_ChgPriority (pRLE, Priority)
-
- PPB_Read_Write pRLE;
- UCHAR Priority;
-
- {
- USHORT rc;
- PReq_List_Header pRLH;
- NPVOLCB pVolCB;
-
- /* If same priority as before then no need to change */
-
- if (pRLE->RqHdr.Priority == Priority)
- rc = 0;
- else if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
- {
- pRLE->RqHdr.Priority = Priority;
- rc = 0;
- }
- else if (pRLE->RqHdr.Status != RH_QUEUED)
- rc = 1;
-
- else /* Request is already queued. Move to new Priority queue. */
- {
- pRLH = (PReq_List_Header) pRLE;
- OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) pRLE->RqHdr.Head_Offset;
- Get_VolCB_Addr(pRLH->Block_Dev_Unit, (NPVOLCB FAR *)&pVolCB);
- if (RemovePriorityQueue(pVolCB->pUnitCB, pRLE) == NO_ERROR)
- {
- pRLE->RqHdr.Priority = Priority;
- PutPriorityQueue_RLE (pVolCB->pUnitCB, pRLE);
- rc = 0;
- }
- else
- rc = 1;
- }
-
- return(rc);
- }
-
- /*------------------------------------------------------------------------
- ;
- ;** DD_SetFSDInfo - Set FSD callout addresses.
- ;
- ; Entry point for FSD to inform us of it's FSD_EndofInt and
- ; FSD_AccValidate entry points.
- ;
- ; USHORT DD_SetFSDInfo (PSet_FSD_Info pFSDInfo)
- ;
- ; ENTRY: pFSDInfo - FSD info structure
- ;
- ; RETURN: USHORT - Return Code
- ; 0 = No error, FSD info changed
- ; 1 = Error, FSD info not changed
- ; ------------------------------------------------------------------------*/
- USHORT _loadds FAR DD_SetFSDInfo ()
-
- {
- FSDInfo FAR *pFSDInfo;
- USHORT rc;
-
- _asm { mov word ptr pFSDInfo[0], bx };
- _asm { mov word ptr pFSDInfo[2], es };
-
- /* Can only set FSDInfo callout addresses once. */
-
- if (pFSD_EndofInt != 0 || pFSD_AccValidate != 0)
- {
- rc = 1;
- _asm {stc};
- }
- else
- {
- pFSD_EndofInt = pFSDInfo->FSD_EndofInt;
- pFSD_AccValidate = pFSDInfo->FSD_AccValidate;
- rc = 0;
- _asm {clc};
- }
-
- return(rc);
- }
-
-
-
-
-
-