update for HEAD-2003021201
[reactos.git] / drivers / net / npf / read.c
diff --git a/drivers/net/npf/read.c b/drivers/net/npf/read.c
new file mode 100644 (file)
index 0000000..7541744
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+
+#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
+#define NdisZeroMappedMemory(Destination,Length)               RtlZeroMemory(Destination,Length)
+#define NdisReinitializePacket(Packet)                                                                         \
+{                                                                                                                                                      \
+       (Packet)->Private.Head = (PNDIS_BUFFER)NULL;                                                    \
+       (Packet)->Private.ValidCounts = FALSE;                                                                  \
+}
+
+
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+#include "tme.h"
+#include "time_calls.h"
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+//-------------------------------------------------------------------
+
+UINT GetBuffOccupation(POPEN_INSTANCE Open)
+{
+       UINT Occupation;
+
+       NdisAcquireSpinLock( &Open->BufLock );
+       
+       if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
+       else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
+
+       NdisReleaseSpinLock( &Open->BufLock );
+
+       return Occupation;
+}
+
+//-------------------------------------------------------------------
+
+void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT  *Bhead)
+{
+ULONG WordLength;
+UINT n,i,NBlocks;
+
+       WordLength=Length>>2;
+       NBlocks=WordLength>>8;
+       
+       for(n=0;n<NBlocks;n++){
+               for(i=0;i<256;i++){
+                       *((PULONG)Destination)++=*((PULONG)Source)++;
+               }
+       *Bhead+=1024;
+       }
+
+       n=WordLength-(NBlocks<<8);
+       for(i=0;i<n;i++){
+               *((PULONG)Destination)++=*((PULONG)Source)++;
+       }
+       *Bhead+=n<<2;
+       
+       n=Length-(WordLength<<2);
+       for(i=0;i<n;i++){
+               *((PUCHAR)Destination)++=*((PUCHAR)Source)++;
+       }
+       *Bhead+=n;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+    POPEN_INSTANCE      Open;
+    PIO_STACK_LOCATION  IrpSp;
+    PUCHAR                             packp;
+       ULONG                           Input_Buffer_Length;
+       UINT                            Thead;
+       UINT                            Ttail;
+       UINT                            TLastByte;
+       PUCHAR                          CurrBuff;
+       LARGE_INTEGER           CapTime;
+       LARGE_INTEGER           TimeFreq;
+       struct bpf_hdr          *header;
+       KIRQL                           Irql;
+       PUCHAR                          UserPointer;
+       ULONG                           bytecopy;
+       UINT                            SizeToCopy;
+       UINT                            PktLen;
+
+       IF_LOUD(DbgPrint("NPF: Read\n");)
+               
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    Open=IrpSp->FileObject->FsContext;
+       
+       if( Open->Bound == FALSE ){
+               // The Network adapter was removed.
+               EXIT_FAILURE(0);
+       }
+       
+       if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){  
+               // this instance is in dump mode, but the dump file has still not been opened
+               EXIT_FAILURE(0);
+       }
+
+       //See if the buffer is full enough to be copied
+       if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
+       {
+               //wait until some packets arrive or the timeout expires         
+               if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+                       KeWaitForSingleObject(Open->ReadEvent,
+                               UserRequest,
+                               KernelMode,
+                               TRUE,
+                               (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+               KeClearEvent(Open->ReadEvent);
+               
+               if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
+                       CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+                       
+                       //fill the bpf header for this packet
+                       header=(struct bpf_hdr*)CurrBuff;
+                       GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+                       if(Open->mode & MODE_DUMP){
+                               *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+                               header->bh_caplen=24;
+                               header->bh_datalen=24;
+                               Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+                       }
+                       else{
+                               header->bh_caplen=16;
+                               header->bh_datalen=16;
+                               header->bh_hdrlen=sizeof(struct bpf_hdr);
+                               Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+                       }
+
+                       *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+                       *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+                       
+                       //reset the countetrs
+                       NdisAcquireSpinLock( &Open->CountersLock );
+                       Open->Npackets.QuadPart=0;
+                       Open->Nbytes.QuadPart=0;
+                       NdisReleaseSpinLock( &Open->CountersLock );
+                       
+                       Irp->IoStatus.Status = STATUS_SUCCESS;
+                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                       
+                       return STATUS_SUCCESS;
+               }
+               
+               if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
+               {   
+                       PTME_DATA data;
+                       ULONG cnt;
+                       ULONG block_size;
+                       PUCHAR tmp;
+
+                       UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+                       
+                       if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
+                       {       
+                               EXIT_FAILURE(0);
+                       }
+                       
+                       header=(struct bpf_hdr*)UserPointer;
+       
+                       GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+                       
+                       header->bh_hdrlen=sizeof(struct bpf_hdr);
+                       
+
+                       //moves user memory pointer
+                       UserPointer+=sizeof(struct bpf_hdr);
+                       
+                       //calculus of data to be copied
+                       //if the user buffer is smaller than data to be copied,
+                       //only some data will be copied
+                       data=&Open->tme.block_data[Open->tme.active_read];
+
+                       if (data->last_read.tv_sec!=0)
+                               data->last_read=header->bh_tstamp;
+                       
+
+                       bytecopy=data->block_size*data->filled_blocks;
+                       
+                       if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
+                               bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
+                       else 
+                               bytecopy=data->filled_blocks;
+
+                       tmp=data->shared_memory_base_address;
+                       block_size=data->block_size;
+                       
+                       for (cnt=0;cnt<bytecopy;cnt++)
+                       {
+                               NdisAcquireSpinLock(&Open->machine_lock);
+                               RtlCopyMemory(UserPointer,tmp,block_size);
+                               NdisReleaseSpinLock(&Open->machine_lock);
+                               tmp+=block_size;
+                               UserPointer+=block_size;
+                       }
+                                               
+                       bytecopy*=block_size;
+
+                       header->bh_caplen=bytecopy;
+                       header->bh_datalen=header->bh_caplen;
+
+                       EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+               }
+
+               if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
+                       // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+                       // We must awake the application, returning an empty buffer.
+               {
+                       EXIT_SUCCESS(0);
+               }
+                               
+       }
+
+       //
+       // The buffer if full enough to be copied,
+       //
+       NdisAcquireSpinLock( &Open->BufLock );
+       
+       Thead = Open->Bhead;
+       Ttail = Open->Btail;
+       TLastByte = Open->BLastByte;
+
+       //get the address of the buffer
+       CurrBuff=Open->Buffer;
+       
+       NdisReleaseSpinLock( &Open->BufLock );
+       
+       Input_Buffer_Length=IrpSp->Parameters.Read.Length;
+       packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+       
+
+       //
+       //fill the application buffer
+       //
+       if(Ttail > Thead){      //first of all see if it we can copy all the buffer in one time
+               if((Ttail-Thead)<Input_Buffer_Length){
+                       KeResetEvent(Open->ReadEvent);
+
+                       PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
+                       EXIT_SUCCESS(Ttail-Thead);
+               }
+       }
+       else if((TLastByte - Thead) < Input_Buffer_Length){
+               PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
+
+               NdisAcquireSpinLock( &Open->BufLock );
+               
+               Open->BLastByte = Open->Btail;
+               Open->Bhead = 0;
+
+               NdisReleaseSpinLock( &Open->BufLock );
+               
+               EXIT_SUCCESS(TLastByte-Thead);
+       }
+       
+       //the buffer must be scannned to determine the number of bytes to copy
+       SizeToCopy = 0;
+       while(TRUE){
+               if(Thead + SizeToCopy == Ttail)
+                       break;
+
+               if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
+
+                       PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+                       // Reset the buffer
+                       NdisAcquireSpinLock( &Open->BufLock );
+                       (INT)Open->BLastByte = -1;
+                       Open->Bhead = 0;                        
+                       NdisReleaseSpinLock( &Open->BufLock );
+
+                       EXIT_SUCCESS(SizeToCopy);
+               }
+
+               // Get the size of the next packet in the buffer
+               PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
+
+               // The length is aligned to 32-bit boundary
+               PktLen = Packet_WORDALIGN(PktLen);
+
+               if(SizeToCopy + PktLen > Input_Buffer_Length)
+                       break;
+               
+               SizeToCopy += PktLen;
+       }
+
+       PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+       EXIT_SUCCESS(SizeToCopy);
+
+}
+
+//-------------------------------------------------------------------
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+                        IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
+                        IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+    POPEN_INSTANCE      Open;
+    PNDIS_PACKET        pPacketb;
+    ULONG               SizeToTransfer;
+    NDIS_STATUS         Status;
+    UINT                BytesTransfered;
+    ULONG               BufferLength;
+    PMDL                pMdl;
+       LARGE_INTEGER           CapTime;
+       LARGE_INTEGER           TimeFreq;
+       struct bpf_hdr          *header;
+       PUCHAR                          CurrBuff;
+       UINT                            Thead;
+       UINT                            Ttail;
+       UINT                            TLastByte;
+       UINT                            fres;
+       UINT                            maxbufspace;
+       USHORT                          NPFHdrSize;
+       UINT                            BufOccupation;
+       BOOLEAN                         ResetBuff = FALSE;
+
+    IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+    IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n", 
+       HeaderBufferSize,
+       LookAheadBuffer,
+       LookaheadBufferSize,
+       PacketSize);)
+
+       Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+       Open->Received++;               // Number of packets received by filter ++
+
+       BufOccupation = GetBuffOccupation(Open);        // Get the full buffer space
+
+       if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
+               // Heuristic that drops the packet also if it possibly fits in the buffer.
+               // It allows to avoid filtering in critical situations when CPU is very important.
+               Open->Dropped++;
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       NdisAcquireSpinLock(&Open->machine_lock);
+       
+       //
+       //Check if the lookahead buffer follows the mac header.
+       //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+       //executed on the packet.
+       //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+       //things like this) bpf_filter_with_2_buffers() is executed.
+       //
+       if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+               fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+                                                                          HeaderBuffer,
+                                                                          LookAheadBuffer,
+                                                                          HeaderBufferSize,
+                                                                          PacketSize+HeaderBufferSize,
+                                                                          LookaheadBufferSize+HeaderBufferSize,
+                                                                          &Open->mem_ex,
+                                                                          &Open->tme,
+                                                                          &G_Start_Time);
+       
+       
+       else 
+               if(Open->Filter != NULL)
+               {
+                       if (Open->bpfprogram != NULL)
+                       {
+                               fres=Open->Filter->Function(HeaderBuffer,
+                                                                       PacketSize+HeaderBufferSize,
+                                                                       LookaheadBufferSize+HeaderBufferSize);
+               
+                               // Restore the stack. 
+                               // I ignore the reason, but this instruction is needed only at kernel level
+#ifndef __GNUC__
+                               _asm add esp,12         
+#else
+                asm("add $0x12,%esp;");
+#endif
+                       }
+                       else
+                               fres = -1;
+               }
+               else
+                       fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+                               HeaderBuffer,
+                                               PacketSize+HeaderBufferSize,
+                                               LookaheadBufferSize+HeaderBufferSize,
+                                               &Open->mem_ex,
+                                               &Open->tme,
+                                               &G_Start_Time);
+
+       NdisReleaseSpinLock(&Open->machine_lock);
+       
+       if(Open->mode==MODE_MON)
+       // we are in monitor mode
+       {
+               if (fres==1) 
+                       KeSetEvent(Open->ReadEvent,0,FALSE);
+               return NDIS_STATUS_NOT_ACCEPTED;
+
+       }
+
+       if(fres==0)
+               // Packet not accepted by the filter, ignore it.
+               return NDIS_STATUS_NOT_ACCEPTED;
+
+       //if the filter returns -1 the whole packet must be accepted
+       if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize; 
+
+       if(Open->mode & MODE_STAT){
+       // we are in statistics mode
+               NdisAcquireSpinLock( &Open->CountersLock );
+
+               Open->Npackets.QuadPart++;
+               
+               if(PacketSize+HeaderBufferSize<60)
+                       Open->Nbytes.QuadPart+=60;
+               else
+                       Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+               // add preamble+SFD+FCS to the packet
+               // these values must be considered because are not part of the packet received from NDIS
+               Open->Nbytes.QuadPart+=12;
+
+               NdisReleaseSpinLock( &Open->CountersLock );
+               
+               if(!(Open->mode & MODE_DUMP)){
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+       }
+
+       if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
+       
+       if(Open->mode & MODE_DUMP && Open->MaxDumpPacks &&      (UINT)Open->Accepted > Open->MaxDumpPacks){
+               // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+               Open->DumpLimitReached = TRUE; // This stops the thread
+               // Awake the dump thread
+               NdisSetEvent(&Open->DumpEvent);
+
+               // Awake the application
+               KeSetEvent(Open->ReadEvent,0,FALSE);
+
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       // Calculate the correct size for the header associated with the packet
+       NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
+       NdisAcquireSpinLock( &Open->BufLock );
+
+       Thead=Open->Bhead;
+       Ttail=Open->Btail;
+       TLastByte = Open->BLastByte;
+
+       NdisReleaseSpinLock( &Open->BufLock );
+       
+       maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
+
+       if(Ttail+maxbufspace >= Open->BufSize){
+               if(Thead <= maxbufspace)
+               {
+                       Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               else{
+                       Ttail=0;
+                       ResetBuff = TRUE;
+               }
+       }
+       
+       if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
+       {
+               Open->Dropped++;
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+       
+       CurrBuff=Open->Buffer+Ttail;
+
+       if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+       {
+               //  Allocate an MDL to map the portion of the buffer following the header
+               pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
+                       maxbufspace,
+                       FALSE,
+                       FALSE,
+                       NULL);
+
+               if (pMdl == NULL)
+               {
+                       // Unable to map the memory: packet lost
+                       IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
+                               Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               MmBuildMdlForNonPagedPool(pMdl);
+               
+               //allocate the packet from NDIS
+               NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
+               if (Status != NDIS_STATUS_SUCCESS)
+               {
+                       IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+                       IoFreeMdl(pMdl);
+                       Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               //link the buffer to the packet
+               NdisChainBufferAtFront(pPacketb,pMdl);
+               
+               BufferLength=fres-HeaderBufferSize;
+               //Find out how much to transfer
+               SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
+               
+               //copy the ethernet header into buffer
+               NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
+               
+               //Copy the look ahead buffer
+               if(LookaheadBufferSize)
+               {
+                       NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
+                               LookAheadBuffer, 
+                               (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
+                       
+                       SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
+                               SizeToTransfer - LookaheadBufferSize : 0;
+               }
+               
+               Open->TransferMdl=pMdl;
+               
+               if(SizeToTransfer)
+               {
+                       //Call the Mac to transfer the packet
+                       NdisTransferData(&Status,
+                               Open->AdapterHandle,
+                               MacReceiveContext,
+                               LookaheadBufferSize,
+                               SizeToTransfer,
+                               pPacketb,
+                               &BytesTransfered);
+               }
+               else{
+                       BytesTransfered = 0;
+               }
+               
+       }
+       else
+       {
+       // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
+       // This allows us to avoid the allocation of the MDL and the NDIS packet as well
+       RtlCopyMemory((CurrBuff) + NPFHdrSize,
+               HeaderBuffer,
+               HeaderBufferSize + LookaheadBufferSize);
+
+               BytesTransfered = 0;
+
+               Open->TransferMdl = NULL;
+               Status = NDIS_STATUS_SUCCESS;
+       }
+
+       if (Status != NDIS_STATUS_FAILURE)
+       {
+
+               Open->Accepted++;               // Increase the accepted packets counter
+
+               if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
+                       fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
+               
+               //
+               // Build the header
+               //
+               header=(struct bpf_hdr*)CurrBuff;
+               GET_TIME(&header->bh_tstamp,&G_Start_Time);
+               header->bh_caplen=fres;
+               header->bh_datalen=PacketSize+HeaderBufferSize;
+               if(Open->mode==MODE_CAPT){
+                       header->bh_hdrlen=NPFHdrSize;
+                       // Don't align if the packet goes to disk
+                       Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
+               }
+               else
+                       Ttail+=fres+NPFHdrSize;
+               
+               //update the buffer     
+               NdisAcquireSpinLock( &Open->BufLock );
+               
+               if(ResetBuff){
+                       Open->BLastByte = Open->Btail;
+               }
+               Open->Btail=Ttail;
+               
+               NdisReleaseSpinLock( &Open->BufLock );
+       }
+
+       if (Status != NDIS_STATUS_PENDING){
+
+               if( Open->TransferMdl != NULL)
+                       // Complete the request and free the buffers
+                       NPF_TransferDataComplete(Open,pPacketb,Status,fres);
+               else{
+                       // Unfreeze the consumer
+                       if(GetBuffOccupation(Open)>Open->MinToCopy){
+                               if(Open->mode & MODE_DUMP){
+                                       NdisSetEvent(&Open->DumpEvent);
+                               }
+                               else
+                                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+                       }
+                       
+               }
+       }
+       
+       return NDIS_STATUS_SUCCESS;
+       
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+                                 IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+    POPEN_INSTANCE      Open;
+
+    IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+    
+       Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+       IoFreeMdl(Open->TransferMdl);
+       //recylcle the packet
+       NdisReinitializePacket(pPacket);
+       //Put the packet on the free queue
+       NdisFreePacket(pPacket);
+       // Unfreeze the consumer
+       if(GetBuffOccupation(Open)>Open->MinToCopy){
+               if(Open->mode & MODE_DUMP){
+                       NdisSetEvent(&Open->DumpEvent);
+               }
+               else
+                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+       }
+       return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+    IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+    return;
+}