home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* Linux partition filter. */
- /* (C) Copyright Deon van der Westhuysen, July 1995. */
- /* */
- /* Dedicated to Jesus Christ, my Lord and Saviour. */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2, or (at your option) */
- /* any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* This code is still under development; expect some rough edges. */
- /* */
- /************************************************************************/
-
- #include "debug.h"
- #include "e2data.h"
- #include "e2router.h"
- #include "e2wrap.h"
- #include "e2filt.h"
- #include "e2part.h"
-
- /* Macro to test whether an pointer points to an element in the array */
- #define IS_ELEMENT(PTR,ARRAY,SIZE) ((((VOID*)PTR)>=((VOID*)ARRAY))&&\
- (((VOID*)PTR)<((VOID*)(ARRAY+SIZE))))
-
- /* All IORBs arrive here. We queue the IORB and then call the queue server */
- /* to take over. */
- void E2FilterIORB (PIORB pIORB)
- {
- NPRecHeader pUnitRec; /* Ptr to unit rec for IORB */
- NPIORBQueue pQueue; /* Ptr to queue for IORB */
-
- if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */
- pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */
- /* virtual unit. (For queue) */
- else
- pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */
- /* from the unit handle */
- /* Check to see if pUnitRec is a pointer to a valid unit record. */
- if (!(IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)||
- IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits)))
- {
- IORBError (pIORB,IOERR_NO_SUCH_UNIT); /* Tell them they are crazy! */
- NotifyDone (pIORB); /* Notify that we are done */
- }
- else
- {
- pQueue= &(pUnitRec->IORBQueue); /* Get pointer to IORB queue */
- DISABLE /* Same safety... */
- AddIORBToQueue (pQueue,pIORB); /* Add IORB to queue */
- ENABLE /* Re-enable interrupts */
- StartIORBQueue (pQueue); /* Try to restart the queue */
- }
- }
-
- /* Function to add an IORB to a queue of IORBs maintainded for the unit. */
- /* MUST be called with interrupts disabled. */
- void AddIORBToQueue (NPIORBQueue pQueue, PIORB pIORB)
- {
- if (pQueue->pTail) /* Queue had IORBs waiting: */
- pQueue->pTail->pNxtIORB= pIORB; /* Add IORB into queue */
- else /* Queue was empty: */
- pQueue->pHead= pIORB; /* Add IORB into queue */
- while (pIORB->RequestControl&IORB_CHAIN) /* If not last IORB in chain */
- pIORB= pIORB->pNxtIORB; /* Seek next IORB in request */
- (pQueue->pTail= pIORB)->pNxtIORB= 0; /* Set new tail pointer and */
- /* clear ptr to chained IORB */
- }
-
- /* Function retrieve an IORB from the queue. Returns NULL if the queue was */
- /* empty. MUST be called with interrupts disabled. */
- PIORB GetIORBFromQueue (NPIORBQueue pQueue)
- {
- PIORB pReturnIORB; /* Pointer to return */
-
- if (pQueue->pHead) /* If queue is not empty: */
- {
- pReturnIORB= pQueue->pHead; /* Get pointer to head */
- pQueue->pHead= pReturnIORB->pNxtIORB; /* Update the head pointer */
- if (!pQueue->pHead) /* If queue now is empty: */
- pQueue->pTail= NULL; /* Clear the tail pointer */
- }
- else
- pReturnIORB= NULL; /* Queue empty: return NULL */
- return pReturnIORB;
- }
-
- /* Function to service an IORB queue. It first checks that the queue is not */
- /* being serviced before entering the service loop. */
- void StartIORBQueue (NPIORBQueue pQueue)
- {
- PIORB pIORB; /* Ptr to IORB to execute */
- NPRecHeader pUnitRec; /* Pointer to unit record */
-
- DISABLE
- if (!(pQueue->Flags&F_SERVER_ACTIVE)) /* Check to no one is busy */
- /* servicing this queue */
- {
- pQueue->Flags|=F_SERVER_ACTIVE; /* Grap control of queue */
- /* If we get where we have exclusize access to the queue. */
- while ((!(pQueue->Flags&F_REQUEST_BUSY))&&
- ((pIORB= GetIORBFromQueue (pQueue))!=NULL))
- /* Loop while there is an */
- /* IORB ready to be serviced */
- /* and the previous IORB is */
- /* finished. */
- {
- pQueue->Flags|=F_REQUEST_BUSY; /* Show request in progress */
- ENABLE
-
- if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */
- pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */
- /* virtual unit. (For queue) */
- else
- pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */
- /* from the unit handle */
-
- /* We will handle (de)allocation and allocation checks here since it is */
- /* common between the two parts- filter and virtual units. */
- if (pIORB->CommandCode==IOCC_UNIT_CONTROL) /* Unit control command? */
- {
- if (pIORB->CommandModifier==IOCM_ALLOCATE_UNIT)
- { /* Allocate unit??? */
- if (pUnitRec->Flags&F_ALLOCATED)
- IORBError (pIORB,IOERR_UNIT_ALLOCATED); /* Error if allocated */
- else
- pUnitRec->Flags|=F_ALLOCATED; /* Else allocate the unit */
- pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
- NotifyDone (pIORB);
- continue; /* Service next request */
- }
- if (pIORB->CommandModifier==IOCM_DEALLOCATE_UNIT)
- { /* Deallocate unit??? */
- if (!(pUnitRec->Flags&F_ALLOCATED))
- IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
- /* Error if not allocated */
- else
- pUnitRec->Flags&=~F_ALLOCATED; /* Else deallocate unit */
- pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
- NotifyDone (pIORB);
- continue; /* Service next request */
- }
- }
-
- /* Do allocations checks... if notify points to us, skip check. */
- if (!(pUnitRec->Flags&F_ALLOCATED)) /* If unit is not allocated: */
- if (pIORB->NotifyAddress!=&PartNotifyWrapper)
- /* and we didn't make request */
- if (pIORB->CommandCode!=IOCC_CONFIGURATION)
- /* and not configuration */
- {
- IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
- /* Then it is an error */
- pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
- NotifyDone (pIORB);
- continue; /* Service next request */
- }
-
-
- if (IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits))
- FilterHandler (pIORB); /* Handler for base units */
- else if (IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits))
- PartHandler (pIORB); /* Handler for virtual units */
- DISABLE
- }
- /* Tell others that this server is not active any more... */
- pQueue->Flags&=~F_SERVER_ACTIVE;
- }
- ENABLE
- }
-
- /* Notify client that the IORB processing is completed. */
- void NotifyDone (PIORB pIORB)
- {
- pIORB->Status |= IORB_DONE; /* Set 'DONE' flag */
- if (pIORB->RequestControl&IORB_ASYNC_POST) /* If notify flag set... */
- pIORB->NotifyAddress(pIORB); /* Notify the caller */
- }
-
- /* Function to return an error code via IORB */
- void IORBError (PIORB pIORB, USHORT ErrorCode)
- {
- if (ErrorCode) /* If really an error: */
- {
- pIORB->Status |= IORB_ERROR; /* Set error flag */
- pIORB->ErrorCode= ErrorCode; /* Fill in error code field */
- }
- }
-