home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2DASD / DMSTRAT2.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  16.2 KB  |  541 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/dmstrat2.c, dsdm, r206, 6a.585 93/07/15";*/
  13. #define SCCSID  "src/dev/dasd/os2dasd/dmstrat2.c, dsdm, r206, 6a.585 93/07/15"
  14.  
  15. /**************************************************************************
  16.  *
  17.  * SOURCE FILE NAME = DMSTRAT2.C
  18.  *
  19.  * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
  20.  *                    Strategy 2 interface for OS/2 DASD Manager
  21.  *
  22.  *
  23.  * VERSION = V2.0
  24.  *
  25.  * DATE
  26.  *
  27.  * DESCRIPTION  Provides validation and routing of Strategy 2 requests
  28.  *              received from the OS/2 Kernel and/or Installable File
  29.  *              Systems.
  30.  *
  31.  *
  32. */
  33. #include "dmh.h"
  34. #include "dmfault.h"
  35.  
  36.  
  37. /*---------------------------------------------------*/
  38. /* Forward Function References and pragma statements */
  39. /*---------------------------------------------------*/
  40.  
  41. VOID NEAR ValidateReqList (PReq_List_Header, NPVOLCB FAR *);
  42. VOID ExecReqList (PReq_List_Header, NPUNITCB);
  43.  
  44.  
  45. /*------------------------------------------------------------------------
  46. ;
  47. ;** DMStrat2 - Strategy2 Request List Entry Point
  48. ;
  49. ;   Processes Strategy2 request lists
  50. ;
  51. ;   USHORT DMStrat2    (PReq_List_Header pRLH)
  52. ;
  53. ;   ENTRY:    pRLH             - Request List Header
  54. ;
  55. ;   RETURN:   VOID
  56. ;
  57. ------------------------------------------------------------------------*/
  58. VOID _loadds FAR DMStrat2 ()
  59.  
  60. {
  61.    PReq_List_Header pRLH;
  62.    NPVOLCB pVolCB;
  63.  
  64.    _asm { mov word ptr pRLH[0], bx };
  65.    _asm { mov word ptr pRLH[2], es };
  66.  
  67.    pRLH->Lst_Status = 0;
  68.    pRLH->y_Done_Count = 0;              /* Zero out request done count */
  69.  
  70.    /* Validate the request list */
  71.  
  72.    ValidateReqList(pRLH, (NPVOLCB FAR *) &pVolCB);
  73.  
  74.    /* If request list not aborted from validate, then execute the list */
  75.  
  76.    if ( !(pRLH->Lst_Status & RLH_All_Req_Done) )
  77.    {
  78.       if ( IsTraceOn() )
  79.          Trace(TRACE_STRAT2 | TRACE_ENTRY, pRLH, pVolCB);
  80.  
  81.       pVolCB->Flags &= ~vf_ForceRdWrt;
  82.       pRLH->y_PhysAddr = VirtToPhys((PBYTE)pRLH); /* Store phys addr of RLH */
  83.  
  84.       /* See if Fault Tolerance is enabled */
  85.  
  86.       if (DDFlags & DDF_FT_ENABLED)
  87.          f_FT_ExecReqList (pRLH, pVolCB->pUnitCB);
  88.       else
  89.          ExecReqList (pRLH, pVolCB->pUnitCB);
  90.    }
  91. }
  92.  
  93. /*------------------------------------------------------------------------
  94. ;
  95. ;** ExecReqList - Execute Strategy2 Request List
  96. ;
  97. ;   Executes Strategy2 request lists
  98. ;
  99. ;   USHORT ExecReqList    (PReq_List_Header pRLHIn, pUnitCB);
  100. ;
  101. ;   ENTRY:    pRLHIn       - Request List Header
  102. ;             pUnitCB      - Pointer to UnitCB
  103. ;
  104. ;   RETURN:   VOID
  105. ;
  106. ------------------------------------------------------------------------*/
  107. VOID ExecReqList (pRLHIn, pUnitCB)
  108.  
  109. PReq_List_Header pRLHIn;
  110. NPUNITCB pUnitCB;
  111. {
  112.    USHORT  i, Count;
  113.  
  114.    _segment ReqSeg;
  115.    Req_List_Header _based(ReqSeg) *pRLH;
  116.    PB_Read_Write _based(ReqSeg) *pRLE;
  117.  
  118.    ReqSeg = SELECTOROF(pRLHIn);
  119.  
  120.    (USHORT) pRLH = OFFSETOF(pRLHIn);
  121.    (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
  122.  
  123.    /* Loop through the list */
  124.  
  125.    Count = pRLH->Count;
  126.    for (i = 0; i < Count; i++)
  127.    {
  128.       if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
  129.       {
  130.          PutPriorityQueue_RLE (pUnitCB, pRLE);
  131.  
  132.          /* Only queue one at a time if Execute in Sequence specified */
  133.  
  134.          if (pRLH->Request_Control & RLH_Exe_Req_Seq)
  135.             break;
  136.       }
  137.       OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
  138.    }
  139.  
  140.    pRLH->Lst_Status &= ~RLH_Req_Not_Queued;
  141.    pRLH->Lst_Status |= RLH_All_Req_Queued;
  142.  
  143.    SubmitRequestsToADD(pUnitCB);
  144. }
  145.  
  146.  
  147. /*------------------------------------------------------------------------
  148. ;
  149. ;** ValidateReqList -  Validate a Strategy-2 request list
  150. ;
  151. ;   Verify the Request List Header has a valid unit number.  Verify
  152. ;   each Request List Entry has a valid command code and that the
  153. ;   I/O is within the partition boundaries.
  154. ;
  155. ;   USHORT ValidateReqList (PReq_List_Header pRLHIn, NPVOLCB *pVolCB_Addr)
  156. ;
  157. ;   ENTRY:    pRLHIn           - Request List Header
  158. ;             pVolCB_Addr      - returned pointer to VolCB
  159. ;
  160. ;   RETURN:   VOID
  161. ;
  162. ------------------------------------------------------------------------*/
  163. VOID  ValidateReqList (pRLHIn, pVolCB_Addr)
  164.  
  165. PReq_List_Header pRLHIn;
  166. NPVOLCB FAR *pVolCB_Addr;
  167.  
  168. {
  169.    USHORT  rc, i, Count;
  170.    NPVOLCB pVolCB;
  171.  
  172.    _segment ReqSeg;
  173.    Req_List_Header _based(ReqSeg) *pRLH;
  174.    PB_Read_Write _based(ReqSeg) *pRLE;
  175.  
  176.    ReqSeg = SELECTOROF(pRLHIn);
  177.    (USHORT) pRLH = OFFSETOF(pRLHIn);
  178.  
  179.    /* First validate the Request List Header.  Make sure the header    */
  180.    /* contains a valid unit number.  If the unit is for a floppy drive,*/
  181.    /* make sure the floppy disk doesnt need to be changed.             */
  182.  
  183.    rc = 0;
  184.    if (Get_VolCB_Addr(pRLH->Block_Dev_Unit, (NPVOLCB FAR *) pVolCB_Addr)
  185.             == ERROR)
  186.  
  187.       rc = STDON + STERR + ERROR_I24_BAD_UNIT;
  188.  
  189.    else
  190.    {
  191.       pVolCB = *pVolCB_Addr;
  192.  
  193.       /*--------------------------------------------------------------*/
  194.       /*  If it's for a psuedo-drive which is not currently mapped to */
  195.       /*  it's associated unit, then a disk swap is needed.           */
  196.       /*--------------------------------------------------------------*/
  197.  
  198.       if  (pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  199.       {
  200.          if (CheckPseudoChange(pRLH->Block_Dev_Unit, pVolCB) == -1)
  201.             rc = STDON + STERR + ERROR_I24_DISK_CHANGE;
  202.  
  203.          else if  ( (!(pVolCB->Flags & vf_ForceRdWrt)) &&
  204.               (pVolCB->Flags & vf_UncertainMedia) )
  205.          {
  206.             rc = STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA;
  207.          }
  208.       }
  209.    }
  210.  
  211.    /* If the Request List Header had an error, then return an error for  */
  212.    /* all entries in the list.                                           */
  213.  
  214.    if (rc & STERR)
  215.    {
  216.       pRLH->Lst_Status |= RLH_Unrec_Error;
  217.  
  218.       (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
  219.       Count = pRLH->Count;
  220.       for (i = 0; i < Count; i++)
  221.       {
  222.          pRLE->Blocks_Xferred = 0;
  223.          pRLE->RqHdr.Status = RH_UNREC_ERROR;
  224.          pRLE->RqHdr.Error_Code = (UCHAR) rc;
  225.          NotifyRLE(pRLE);
  226.          OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
  227.       }
  228.       return;
  229.    }
  230.  
  231.    /* The Request List Header is ok. Make sure each request in the  */
  232.    /* list has a valid command code and the I/O fails within the    */
  233.    /* partition boundary.                                           */
  234.  
  235.    (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
  236.    Count = pRLH->Count;
  237.  
  238.    for (i = 0; i < Count; i++)
  239.    {
  240.       rc = 0;
  241.  
  242.       /* Copy the Block_Dev_Unit from the RLH to each RLE   */
  243.       ((PRHFT)pRLE)->Block_Dev_Unit = pRLH->Block_Dev_Unit;
  244.       ((PRHFT)pRLE)->ftdb.FT_Flags = 0;
  245.  
  246.       if (pRLE->RqHdr.Command_Code == PB_READ_X ||
  247.           pRLE->RqHdr.Command_Code == PB_WRITE_X ||
  248.           pRLE->RqHdr.Command_Code == PB_WRITEV_X)
  249.         ;
  250.       else if (pRLE->RqHdr.Command_Code == PB_PREFETCH_X)
  251.       {
  252.          if ( !(pVolCB->pUnitCB->UnitInfo.UnitFlags & UF_PREFETCH) )
  253.             rc = ERROR_I24_BAD_COMMAND;
  254.       }
  255.       else
  256.          rc = ERROR_I24_BAD_COMMAND;
  257.  
  258.       if (rc == 0)
  259.       {
  260.          if (CheckWithinPartition(pVolCB, pRLE->Start_Block,
  261.                                             pRLE->Block_Count) & STERR)
  262.             rc = ERROR_I24_SECTOR_NOT_FOUND;
  263.       }
  264.  
  265.       /* If the Request List Entry had an error notify the file system */
  266.  
  267.       if (rc != 0)
  268.       {
  269.          pRLE->RqHdr.Status = RH_UNREC_ERROR;
  270.          pRLE->RqHdr.Error_Code = (UCHAR) rc;
  271.          pRLE->Blocks_Xferred = 0;
  272.          NotifyRLE(pRLE);
  273.  
  274.          /* Abort the list and return if Abort_Err specified */
  275.  
  276.          if (pRLH->Request_Control & RLH_Abort_Err)
  277.          {
  278.             AbortReqList(pRLH);
  279.             return;
  280.          }
  281.       }
  282.       OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
  283.    } /* end for */
  284. }
  285.  
  286. /*------------------------------------------------------------------------
  287. ;
  288. ;** AbortReqList -  Abort the request list
  289. ;
  290. ;   Abort the reqeust list when Abort on Error is specified.
  291. ;
  292. ;   VOID AbortReqList (PReq_List_Header pRLHIn)
  293. ;
  294. ;   ENTRY:    pRLH             - Request List Header
  295. ;
  296. ;   RETURN:   VOID
  297. ;
  298. ------------------------------------------------------------------------*/
  299. VOID AbortReqList (pRLHIn)
  300.  
  301. PReq_List_Header pRLHIn;
  302.  
  303. {
  304.    USHORT i, Count;
  305.  
  306.    _segment ReqSeg;
  307.    Req_List_Header _based(ReqSeg) *pRLH;
  308.    PB_Read_Write _based(ReqSeg) *pRLE;
  309.  
  310.    ReqSeg = SELECTOROF(pRLHIn);
  311.    (USHORT) pRLH = OFFSETOF(pRLHIn);
  312.  
  313.    pRLH->Lst_Status |= RLH_Unrec_Error;
  314.  
  315.    (USHORT) pRLE = (USHORT) pRLH + sizeof(Req_List_Header);
  316.    Count = pRLH->Count;
  317.  
  318.    for (i = 0; i < Count; i++)
  319.    {
  320.       if ( !(pRLE->RqHdr.Status & RH_DONE) )
  321.       {
  322.          pRLE->Blocks_Xferred = 0;
  323.          pRLE->RqHdr.Status |= RH_ABORTED;
  324.          pRLE->RqHdr.Error_Code = 0;
  325.          NotifyRLE(pRLE);
  326.       }
  327.       OFFSETOF(pRLE) = OFFSETOF(pRLE) + pRLE->RqHdr.Length;
  328.    }
  329. }
  330.  
  331.  
  332. /*------------------------------------------------------------------------
  333. ;
  334. ;** NotifyRLE - Notification callout for Request Lists
  335. ;
  336. ;   Perform notification callouts to the filesystem when a
  337. ;   Request List Entry is done.  Also, do the final Request List
  338. ;   notification callout when the entire list is complete.
  339. ;
  340. ;   USHORT NotifyRLE (PB_Read_Write pRLEIn)
  341. ;
  342. ;   ENTRY:    pRLEIn           - Request List Entry
  343. ;
  344. ;   RETURN:   VOID
  345. ;
  346. ------------------------------------------------------------------------*/
  347. VOID NotifyRLE (pRLEIn)
  348.  
  349. PPB_Read_Write pRLEIn;
  350.  
  351. {
  352.    _segment ReqSeg;
  353.    Req_List_Header _based(ReqSeg) *pRLH;
  354.    PB_Read_Write _based(ReqSeg) *pRLE;
  355.  
  356.    ReqSeg = SELECTOROF(pRLEIn);
  357.    (USHORT) pRLE = OFFSETOF(pRLEIn);
  358.  
  359.    /* Make sure this request is not already done */
  360.  
  361.    DISABLE;
  362.    if (pRLE->RqHdr.Status & (RH_DONE | RH_ABORTED) )
  363.    {
  364.       ENABLE;
  365.       return;
  366.    }
  367.  
  368.    /* Set the status field to RH_DONE and do notification callouts */
  369.    /* if required.                                                 */
  370.  
  371.    pRLE->RqHdr.Status |= RH_DONE;
  372.  
  373.    ENABLE;
  374.  
  375.    pRLH = (PReq_List_Header) pRLE;
  376.    OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) pRLE->RqHdr.Head_Offset;
  377.  
  378.    /* If there's an error, see if we should notify on errors */
  379.  
  380.    if ( (pRLE->RqHdr.Status & RH_RECOV_ERROR) &&
  381.         ( !(pRLH->Lst_Status & RLH_Unrec_Error) ) )
  382.       pRLH->Lst_Status |= RLH_Rec_Error;
  383.  
  384.    if (TraceFlags != 0)                                              /*@V85908*/
  385.       Trace((USHORT) (TRACE_STRAT2 | TRACE_ASYNCDONE | TRACE_RLE),   /*@V85908*/
  386.             (PBYTE)   pRLE,                                          /*@V85908*/
  387.             (NPVOLCB) 0);                                            /*@V85908*/
  388.  
  389.    if (pRLE->RqHdr.Status & RH_UNREC_ERROR)
  390.    {
  391.      /* Notify with error */
  392.  
  393.       pRLH->Lst_Status |= RLH_Unrec_Error;
  394.       if (pRLE->RqHdr.Req_Control & (RH_NOTIFY_ERROR | RH_NOTIFY_DONE) )
  395.          FSD_Notify((PBYTE)pRLE, pRLE->RqHdr.Notify_Address, 1);
  396.    }
  397.    else if (pRLE->RqHdr.Req_Control &  RH_NOTIFY_DONE)
  398.  
  399.          /* Notify with no with error */
  400.  
  401.          FSD_Notify((PBYTE)pRLE, pRLE->RqHdr.Notify_Address, 0);
  402.  
  403.    /* Increment the requests completed count in the request list header. */
  404.    /* If all the requests in the list are done, or an error occurred,    */
  405.    /* then call the list notification routine if required.               */
  406.  
  407.    pRLH->y_Done_Count ++;
  408.  
  409.    if (pRLH->y_Done_Count == pRLH->Count)
  410.    {                                                                 /*@V85908*/
  411.       pRLH->Lst_Status &= ~(RLH_Req_Not_Queued | RLH_All_Req_Queued);
  412.       pRLH->Lst_Status |= RLH_All_Req_Done;
  413.  
  414.       if (TraceFlags != 0)                                           /*@V85908*/
  415.          Trace((USHORT) (TRACE_STRAT2 | TRACE_ASYNCDONE),            /*@V85908*/
  416.                (PBYTE)   pRLH,                                       /*@V85908*/
  417.                (NPVOLCB) 0);                                         /*@V85908*/
  418.  
  419.       if (pRLH->Request_Control & RLH_Notify_Done)
  420.       {
  421.          /* List notify when done */
  422.  
  423.          FSD_Notify((PBYTE)pRLH,                                     /*@V71660*/
  424.                            pRLH->Notify_Address,
  425.                            (pRLH->Lst_Status & RLH_Unrec_Error) ? 1 : 0 );
  426.  
  427.       }
  428.       else if ( (pRLH->Lst_Status & RLH_Unrec_Error) &&              /*@V71660*/
  429.                 (pRLH->Request_Control & RLH_Notify_Err) )
  430.       {
  431.             /* List notify on error */
  432.  
  433.          FSD_Notify((PBYTE)pRLH, pRLH->Notify_Address, 1);
  434.       }
  435.    }                                                                 /*@V85908*/
  436. }
  437.  
  438.  
  439. /*------------------------------------------------------------------------
  440. ;
  441. ;** DD_ChgPriority - Change the priority of a Request List Entry
  442. ;
  443. ;   Change the priority of a Request List Entry
  444. ;
  445. ;   USHORT DD_ChgPriority   (PPB_ReadWrite pRLE, UCHAR Priority)
  446. ;
  447. ;   ENTRY:    pRLE             - Request List Entry
  448. ;             Priority         - Priority
  449. ;
  450. ;   RETURN:   USHORT           - Return Code
  451. ;                                  0 = No error, priority changed
  452. ;                                  1 = Error, priority not changed since
  453. ;                                      request no longer on queue
  454. ; ------------------------------------------------------------------------*/
  455. USHORT  DD_ChgPriority (pRLE, Priority)
  456.  
  457. PPB_Read_Write pRLE;
  458. UCHAR  Priority;
  459.  
  460. {
  461.    USHORT rc;
  462.    PReq_List_Header pRLH;
  463.    NPVOLCB pVolCB;
  464.  
  465.    /* If same priority as before then no need to change */
  466.  
  467.    if (pRLE->RqHdr.Priority == Priority)
  468.       rc = 0;
  469.    else if (pRLE->RqHdr.Status == RH_NOT_QUEUED)
  470.    {
  471.       pRLE->RqHdr.Priority = Priority;
  472.       rc = 0;
  473.    }
  474.    else if (pRLE->RqHdr.Status != RH_QUEUED)
  475.       rc = 1;
  476.  
  477.    else   /* Request is already queued.  Move to new Priority queue. */
  478.    {
  479.       pRLH = (PReq_List_Header) pRLE;
  480.       OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) pRLE->RqHdr.Head_Offset;
  481.       Get_VolCB_Addr(pRLH->Block_Dev_Unit, (NPVOLCB FAR *)&pVolCB);
  482.       if (RemovePriorityQueue(pVolCB->pUnitCB, pRLE) == NO_ERROR)
  483.       {
  484.          pRLE->RqHdr.Priority = Priority;
  485.          PutPriorityQueue_RLE (pVolCB->pUnitCB, pRLE);
  486.          rc = 0;
  487.       }
  488.       else
  489.          rc = 1;
  490.    }
  491.  
  492.    return(rc);
  493. }
  494.  
  495. /*------------------------------------------------------------------------
  496. ;
  497. ;** DD_SetFSDInfo - Set FSD callout addresses.
  498. ;
  499. ;   Entry point for FSD to inform us of it's FSD_EndofInt and
  500. ;   FSD_AccValidate entry points.
  501. ;
  502. ;   USHORT DD_SetFSDInfo  (PSet_FSD_Info pFSDInfo)
  503. ;
  504. ;   ENTRY:    pFSDInfo         - FSD info structure
  505. ;
  506. ;   RETURN:   USHORT           - Return Code
  507. ;                                  0 = No error, FSD info changed
  508. ;                                  1 = Error, FSD info not changed
  509. ; ------------------------------------------------------------------------*/
  510. USHORT _loadds FAR DD_SetFSDInfo ()
  511.  
  512. {
  513.    FSDInfo FAR *pFSDInfo;
  514.    USHORT rc;
  515.  
  516.    _asm { mov word ptr pFSDInfo[0], bx };
  517.    _asm { mov word ptr pFSDInfo[2], es };
  518.  
  519.    /* Can only set FSDInfo callout addresses once. */
  520.  
  521.    if (pFSD_EndofInt != 0 || pFSD_AccValidate != 0)
  522.    {
  523.       rc = 1;
  524.       _asm {stc};
  525.    }
  526.    else
  527.    {
  528.       pFSD_EndofInt = pFSDInfo->FSD_EndofInt;
  529.       pFSD_AccValidate = pFSDInfo->FSD_AccValidate;
  530.       rc = 0;
  531.       _asm {clc};
  532.    }
  533.  
  534.    return(rc);
  535. }
  536.  
  537.  
  538.  
  539.  
  540.  
  541.