home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / e2fltsrc.zip / e2router.c < prev    next >
C/C++ Source or Header  |  1995-07-25  |  7KB  |  188 lines

  1. /************************************************************************/
  2. /*  Linux partition filter (C) Deon van der Westhuysen.                 */
  3. /*                                                                      */
  4. /*  Dedicated to Jesus Christ, my Lord and Saviour.                     */
  5. /*                                                                      */
  6. /*  Permission is granted to freely use and modify this code for non-   */
  7. /*  profit use on the condition that this notice is not removed. All    */
  8. /*  other rights are reserved. No warranty, etc.                        */
  9. /*                                                                      */
  10. /*  This code is still under development; expect some rough edges.      */
  11. /*                                                                      */
  12. /************************************************************************/
  13.  
  14. #include "debug.h"
  15. #include "e2data.h"
  16. #include "e2router.h"
  17. #include "e2wrap.h"
  18. #include "e2filt.h"
  19. #include "e2part.h"
  20.  
  21. /* Macro to test whether an pointer points to an element in the array */
  22. #define IS_ELEMENT(PTR,ARRAY,SIZE)    ((((VOID*)PTR)>=((VOID*)ARRAY))&&\
  23.                      (((VOID*)PTR)<((VOID*)(ARRAY+SIZE))))
  24.  
  25. /* All IORBs arrive here. We queue the IORB and then call the queue server */
  26. /* to take over. */
  27. void E2FilterIORB (PIORB pIORB)
  28. {
  29.  NPRecHeader    pUnitRec;            /* Ptr to unit rec for IORB */
  30.  NPIORBQueue    pQueue;                /* Ptr to queue for IORB */
  31.  
  32.  if (pIORB->CommandCode==IOCC_CONFIGURATION)    /* For configuration IORBs: */
  33.   pUnitRec= (NPRecHeader) VirtUnits;        /* Assign IORB to the first */
  34.                         /* virtual unit. (For queue) */
  35.  else
  36.   pUnitRec= (NPRecHeader) pIORB->UnitHandle;    /* Get pointer to unit */
  37.                         /* from the unit handle */
  38.  /* Check to see if pUnitRec is a pointer to a valid unit record. */
  39.  if (!(IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)||
  40.        IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits)))
  41.  {
  42.   IORBError (pIORB,IOERR_NO_SUCH_UNIT);        /* Tell them they are crazy! */
  43.   NotifyDone (pIORB);                /* Notify that we are done */
  44.  }
  45.  else
  46.  {
  47.   pQueue= &(pUnitRec->IORBQueue);        /* Get pointer to IORB queue */
  48.   DISABLE                    /* Same safety... */
  49.   AddIORBToQueue (pQueue,pIORB);        /* Add IORB to queue */
  50.   ENABLE                    /* Re-enable interrupts */
  51.   StartIORBQueue (pQueue);            /* Try to restart the queue */
  52.  }
  53. }
  54.  
  55. /* Function to add an IORB to a queue of IORBs maintainded for the unit. */
  56. /* MUST be called with interrupts disabled. */
  57. void AddIORBToQueue (NPIORBQueue pQueue, PIORB pIORB)
  58. {
  59.  if (pQueue->pTail)                /* Queue had IORBs waiting: */
  60.   pQueue->pTail->pNxtIORB= pIORB;        /* Add IORB into queue */
  61.  else                        /* Queue was empty: */
  62.   pQueue->pHead= pIORB;                /* Add IORB into queue */
  63.  while (pIORB->RequestControl&IORB_CHAIN)    /* If not last IORB in chain */
  64.   pIORB= pIORB->pNxtIORB;            /* Seek next IORB in request */
  65.  (pQueue->pTail= pIORB)->pNxtIORB= 0;        /* Set new tail pointer and */
  66.                         /* clear ptr to chained IORB */
  67. }
  68.  
  69. /* Function retrieve an IORB from the queue. Returns NULL if the queue was */
  70. /* empty. MUST be called with interrupts disabled. */
  71. PIORB GetIORBFromQueue (NPIORBQueue pQueue)
  72. {
  73.  PIORB    pReturnIORB;                /* Pointer to return */
  74.  
  75.  if (pQueue->pHead)                /* If queue is not empty: */
  76.  {
  77.   pReturnIORB= pQueue->pHead;            /* Get pointer to head */
  78.   pQueue->pHead= pReturnIORB->pNxtIORB;        /* Update the head pointer */
  79.   if (!pQueue->pHead)                /* If queue now is empty: */
  80.    pQueue->pTail= NULL;                /* Clear the tail pointer */
  81.  }
  82.  else
  83.   pReturnIORB= NULL;                /* Queue empty: return NULL */
  84.  return pReturnIORB;
  85. }
  86.  
  87. /* Function to service an IORB queue. It first checks that the queue is not */
  88. /* being serviced before entering the service loop. */
  89. void StartIORBQueue (NPIORBQueue pQueue)
  90. {
  91.  PIORB            pIORB;            /* Ptr to IORB to execute */
  92.  NPRecHeader        pUnitRec;        /* Pointer to unit record */
  93.  
  94.  DISABLE                    
  95.  if (!(pQueue->Flags&F_SERVER_ACTIVE))        /* Check to no one is busy */
  96.                         /* servicing this queue */
  97.  {
  98.   pQueue->Flags|=F_SERVER_ACTIVE;        /* Grap control of queue */
  99.   /* If we get where we have exclusize access to the queue. */
  100.   while ((!(pQueue->Flags&F_REQUEST_BUSY))&&
  101.          ((pIORB= GetIORBFromQueue (pQueue))!=NULL))
  102.                         /* Loop while there is an */
  103.                         /* IORB ready to be serviced */
  104.                         /* and the previous IORB is */
  105.                         /* finished. */
  106.   {
  107.    pQueue->Flags|=F_REQUEST_BUSY;        /* Show request in progress */
  108.    ENABLE
  109.  
  110.    if (pIORB->CommandCode==IOCC_CONFIGURATION)    /* For configuration IORBs: */
  111.     pUnitRec= (NPRecHeader) VirtUnits;        /* Assign IORB to the first */
  112.                         /* virtual unit. (For queue) */
  113.    else
  114.     pUnitRec= (NPRecHeader) pIORB->UnitHandle;    /* Get pointer to unit */
  115.                         /* from the unit handle */
  116.  
  117.    /* We will handle (de)allocation and allocation checks here since it is */
  118.    /* common between the two parts- filter and virtual units. */
  119.    if (pIORB->CommandCode==IOCC_UNIT_CONTROL)    /* Unit control command? */
  120.    {
  121.     if (pIORB->CommandModifier==IOCM_ALLOCATE_UNIT)
  122.     {                        /* Allocate unit??? */
  123.      if (pUnitRec->Flags&F_ALLOCATED)        
  124.       IORBError (pIORB,IOERR_UNIT_ALLOCATED);    /* Error if allocated */
  125.      else
  126.       pUnitRec->Flags|=F_ALLOCATED;        /* Else allocate the unit */
  127.      pQueue->Flags&=~F_REQUEST_BUSY;        /* Indicate queue finished */
  128.      NotifyDone (pIORB);
  129.      continue;                    /* Service next request */
  130.     }
  131.     if (pIORB->CommandModifier==IOCM_DEALLOCATE_UNIT)
  132.     {                        /* Deallocate unit??? */
  133.      if (!(pUnitRec->Flags&F_ALLOCATED))    
  134.       IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
  135.                         /* Error if not allocated */
  136.      else
  137.       pUnitRec->Flags&=~F_ALLOCATED;        /* Else deallocate unit */
  138.      pQueue->Flags&=~F_REQUEST_BUSY;        /* Indicate queue finished */
  139.      NotifyDone (pIORB);
  140.      continue;                    /* Service next request */
  141.     }
  142.    }
  143.  
  144.    /* Do allocations checks... if notify points to us, skip check. */
  145.    if (!(pUnitRec->Flags&F_ALLOCATED))        /* If unit is not allocated: */
  146.     if (pIORB->NotifyAddress!=&PartNotifyWrapper)
  147.                         /* and we didn't make request */
  148.      if (pIORB->CommandCode!=IOCC_CONFIGURATION)
  149.                         /*  and not configuration */
  150.      {
  151.       IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
  152.                         /* Then it is an error */
  153.       pQueue->Flags&=~F_REQUEST_BUSY;        /* Indicate queue finished */
  154.       NotifyDone (pIORB);
  155.       continue;                    /* Service next request */
  156.      }
  157.  
  158.  
  159.    if (IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)) 
  160.     FilterHandler (pIORB);            /* Handler for base units */
  161.    else if (IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits))
  162.     PartHandler (pIORB);            /* Handler for virtual units */
  163.    DISABLE
  164.   }
  165.   /* Tell others that this server is not active any more... */
  166.   pQueue->Flags&=~F_SERVER_ACTIVE;
  167.  }
  168.  ENABLE
  169. }
  170.  
  171. /* Notify client that the IORB processing is completed. */
  172. void NotifyDone (PIORB pIORB)
  173. {
  174.  pIORB->Status |= IORB_DONE;            /* Set 'DONE' flag */
  175.  if (pIORB->RequestControl&IORB_ASYNC_POST)    /* If notify flag set... */
  176.   pIORB->NotifyAddress(pIORB);            /* Notify the caller */
  177. }
  178.  
  179. /* Function to return an error code via IORB */
  180. void IORBError (PIORB pIORB, USHORT ErrorCode)
  181. {
  182.  if (ErrorCode)                    /* If really an error: */
  183.  {
  184.   pIORB->Status |= IORB_ERROR;            /* Set error flag */
  185.   pIORB->ErrorCode= ErrorCode;            /* Fill in error code field */
  186.  }
  187. }
  188.