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

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /*static char *SCCSID = "%w% %e%";*/
  13. #define SCCSID  "%w% %e%"
  14.  
  15. /**************************************************************************
  16.  *
  17.  * SOURCE FILE NAME = DMQUEUE.C
  18.  *
  19.  * DESCRIPTIVE NAME = OS2DASD.DMD - OS/2 DASD Device Manager
  20.  *                    Request sorting/queuing routines for OS/2 DASD Mgr
  21.  *
  22.  *
  23.  * VERSION = V2.0
  24.  *
  25.  * DATE
  26.  *
  27.  * DESCRIPTION     Maintains sorted queues of Strategy 1/2 requests from
  28.  *                 the OS/2 kernel and Installable File Systems (IFS)
  29.  *                 that are awaiting processing. Also provides routing of
  30.  *                 IORBs to Adapter Device Drivers.
  31.  *
  32.  *
  33.  *
  34. */
  35. #include "dmh.h"
  36. #include "dmfault.h"
  37.  
  38. USHORT NotifyDoneIORB_RLE (NPIORB, PPB_Read_Write, NPUNITCB);
  39. VOID NotifyDoneIORB_RP (NPIORB, PBYTE, NPUNITCB);
  40. VOID CallADD (NPUNITCB, NPIORB);
  41.  
  42. /*------------------------------------------------------------------------
  43. ;
  44. ;** PutPriorityQueue - Put a Request List Entry or RP on a priority queue
  45. ;
  46. ;   Put a RLE or a RP on one of the priority queues in
  47. ;   the Unit Control Block for the specified unit.
  48. ;
  49. ;   VOID PutPriorityQueue  (NPUNITCB pUnitCB, PBYTE pReq)
  50. ;
  51. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  52. ;             pReq             - Pointer to Request Packet or Request List Entry
  53. ;
  54. ;   RETURN:   VOID
  55. ;
  56. ;   EFFECTS:
  57. ;
  58. ------------------------------------------------------------------------*/
  59. VOID FAR f_PutPriorityQueue (pUnitCB, pReq)
  60.  
  61. NPUNITCB pUnitCB;
  62. PBYTE    pReq;
  63. {
  64.    PutPriorityQueue(pUnitCB, pReq);
  65. }
  66.  
  67. VOID NEAR PutPriorityQueue (pUnitCB, pReq)
  68.  
  69. NPUNITCB pUnitCB;
  70. PBYTE    pReq;
  71. {
  72.    if ( ((PRPH)pReq)->Cmd == PB_REQ_LIST)
  73.        PutPriorityQueue_RLE (pUnitCB, (PPB_Read_Write) pReq);
  74.    else
  75.        PutPriorityQueue_RP (pUnitCB, pReq);
  76. }
  77.  
  78. /*------------------------------------------------------------------------
  79. ;
  80. ;** PutPriorityQueue_RLE - Put a Request List Entry on a priority queue.
  81. ;
  82. ;   Put a Request List Entry on one of the priority queues in
  83. ;   the Unit Control Block for the specified unit.
  84. ;
  85. ;   VOID PutPriorityQueue_RLE  (NPUNITCB pUnitCB, PPB_Read_Write pRLE)
  86. ;
  87. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  88. ;             pRLE             - Pointer to Request List Entry
  89. ;
  90. ;   RETURN:   VOID
  91. ;
  92. ;   EFFECTS:
  93. ;
  94. ------------------------------------------------------------------------*/
  95. VOID FAR f_PutPriorityQueue_RLE (pUnitCB, pRLE)
  96.  
  97. NPUNITCB pUnitCB;
  98. PPB_Read_Write  pRLE;
  99.  
  100. {
  101.    PutPriorityQueue_RLE (pUnitCB, pRLE);
  102. }
  103.  
  104.  
  105. VOID PutPriorityQueue_RLE (pUnitCB, pRLE)
  106.  
  107. NPUNITCB pUnitCB;
  108. PPB_Read_Write  pRLE;
  109.  
  110. {
  111.    PRTYQ *pPrtyQ;
  112.  
  113.    PUSHFLAGS;
  114.    DISABLE;
  115.  
  116.    /* For request list entries, put on a priority queue based on the   */
  117.    /* priority value in the request list entry.                        */
  118.  
  119.    if (pRLE->RqHdr.Status != RH_NOT_QUEUED)
  120.      goto PutRLE_Ret;
  121.  
  122.    pRLE->RqHdr.Status = RH_QUEUED;
  123.    pRLE->RqHdr.Waiting = 0;
  124.  
  125.    pPrtyQ =
  126.         (PRTYQ *) (&(pUnitCB->PrtyQRLE[GetPrtyQIndex(pUnitCB, pRLE->RqHdr.Priority)])); /*@V74404*/
  127.  
  128.    /* If the queue is empty then stick the request at the head */
  129.  
  130.    if (pPrtyQ->Head == 0)
  131.    {
  132.       pPrtyQ->Head = (PBYTE) pRLE;
  133.       pPrtyQ->Tail = (PBYTE) pRLE;
  134.    }
  135.    else
  136.    {
  137.  
  138.       if (pUnitCB->SortMethod == SORT_METHOD_FIFO)                   /*@V74404*/
  139.       {
  140.          /* Put request at end of queue */
  141.  
  142.          ((PPB_Read_Write)(pPrtyQ->Tail))->RqHdr.Waiting = (ULONG) pRLE;
  143.          pPrtyQ->Tail = (PBYTE) pRLE;
  144.       }
  145.       else
  146.       {
  147.          /* Sort on queue via an elevator algorithm */
  148.  
  149.          SortPriorityQueue (pPrtyQ, (PBYTE) pRLE);
  150.       }
  151.    }
  152.  
  153.    pUnitCB->NumReqsWaiting++;
  154.    NumReqsWaiting++;
  155.  
  156.    ENABLE;
  157.  
  158. PutRLE_Ret:
  159.    POPFLAGS;
  160.  
  161. }
  162.  
  163. /*------------------------------------------------------------------------
  164. ;
  165. ;** PutPriorityQueue_RP - Put a request packet on a priority queue.
  166. ;
  167. ;   Put a Request Packet on one of the priority queues in the
  168. ;   Unit Control Block for the specified unit.
  169. ;
  170. ;   VOID PutPriorityQueue_RP  (NPUNITCB pUnitCB, PBYTE pReq)
  171. ;
  172. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  173. ;             pReq             - Pointer to Request Packet
  174. ;
  175. ;   RETURN:   VOID
  176. ;
  177. ;   EFFECTS:
  178. ;
  179. ------------------------------------------------------------------------*/
  180. VOID PutPriorityQueue_RP (pUnitCB, pReq)
  181.  
  182. NPUNITCB pUnitCB;
  183. PBYTE    pReq;
  184.  
  185. {
  186.    PRTYQ *pPrtyQ;
  187.  
  188.    PUSHFLAGS;
  189.    DISABLE;
  190.  
  191.    /* Put a request packet on the priority queue for request packets.    */
  192.    /* The first request packet priority queue is for read/writes/verifys */
  193.    /* which may require elevator sorting.  The second request packet     */
  194.    /* queue is for requests that should not be elevator sorted, i.e.     */
  195.    /* "Get Media Sense", etc.                                            */
  196.  
  197.    ((PRPH)pReq)->Link = 0;
  198.  
  199.    if ( ((PRPH)pReq)->Cmd != CMDInternal)
  200.       pPrtyQ = &(pUnitCB->PrtyQRP[0]);
  201.    else
  202.    {
  203.       if (((PRP_INTERNAL)pReq)->Function == DISKOP_READ_VERIFY)
  204.          pPrtyQ = &(pUnitCB->PrtyQRP[0]);
  205.       else
  206.          pPrtyQ = &(pUnitCB->PrtyQRP[1]);
  207.    }
  208.  
  209.    /* If the queue is empty then stick request at the head */
  210.  
  211.    if (pPrtyQ->Head == 0)
  212.    {
  213.       pPrtyQ->Head = pReq;
  214.       pPrtyQ->Tail = pReq;
  215.    }
  216.    else
  217.    {
  218.       /* Either sort the request or put at end of queue */
  219.  
  220.       if ( (pPrtyQ == &(pUnitCB->PrtyQRP[1])) ||
  221.            (pUnitCB->SortMethod == SORT_METHOD_FIFO) )               /*@V74404*/
  222.       {
  223.          /* Put request at end of queue */
  224.  
  225.          ((PRPH)(pPrtyQ->Tail))->Link = (PRPH) pReq;
  226.          pPrtyQ->Tail = pReq;
  227.       }
  228.       else
  229.       {
  230.          /* Sort on queue via an elevator algorithm */
  231.  
  232.          SortPriorityQueue (pPrtyQ, pReq);
  233.       }
  234.    }
  235.  
  236.    pUnitCB->NumReqsWaiting++;
  237.    NumReqsWaiting++;
  238.  
  239.    ENABLE;
  240.    POPFLAGS;
  241.  
  242. }
  243.  
  244. /*------------------------------------------------------------------------
  245. ;
  246. ;** PullPriorityQueue - Pull a request from a priority queue.
  247. ;
  248. ;   Pull the highest priority request from the priority queues
  249. ;   for the specified unit.  The request returned can either be
  250. ;   a request packet of a request list entry.
  251. ;
  252. ;   USHORT PullPriorityQueue  (NPUNITCB pUnitCB, PBYTE *pReqAddr)
  253. ;
  254. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  255. ;             pReqAddr         - returned pointer to Request Packet or
  256. ;                                Request List entry
  257. ;
  258. ;   RETURN:   USHORT           - = 0, Request pulled
  259. ;                                <> 0, No request pulled, queues empty
  260. ;
  261. ;   EFFECTS:
  262. ;
  263. ------------------------------------------------------------------------*/
  264. USHORT PullPriorityQueue (pUnitCB, pReqAddr)
  265.  
  266. NPUNITCB pUnitCB;
  267. PBYTE    FAR *pReqAddr;
  268.  
  269. {
  270.    USHORT i, j, rc;
  271.    PBYTE  pReq;
  272.    USHORT PullRequest = 0;
  273.  
  274.    /* Priority queues are ordered with the highest priority queue as the */
  275.    /* first queue in the array.  The request packet queues are searched  */
  276.    /* after the PRIO_FOREGROUND priority queue for request list entries  */
  277.  
  278.    PUSHFLAGS;
  279.    DISABLE;
  280.  
  281.    /* Make sure there's a request waiting to be processed before  */
  282.    /* searching the queues.                                       */
  283.  
  284.    if (pUnitCB->NumReqsWaiting == 0)
  285.    {
  286.       rc = ERROR;
  287.       goto PullRet;
  288.    }
  289.  
  290.    /* Search the Request List Priority Queues First  */
  291.  
  292.    for (i = 0; i < NUM_RLE_QUEUES; i++)
  293.    {
  294.       if (pUnitCB->PrtyQRLE[i].Head != 0)
  295.       {
  296.          PullRequest = 1;
  297.          break;
  298.       }
  299.    }
  300.  
  301.    /* If not found, or priority queue above 4 (Foreground I/O) found, */
  302.    /* then search the request packet queues.                          */
  303.  
  304.    if (i > 4)
  305.    {
  306.       for (j = 0; j < NUM_RP_QUEUES; j++)
  307.       {
  308.          if (pUnitCB->PrtyQRP[j].Head != 0)
  309.          {
  310.            PullRequest = 2;
  311.            break;
  312.          }
  313.       }
  314.    }
  315.  
  316.    /* If PullRequest == 1, then pull a request list entry from the queue */
  317.  
  318.    if (PullRequest == 1)
  319.    {
  320.       pReq = pUnitCB->PrtyQRLE[i].Head;
  321.       (ULONG) pUnitCB->PrtyQRLE[i].Head=((PPB_Read_Write)pReq)->RqHdr.Waiting;
  322.       ((PPB_Read_Write)pReq)->RqHdr.Waiting = 0;
  323.       if (pUnitCB->PrtyQRLE[i].Head == 0)
  324.          pUnitCB->PrtyQRLE[i].Tail = 0;
  325.    }
  326.  
  327.    /* If PullRequest = 2, then pull a request packet entry from the queue */
  328.  
  329.    else if (PullRequest == 2)
  330.    {
  331.       pReq = pUnitCB->PrtyQRP[j].Head;
  332.       pUnitCB->PrtyQRP[j].Head = (PBYTE) (((PRPH)pReq)->Link);
  333.       ((PRPH)pReq)->Link = 0;
  334.       if (pUnitCB->PrtyQRP[j].Head == 0)
  335.          pUnitCB->PrtyQRP[j].Tail = 0;
  336.    }
  337.  
  338.    /* If request pulled, then return address of request, else return error */
  339.  
  340.    if (PullRequest != 0)
  341.    {
  342.       *pReqAddr = pReq;
  343.       pUnitCB->NumReqsWaiting--;
  344.       NumReqsWaiting--;
  345.       rc = NO_ERROR;
  346.    }
  347.    else
  348.       rc = ERROR;
  349.  
  350. PullRet:
  351.    POPFLAGS;
  352.    return(rc);
  353. }
  354.  
  355. /*------------------------------------------------------------------------
  356. ;
  357. ;** RemovePriorityQueue - Remove an entry from a priority queue.
  358. ;
  359. ;   This routine removes a specific Request List entry from one of
  360. ;   the priority queues.
  361. ;
  362. ;   USHORT RemovePriorityQueue  (NPUNITCB pUnitCB, PPB_Read_Write pRLE)
  363. ;
  364. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  365. ;             pRLE             - Request List Entry
  366. ;
  367. ;   RETURN:   USHORT           - = 0, Request removed
  368. ;                                <> 0, No request removed, entry not found
  369. ;
  370. ;   EFFECTS:
  371. ;
  372. ------------------------------------------------------------------------*/
  373. USHORT RemovePriorityQueue (pUnitCB, pRLE)
  374.  
  375. NPUNITCB pUnitCB;
  376. PPB_Read_Write  pRLE;
  377.  
  378. {
  379.    PPB_Read_Write  pCurReq, pPrevReq;
  380.    USHORT PrtyQIndex, rc;
  381.    USHORT Removed = NO;
  382.  
  383.    /* First make sure the entry is queued and the queue is not empty */
  384.  
  385.    PUSHFLAGS;
  386.    DISABLE;
  387.  
  388.    if (pRLE->RqHdr.Status & RH_QUEUED)
  389.    {
  390.       PrtyQIndex = GetPrtyQIndex(pUnitCB,pRLE->RqHdr.Priority);      /*@V74404*/
  391.  
  392.       if (pUnitCB->PrtyQRLE[PrtyQIndex].Head != 0)
  393.       {
  394.          /* See if entry is at the head of the queue */
  395.  
  396.          if (pUnitCB->PrtyQRLE[PrtyQIndex].Head = (PBYTE) pRLE)
  397.          {
  398.             pUnitCB->PrtyQRLE[PrtyQIndex].Head = (PBYTE) pRLE->RqHdr.Waiting;
  399.             if (pRLE->RqHdr.Waiting == 0)
  400.                pUnitCB->PrtyQRLE[PrtyQIndex].Tail = 0;
  401.             else
  402.                pRLE->RqHdr.Waiting = 0;
  403.             Removed = YES;
  404.          }
  405.          else   /* Entry is not at the head, so search for it */
  406.          {
  407.             (PBYTE) pCurReq = pUnitCB->PrtyQRLE[PrtyQIndex].Head;
  408.             while (pCurReq != 0 && Removed == NO)
  409.             {
  410.                if (pCurReq = pRLE)
  411.                {
  412.                   pPrevReq->RqHdr.Waiting = pCurReq->RqHdr.Waiting;
  413.                   if (pUnitCB->PrtyQRLE[PrtyQIndex].Tail = (PBYTE) pCurReq)
  414.                      (ULONG) pUnitCB->PrtyQRLE[PrtyQIndex].Tail =
  415.                                ((PPB_Read_Write)pCurReq)->RqHdr.Waiting;
  416.                    Removed = YES;
  417.                }
  418.                pPrevReq = pCurReq;
  419.                if (pCurReq->RqHdr.Waiting != 0)
  420.                   pCurReq = (PPB_Read_Write) pCurReq->RqHdr.Waiting;
  421.             }
  422.          }
  423.       }
  424.    }
  425.  
  426.    if (Removed == YES)
  427.    {
  428.       pRLE->RqHdr.Status = RH_NOT_QUEUED;
  429.       rc = 0;
  430.    }
  431.    else
  432.      rc = 1;
  433.  
  434.    ENABLE;
  435.    POPFLAGS;
  436.    return(rc);
  437.  
  438. }
  439. /*------------------------------------------------------------------------
  440. ;
  441. ;** PurgePriorityQueues - Purge Priority Queues
  442. ;
  443. ;   Purge all requests from all priority queues for a specifed unit.
  444. ;
  445. ;   USHORT PurgePriorityQueues (NPUNITCB pUnitCB, UCHAR ErrorCode)
  446. ;
  447. ;   ENTRY:    pUnitCB          - Pointer to UnitCB
  448. ;             ErrorCode        - error code stored in Request Packet
  449. ;                                or Request List prior to notifying caller
  450. ;
  451. ;   RETURN:
  452. ;
  453. ;   EFFECTS:
  454. ;
  455. ------------------------------------------------------------------------*/
  456. VOID PurgePriorityQueues (pUnitCB, ErrorCode)
  457.  
  458. NPUNITCB pUnitCB;
  459. UCHAR    ErrorCode;
  460.  
  461. {
  462.    PBYTE pRequest;
  463.    USHORT AwakeCount;
  464.  
  465.    while (PullPriorityQueue(pUnitCB, (PBYTE FAR *) &pRequest) == NO_ERROR)
  466.    {
  467.       if ( ((PRPH)pRequest)->Cmd == PB_REQ_LIST )
  468.       {
  469.          ((PPB_Read_Write)pRequest)->Blocks_Xferred = 0;
  470.          ((PPB_Read_Write)pRequest)->RqHdr.Status = RH_UNREC_ERROR;
  471.          ((PPB_Read_Write)pRequest)->RqHdr.Error_Code = ErrorCode;
  472.          NotifyRLE((PPB_Read_Write)pRequest);
  473.       }
  474.       else
  475.       {
  476.          ((PRPH)pRequest)->Status = STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA;
  477.          ((PRP_RWV)pRequest)->NumSectors = 0;
  478.  
  479.          if (TraceFlags != 0)
  480.             Trace(TRACE_STRAT1 | TRACE_ASYNCDONE, (PBYTE)pRequest,
  481.                                                   pUnitCB->pCurrentVolCB);
  482.  
  483.          /* If internal request came from us, then issue PRUN */
  484.  
  485.          if (((PRPH)pRequest)->Flags & RPF_Internal)
  486.             DevHelp_ProcRun((ULONG)pRequest, &AwakeCount);
  487.  
  488.          else
  489.          {
  490.             /* Normal request from file system, issue DevHelp_DevDone */
  491.  
  492.             DevHelp_DevDone((PBYTE) pRequest);
  493.          }
  494.       }
  495.    }
  496. }
  497.  
  498.  
  499. /*------------------------------------------------------------------------
  500. ;
  501. ;** GetPrtyQIndex - Get priority queue index
  502. ;
  503. ;   This function converts an input priority value to an index
  504. ;   into the priority queue array in the UnitCB.
  505. ;
  506. ;   USHORT GetPrtyQIndex  (UCHAR Priority)
  507. ;
  508. ;   ENTRY:    Priority         - Priority flag value
  509. ;
  510. ;   RETURN:   USHORT           - Index into priority array
  511. ;
  512. ;   EFFECTS:
  513. ;
  514. ------------------------------------------------------------------------*/
  515. USHORT GetPrtyQIndex (pUnitCB,Priority)                              /*@V74404*/
  516.  
  517. NPUNITCB pUnitCB;                                                    /*@V74404*/
  518. UCHAR    Priority;
  519.  
  520. {
  521.    USHORT i;
  522.  
  523.    /* If priority queuing disabled, return highest priority queue index */
  524.  
  525.    if (pUnitCB->QueueMethod == QUEUE_METHOD_NOPRIORITY)              /*@V74404*/
  526.       return(0);
  527.  
  528.    /* Lowest priority value (i.e. 0) is the last queue */
  529.  
  530.    if (Priority == 0)
  531.       return(NUM_RLE_QUEUES - 1);
  532.  
  533.    for (i = NUM_RLE_QUEUES - 1; i > 0; i--)
  534.    {
  535.       Priority >>= 1;
  536.       if (Priority == 0)
  537.          return(i-1);
  538.    }
  539.    return(5);           /* Set to background user if invalid priority */
  540.  
  541.  
  542. }
  543.  
  544.  
  545. /*------------------------------------------------------------------------
  546. ;
  547. ;** SubmitRequestsToADD - Submit Requests to an Adapter Device Driver
  548. ;
  549. ;   This function submits requests in priority order to the Adapter
  550. ;   Device Driver which manages this unit.  Requests are pulled from
  551. ;   the priority waiting queues, IORBs are built and submitted to the
  552. ;   ADD.  IORBs will be chained together is the ADD supports a queuing
  553. ;   count > 1 and the recommended queuing limit has not been exceded.
  554. ;
  555. ;   USHORT SubmitRequestsToADD (pUnitCB)
  556. ;
  557. ;   ENTRY:    pUnitCB          - pointer to unit control block
  558. ;
  559. ;   RETURN:   VOID
  560. ;
  561. ;   EFFECTS:
  562. ;
  563. ------------------------------------------------------------------------*/
  564. VOID FAR f_SubmitRequestsToADD (pUnitCB)
  565.  
  566. NPUNITCB pUnitCB;
  567. {
  568.    SubmitRequestsToADD (pUnitCB);
  569. }
  570.  
  571.  
  572. VOID NEAR SubmitRequestsToADD (pUnitCB)
  573.  
  574. NPUNITCB pUnitCB;
  575.  
  576. {
  577.    NPIORB pIORB, pPrevIORB, pFirstIORB;
  578.    PBYTE  pReq;
  579.    USHORT i;
  580.    USHORT NumIORBsBuilt = 0;
  581.  
  582.    PUSHFLAGS;
  583.    DISABLE;
  584.  
  585.    /* If the number of requests already submitted to the ADD is     */
  586.    /* less than the ADD's recommended queuing count, then submit    */
  587.    /* additional requests.                                          */
  588.  
  589.    for (i=pUnitCB->NumReqsInProgress; i < pUnitCB->QueueDepth; i++)  /*@V74404*/
  590.    {
  591.  
  592.       /* Allocate an IORB.  If one is available, then pull the next     */
  593.       /* highest priority request from the unit's priority queues.      */
  594.  
  595.       if (AllocIORB(pUnitCB, (NPIORB FAR *) &pIORB) != NO_ERROR)
  596.          break;
  597.  
  598.       if (PullPriorityQueue (pUnitCB, (PBYTE FAR *)&pReq) != NO_ERROR)
  599.       {
  600.          FreeIORB(pUnitCB, pIORB);
  601.          break;
  602.       }
  603.  
  604.       /* We've pulled another request from the queue, so build the IORB    */
  605.       /* for it and chain it to the previous if we've built more than one. */
  606.  
  607.       pUnitCB->NumReqsInProgress++;
  608.       NumReqsInProgress++;
  609.  
  610.       ENABLE;
  611.  
  612.       SetupIORB(pUnitCB, pReq, pIORB);
  613.  
  614.       NumIORBsBuilt++;
  615.  
  616.       if (NumIORBsBuilt == 1)
  617.       {
  618.          /* Only Execute_IO commands can be chained */
  619.  
  620.          if (pIORB->CommandCode == IOCC_EXECUTE_IO)
  621.          {
  622.             pFirstIORB = pIORB;
  623.             pPrevIORB = pIORB;
  624.          }
  625.          else
  626.          {
  627.             /* Non Execute_IO request, send single IORB now */
  628.  
  629.             CallADD(pUnitCB, pIORB);
  630.             NumIORBsBuilt = 0;
  631.          }
  632.       }
  633.       else
  634.       {
  635.          /* Only Execute_IO commands can be chained */
  636.  
  637.          if (pIORB->CommandCode == IOCC_EXECUTE_IO)
  638.          {
  639.             pPrevIORB->pNxtIORB = (PVOID) pIORB;
  640.             pPrevIORB->RequestControl |= IORB_CHAIN;
  641.             pPrevIORB = pIORB;
  642.          }
  643.          else
  644.          {
  645.             /* Pulled non-Execute_IO Request after chain built */
  646.  
  647.             CallADD(pUnitCB, pFirstIORB);    /* Send Execute_IO chain */
  648.             CallADD(pUnitCB, pIORB);         /* Send Non Execute_IO request */
  649.             NumIORBsBuilt = 0;
  650.          }
  651.       }
  652.       DISABLE;
  653.    }
  654.  
  655.    ENABLE;
  656.    POPFLAGS;
  657.  
  658.    /* If at least one IORB has been built, then send the IORB chain */
  659.    /* (or single IORB) to the ADD.                                  */
  660.  
  661.    if (NumIORBsBuilt > 0)
  662.    {
  663.       CallADD(pUnitCB, pFirstIORB);
  664.    }
  665. }
  666. /*------------------------------------------------------------------------
  667. ;
  668. ;** CallADD - Call the Adapter Driver Entry Point
  669. ;
  670. ;   This function calls the adapter driver entry point with the
  671. ;   specified IORB chain.
  672. ;
  673. ;   VOID CallADD (pUnitCB, pIORB)
  674. ;
  675. ;   ENTRY:    pUnitCB          - pointer to unit control block
  676. ;             pIORB            - pointer to IORB chain
  677. ;
  678. ;   RETURN:   VOID
  679. ;
  680. ;   EFFECTS:
  681. ;
  682. ------------------------------------------------------------------------*/
  683. VOID CallADD (pUnitCB, pIORB)
  684.  
  685. NPUNITCB pUnitCB;
  686. NPIORB   pIORB;
  687.  
  688. {
  689.    if (TraceFlags != 0)
  690.       Trace(TRACE_IORB | TRACE_ENTRY, (PBYTE)pIORB, pUnitCB);
  691.  
  692.    (pUnitCB->AdapterDriverEP) ((PVOID) pIORB);
  693. }
  694.  
  695. /*------------------------------------------------------------------------
  696. ;
  697. ;** SubmitImmedRequestToADD - Submit Immediate request to Adapter Driver
  698. ;
  699. ;   This function bypasses the priority queues and sends an immediate
  700. ;   request to the adapter driver.  An IORB is built and submitted to
  701. ;   the ADD even if the recommended queuing count has reached its limit.
  702. ;   This is required for commands like RESUME, which must be sent to
  703. ;   the ADD in order to resume work which may have already been queued up
  704. ;   in the driver.
  705. ;
  706. ;   USHORT SubmitImmedRequestsToADD (pUnitCB, pRequest)
  707. ;
  708. ;   ENTRY:    pUnitCB          - pointer to unit control block
  709. ;             pRequest         - pointer to Request
  710. ;
  711. ;   RETURN:   VOID
  712. ;
  713. ;   EFFECTS:
  714. ;
  715. ------------------------------------------------------------------------*/
  716. VOID SubmitImmedRequestToADD (pUnitCB, pRequest)
  717.  
  718. NPUNITCB pUnitCB;
  719. PBYTE    pRequest;
  720. {
  721.    NPIORB pIORB;
  722.  
  723.    /* Allocate an IORB.  Wait until one is available.   */
  724.  
  725.    AllocIORB_Wait(pUnitCB, (NPIORB FAR *) &pIORB);
  726.  
  727.    DISABLE;
  728.  
  729.    pUnitCB->NumReqsInProgress++;
  730.    NumReqsInProgress++;
  731.  
  732.    ENABLE;
  733.  
  734.    SetupIORB(pUnitCB, pRequest, pIORB);
  735.  
  736.    /* Send the IORB to the adapter driver */
  737.  
  738.    (pUnitCB->AdapterDriverEP) ((PVOID) pIORB);
  739.  
  740. }
  741.  
  742.  
  743. /*------------------------------------------------------------------------
  744. ;
  745. ;** NotifyDoneIORB - Notify routine when IORB is done in ADD
  746. ;
  747. ;   This function is the notification routine called by an Adapter Device
  748. ;   Driver when an IORB is done.  Error status and blocks transferred
  749. ;   are updated in the associated Request Packet or Request List entry.  If
  750. ;   the request is a Strategy-2 Request List Entry, the file system is
  751. ;   notified that the request has completed.  If the request is a
  752. ;   Strategy-1 Request Packet, the thread waiting on the request is woken up.
  753. ;
  754. ;   VOID NotifyDoneIORB (PIORB fpIORB)
  755. ;
  756. ;   ENTRY:    fpIORB            - far pointer to completed IORB
  757. ;
  758. ;   RETURN:   VOID
  759. ;
  760. ;   EFFECTS:
  761. ;
  762. ------------------------------------------------------------------------*/
  763. VOID _loadds FAR NotifyDoneIORB (fpIORB)
  764.  
  765. PIORB fpIORB;
  766.  
  767. {
  768.    PRPH pReq;
  769.    NPUNITCB pUnitCB;
  770.    NPIORB pIORB;
  771.    NPIORB_DMWORK pDMWork;
  772.  
  773.    pIORB = (NPIORB) (OFFSETOF(fpIORB));
  774.    pDMWork = (NPIORB_DMWORK) &(pIORB->DMWorkSpace);
  775.    pUnitCB = (NPUNITCB) pDMWork->pUnitCB;
  776.  
  777.  
  778.    if (TraceFlags != 0)
  779.       Trace(TRACE_IORB | TRACE_ASYNCDONE, (PBYTE) pIORB, pUnitCB);
  780.    else if ((pIORB->Status & IORB_ERROR) && !(DDFlags & DDF_DISCARD_TRACE)) /*@V81576*/
  781.    {
  782.       TraceIORBInternal(TRACE_IORB | TRACE_ASYNCDONE, (PBYTE) pIORB);
  783.    }
  784.  
  785.    if ( ((PRPH)pDMWork->pRequest)->Cmd == PB_REQ_LIST)
  786.       NotifyDoneIORB_RLE(pIORB, (PPB_Read_Write) pDMWork->pRequest, pUnitCB);
  787.    else
  788.    {
  789.       NotifyDoneIORB_RP (pIORB, (PBYTE) pDMWork->pRequest, pUnitCB);
  790.    }
  791.  
  792.    /* Call the file system's end of interrupt routine */
  793.  
  794.    if (pFSD_EndofInt != 0)
  795.       FSD_EndofInt();
  796. }
  797.  
  798. /*------------------------------------------------------------------------
  799. ;
  800. ;** NotifyDoneIORB_RLE - Notify routine when IORB for a RLE is done
  801. ;
  802. ;   This function is called when the ADD notifies us that a
  803. ;   Request List entry is done.  Error status and blocks transferred
  804. ;   are updated in the Request List Entry.  The file system is
  805. ;   notified that the request has completed.
  806. ;
  807. ;   USHORT NotifyDoneIORB_RLE (NPIORB pIORB, PPB_Read_Write pRLE)
  808. ;
  809. ;   ENTRY:    pIORB            - pointer to completed IORB
  810. ;             pRLE             - pointer to Request List Entry
  811. ;             pUnitCB          - pointer to UnitCB
  812. ;
  813. ;   RETURN:   USHORT           - Next Event Code
  814. ;
  815. ;   EFFECTS:
  816. ;
  817. ------------------------------------------------------------------------*/
  818. USHORT NotifyDoneIORB_RLE (pIORB, pRLE, pUnitCB)
  819.  
  820. NPIORB pIORB;
  821. PPB_Read_Write  pRLE;
  822. NPUNITCB pUnitCB;
  823.  
  824. {
  825.    PReq_List_Header pRLH;
  826.    PPB_Read_Write   pRLEOrig;
  827.    NPIORB_DMWORK pDMWork;
  828.    USHORT NextEvent = 0;
  829.    USHORT FT_Status = 0;
  830.    NPVOLCB pVolCB;
  831.  
  832.    pDMWork = (NPIORB_DMWORK) &(pIORB->DMWorkSpace);
  833.  
  834.    pRLH = (PReq_List_Header) pRLE;
  835.    OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) (pRLE->RqHdr.Head_Offset);
  836.  
  837.    /* Set the error status and error code and call the file system */
  838.    /* notification routine.                                        */
  839.  
  840.    if (pIORB->Status & IORB_ERROR)
  841.    {
  842.       if (pIORB->Status & IORB_RECOV_ERROR)
  843.       {
  844.          /* HPFS doesnt handle recovered errors so set to no error */
  845.  
  846.          pRLE->RqHdr.Status = RH_NO_ERROR;
  847.          pRLE->RqHdr.Error_Code = 0;
  848.          pRLE->Blocks_Xferred = pRLE->Block_Count;
  849.       }
  850.       else
  851.       {
  852.          pRLE->RqHdr.Status = RH_UNREC_ERROR;
  853.          pRLE->RqHdr.Error_Code = MapIORBError(pIORB->ErrorCode);
  854.          pRLE->Blocks_Xferred = 0;
  855.       }
  856.    }
  857.    else
  858.    {
  859.       pRLE->RqHdr.Status = RH_NO_ERROR;
  860.       pRLE->RqHdr.Error_Code = 0;
  861.       pRLE->Blocks_Xferred = pRLE->Block_Count;
  862.    }
  863.  
  864.  
  865.    if ( (DDFlags & DDF_FT_ENABLED) &&
  866.         ( ((PRHFT)pRLE)->ftdb.FT_Flags & FTF_FT_REQUEST) )
  867.    {
  868.        if ((FT_Status = f_FT_NotifyDoneIORB_RLE(pIORB, pRLE,
  869.                         (PPB_Read_Write FAR *)&pRLEOrig)) & STDON)
  870.        {
  871.           pRLE = pRLEOrig;
  872.           pRLH = (PReq_List_Header) pRLE;
  873.           OFFSETOF(pRLH) = OFFSETOF(pRLE) - (USHORT) (pRLE->RqHdr.Head_Offset);
  874.        }
  875.        else
  876.           goto RLE_Cleanup;
  877.    }
  878.    NotifyRLE (pRLE);
  879.  
  880.    /* If Uncertain Media error or Abort List on Error specified, */
  881.    /* then abort the entire request list.                        */
  882.  
  883.    if (pRLE->RqHdr.Status & RH_UNREC_ERROR)
  884.    {
  885.       if (pRLE->RqHdr.Error_Code == ERROR_I24_UNCERTAIN_MEDIA)
  886.       {
  887.          pUnitCB->pCurrentVolCB->Flags |= vf_UncertainMedia;
  888.  
  889.          PurgePriorityQueues(pUnitCB, ERROR_I24_UNCERTAIN_MEDIA);
  890.       }
  891.       else if ( (pRLH->Lst_Status & RLH_Abort_Err) &&
  892.                 (pRLH->Lst_Status & RLH_Exe_Req_Seq) )
  893.       {
  894.          pRLH->Lst_Status |= RLH_Abort_pendings;
  895.          AbortReqList(pRLH);
  896.       }
  897.    }
  898.  
  899.    /* Clean up request */
  900.  
  901. RLE_Cleanup:
  902.    FreeIORB(pUnitCB, pIORB);
  903.  
  904.    PUSHFLAGS;
  905.    DISABLE;
  906.    pUnitCB->NumReqsInProgress --;
  907.    NumReqsInProgress--;
  908.    POPFLAGS;
  909.  
  910.    /* If Execute in Sequence specified, then queue the next request in */
  911.    /* in the list and submit it for processing.                        */
  912.  
  913.    if ( (pRLH->Request_Control & RLH_Exe_Req_Seq) &&
  914.         ( !(pRLH->Lst_Status & RLH_All_Req_Done)) )
  915.    {
  916.       if (DDFlags & DDF_FT_ENABLED)
  917.       {
  918.          if (FT_Status & STDON)
  919.          {
  920.             Get_VolCB_Addr(pRLH->Block_Dev_Unit, (NPVOLCB FAR *)&pVolCB);
  921.             f_FT_ExecReqList(pRLH, pVolCB->pUnitCB);
  922.          }
  923.       }
  924.       else
  925.          ExecReqList(pRLH, pUnitCB);        /* Execute in sequence case */
  926.    }
  927.    else
  928.  
  929.    /*  Pull the next request from the priority queues and submit it */
  930.  
  931.       SubmitRequestsToADD(pUnitCB);         /* Normal case */
  932.  
  933. }
  934.  
  935.  
  936. /*------------------------------------------------------------------------
  937. ;
  938. ;** NotifyDoneIORB_RP - Notify routine when an IORB for a RP is done
  939. ;
  940. ;   This function is called when the ADD notifies us that a
  941. ;   Request Packet is done.  Error status and blocks transferred
  942. ;   are updated in the Request Packet.  The thread waiting on
  943. ;   the request is woken up.
  944. ;
  945. ;   VOID NotifyDoneIORB_RP (PIORB pIORB, PBYTE pRP)
  946. ;
  947. ;   ENTRY:    pIORB            - pointer to completed IORB
  948. ;             pRP              - pointer to Request Packet
  949. ;             pUnitCB          - pointer to UnitCB
  950. ;
  951. ;   RETURN:   VOID
  952. ;
  953. ;   EFFECTS:
  954. ;
  955. ------------------------------------------------------------------------*/
  956. VOID NotifyDoneIORB_RP (pIORB, pRP, pUnitCB)
  957.  
  958. NPIORB pIORB;
  959. PBYTE pRP;
  960. NPUNITCB pUnitCB;
  961.  
  962. {
  963.    USHORT RP_Status;
  964.    USHORT AwakeCount;
  965.    NPIORB_DMWORK pDMWork;
  966.    PBYTE  pRPOrig;
  967.    NPVOLCB pVolCB;
  968.  
  969.    pDMWork = (NPIORB_DMWORK) &(pIORB->DMWorkSpace);
  970.  
  971.    RP_Status = STDON;
  972.  
  973.    /* Set the packet status word and wake up the thread waiting    */
  974.    /* on completition of this request.  Recovered errors are       */
  975.    /* treated as no error, since Request Packets dont handle       */
  976.    /* recovered error conditions.                                  */
  977.  
  978.    if (pIORB->Status & IORB_ERROR)
  979.    {
  980.       if ( !(pIORB->Status & IORB_RECOV_ERROR) )
  981.       {
  982.          RP_Status |= STERR;
  983.  
  984.          (UCHAR) RP_Status = MapIORBError(pIORB->ErrorCode);
  985.  
  986.          if (pIORB->CommandCode == IOCC_EXECUTE_IO)
  987.            ((PRP_RWV)pRP)->NumSectors = 0;
  988.  
  989.          if ((UCHAR) RP_Status == ERROR_I24_UNCERTAIN_MEDIA)
  990.          {
  991.             pUnitCB->pCurrentVolCB->Flags |= vf_UncertainMedia;
  992.  
  993.             PurgePriorityQueues(pUnitCB, ERROR_I24_UNCERTAIN_MEDIA);
  994.          }
  995.       }
  996.    }
  997.  
  998.    /* Set the status word and blocks transferred count in the RP */
  999.  
  1000.    ((PRPH)pRP)->Status = RP_Status;
  1001.  
  1002.    if ( (DDFlags & DDF_FT_ENABLED) &&
  1003.         ( ((PRPFT)pRP)->ftdb.FT_Flags & FTF_FT_REQUEST ) )
  1004.    {
  1005.        if (f_FT_NotifyDoneIORB_RP(pIORB, (PRP_RWV) pRP,
  1006.                                          (PRP_RWV FAR *)&pRPOrig) & STDON)
  1007.           pRP = pRPOrig;
  1008.        else
  1009.           goto RP_Cleanup;
  1010.    }
  1011.  
  1012.    if (pIORB->CommandCode == IOCC_UNIT_STATUS)
  1013.       ((PRP_INTERNAL)pRP)->RetStatus = ((NPIORB_UNIT_STATUS)pIORB)->UnitStatus;
  1014.  
  1015.    if (pIORB->CommandCode == IOCC_GEOMETRY)
  1016.    {
  1017.       if (pIORB->CommandModifier == IOCM_GET_MEDIA_GEOMETRY)
  1018.       {                                                                /*@V63867*/
  1019.          if ( ((PRP_INTERNAL)pRP)->Function == DISKOP_UPDATE_REC_BPB ) /*@V63867*/
  1020.          {                                                             /*@V63867*/
  1021.             if ( !(pIORB->Status & IORB_ERROR) )                       /*@V63867*/
  1022.             {                                                          /*@V63867*/
  1023.                pVolCB = (NPVOLCB) ((PRP_INTERNAL)pRP)->NumSectors;     /*@V63867*/
  1024.                                                                        /*@V63867*/
  1025.                f_BPBFromGeom( (NPVOLCB)   pVolCB,                      /*@V63867*/
  1026.                               (NPBPB)     &pVolCB->RecBPB,             /*@V63867*/
  1027.                               (PGEOMETRY) ((NPIORB_GEOMETRY) pIORB)->pGeometry ); /*@V63867*/
  1028.             }                                                          /*@V63867*/
  1029.          }                                                             /*@V63867*/
  1030.          else                                                          /*@V63867*/
  1031.          {                                                             /*@V63867*/
  1032.            ((PRP_INTERNAL)pRP)->NumSectors =
  1033.               (USHORT)((NPGEOMETRY)((NPIORB_GEOMETRY)pIORB)->pGeometry)->TotalSectors;
  1034.          }
  1035.       }
  1036.    }
  1037.  
  1038.  
  1039.    /* Wake up the thread waiting on completion of this request  */
  1040.  
  1041.    if (TraceFlags != 0)
  1042.       Trace(TRACE_STRAT1 | TRACE_ASYNCDONE, (PBYTE) pRP, (NPVOLCB) 0);
  1043.  
  1044.  
  1045.    /* If internal request came from us, then issue ProcRun, */
  1046.    /* else issue DevDone for normal file system requests.   */
  1047.  
  1048.    if (((PRPH)pRP)->Flags & RPF_Internal)
  1049.       DevHelp_ProcRun((ULONG)pRP, &AwakeCount);
  1050.    else
  1051.       DevHelp_DevDone((PBYTE) pRP);
  1052.  
  1053.  
  1054.    /* Clean up request and submit next request for processing */
  1055.  
  1056.    if (DDFlags & DDF_INIT_TIME)          /* No cleanup if at init time */
  1057.       return;
  1058.  
  1059. RP_Cleanup:
  1060.    FreeIORB(pUnitCB, pIORB);
  1061.  
  1062.    PUSHFLAGS;
  1063.    DISABLE;
  1064.    pUnitCB->NumReqsInProgress --;
  1065.    NumReqsInProgress--;
  1066.    POPFLAGS;
  1067.  
  1068.    SubmitRequestsToADD(pUnitCB);         /* Normal case */
  1069.  
  1070. }
  1071.  
  1072.  
  1073.  
  1074.