home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
e2fltsrc.zip
/
e2router.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-25
|
7KB
|
188 lines
/************************************************************************/
/* Linux partition filter (C) Deon van der Westhuysen. */
/* */
/* Dedicated to Jesus Christ, my Lord and Saviour. */
/* */
/* Permission is granted to freely use and modify this code for non- */
/* profit use on the condition that this notice is not removed. All */
/* other rights are reserved. No warranty, etc. */
/* */
/* 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 */
}
}