75417440b0fa3959773236657486107954d8f200
[reactos.git] / drivers / net / npf / read.c
1 /*
2  * Copyright (c) 1999, 2000
3  *      Politecnico di Torino.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the Politecnico
13  * di Torino, and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifdef _MSC_VER
23 #include <stdarg.h>
24 #include <ntddk.h>
25 #include <ntiologc.h>
26 #include <ndis.h>
27 #else
28 #include <ddk/ntddk.h>
29 #include <net/ndis.h>
30
31 #define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
32 #define NdisZeroMappedMemory(Destination,Length)                RtlZeroMemory(Destination,Length)
33 #define NdisReinitializePacket(Packet)                                                                          \
34 {                                                                                                                                                       \
35         (Packet)->Private.Head = (PNDIS_BUFFER)NULL;                                                    \
36         (Packet)->Private.ValidCounts = FALSE;                                                                  \
37 }
38
39
40 #endif
41
42 #include "debug.h"
43 #include "packet.h"
44 #include "win_bpf.h"
45
46 #include "tme.h"
47 #include "time_calls.h"
48
49 extern struct time_conv G_Start_Time; // from openclos.c
50
51 //-------------------------------------------------------------------
52
53 UINT GetBuffOccupation(POPEN_INSTANCE Open)
54 {
55         UINT Occupation;
56
57         NdisAcquireSpinLock( &Open->BufLock );
58         
59         if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
60         else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
61
62         NdisReleaseSpinLock( &Open->BufLock );
63
64         return Occupation;
65 }
66
67 //-------------------------------------------------------------------
68
69 void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT   *Bhead)
70 {
71 ULONG WordLength;
72 UINT n,i,NBlocks;
73
74         WordLength=Length>>2;
75         NBlocks=WordLength>>8;
76         
77         for(n=0;n<NBlocks;n++){
78                 for(i=0;i<256;i++){
79                         *((PULONG)Destination)++=*((PULONG)Source)++;
80                 }
81         *Bhead+=1024;
82         }
83
84         n=WordLength-(NBlocks<<8);
85         for(i=0;i<n;i++){
86                 *((PULONG)Destination)++=*((PULONG)Source)++;
87         }
88         *Bhead+=n<<2;
89         
90         n=Length-(WordLength<<2);
91         for(i=0;i<n;i++){
92                 *((PUCHAR)Destination)++=*((PUCHAR)Source)++;
93         }
94         *Bhead+=n;
95 }
96
97 //-------------------------------------------------------------------
98
99 NTSTATUS STDCALL
100 NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
101 {
102     POPEN_INSTANCE      Open;
103     PIO_STACK_LOCATION  IrpSp;
104     PUCHAR                              packp;
105         ULONG                           Input_Buffer_Length;
106         UINT                            Thead;
107         UINT                            Ttail;
108         UINT                            TLastByte;
109         PUCHAR                          CurrBuff;
110         LARGE_INTEGER           CapTime;
111         LARGE_INTEGER           TimeFreq;
112         struct bpf_hdr          *header;
113         KIRQL                           Irql;
114         PUCHAR                          UserPointer;
115         ULONG                           bytecopy;
116         UINT                            SizeToCopy;
117         UINT                            PktLen;
118
119         IF_LOUD(DbgPrint("NPF: Read\n");)
120                 
121         IrpSp = IoGetCurrentIrpStackLocation(Irp);
122     Open=IrpSp->FileObject->FsContext;
123         
124         if( Open->Bound == FALSE ){
125                 // The Network adapter was removed.
126                 EXIT_FAILURE(0);
127         }
128         
129         if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){  
130                 // this instance is in dump mode, but the dump file has still not been opened
131                 EXIT_FAILURE(0);
132         }
133
134         //See if the buffer is full enough to be copied
135         if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
136         {
137                 //wait until some packets arrive or the timeout expires         
138                 if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
139                         KeWaitForSingleObject(Open->ReadEvent,
140                                 UserRequest,
141                                 KernelMode,
142                                 TRUE,
143                                 (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
144
145                 KeClearEvent(Open->ReadEvent);
146                 
147                 if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
148                         CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
149                         
150                         //fill the bpf header for this packet
151                         header=(struct bpf_hdr*)CurrBuff;
152                         GET_TIME(&header->bh_tstamp,&G_Start_Time);
153
154                         if(Open->mode & MODE_DUMP){
155                                 *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
156                                 header->bh_caplen=24;
157                                 header->bh_datalen=24;
158                                 Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
159                         }
160                         else{
161                                 header->bh_caplen=16;
162                                 header->bh_datalen=16;
163                                 header->bh_hdrlen=sizeof(struct bpf_hdr);
164                                 Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
165                         }
166
167                         *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
168                         *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
169                         
170                         //reset the countetrs
171                         NdisAcquireSpinLock( &Open->CountersLock );
172                         Open->Npackets.QuadPart=0;
173                         Open->Nbytes.QuadPart=0;
174                         NdisReleaseSpinLock( &Open->CountersLock );
175                         
176                         Irp->IoStatus.Status = STATUS_SUCCESS;
177                         IoCompleteRequest(Irp, IO_NO_INCREMENT);
178                         
179                         return STATUS_SUCCESS;
180                 }
181                 
182                 if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
183                 {   
184                         PTME_DATA data;
185                         ULONG cnt;
186                         ULONG block_size;
187                         PUCHAR tmp;
188
189                         UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
190                         
191                         if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
192                         {       
193                                 EXIT_FAILURE(0);
194                         }
195                         
196                         header=(struct bpf_hdr*)UserPointer;
197         
198                         GET_TIME(&header->bh_tstamp,&G_Start_Time);
199
200                         
201                         header->bh_hdrlen=sizeof(struct bpf_hdr);
202                         
203
204                         //moves user memory pointer
205                         UserPointer+=sizeof(struct bpf_hdr);
206                         
207                         //calculus of data to be copied
208                         //if the user buffer is smaller than data to be copied,
209                         //only some data will be copied
210                         data=&Open->tme.block_data[Open->tme.active_read];
211
212                         if (data->last_read.tv_sec!=0)
213                                 data->last_read=header->bh_tstamp;
214                         
215
216                         bytecopy=data->block_size*data->filled_blocks;
217                         
218                         if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
219                                 bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
220                         else 
221                                 bytecopy=data->filled_blocks;
222
223                         tmp=data->shared_memory_base_address;
224                         block_size=data->block_size;
225                         
226                         for (cnt=0;cnt<bytecopy;cnt++)
227                         {
228                                 NdisAcquireSpinLock(&Open->machine_lock);
229                                 RtlCopyMemory(UserPointer,tmp,block_size);
230                                 NdisReleaseSpinLock(&Open->machine_lock);
231                                 tmp+=block_size;
232                                 UserPointer+=block_size;
233                         }
234                                                 
235                         bytecopy*=block_size;
236
237                         header->bh_caplen=bytecopy;
238                         header->bh_datalen=header->bh_caplen;
239
240                         EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
241                 }
242
243                 if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
244                         // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
245                         // We must awake the application, returning an empty buffer.
246                 {
247                         EXIT_SUCCESS(0);
248                 }
249                                 
250         }
251
252         //
253         // The buffer if full enough to be copied,
254         //
255         NdisAcquireSpinLock( &Open->BufLock );
256         
257         Thead = Open->Bhead;
258         Ttail = Open->Btail;
259         TLastByte = Open->BLastByte;
260
261         //get the address of the buffer
262         CurrBuff=Open->Buffer;
263         
264         NdisReleaseSpinLock( &Open->BufLock );
265         
266         Input_Buffer_Length=IrpSp->Parameters.Read.Length;
267         packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
268         
269
270         //
271         //fill the application buffer
272         //
273         if(Ttail > Thead){      //first of all see if it we can copy all the buffer in one time
274                 if((Ttail-Thead)<Input_Buffer_Length){
275                         KeResetEvent(Open->ReadEvent);
276
277                         PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
278                         EXIT_SUCCESS(Ttail-Thead);
279                 }
280         }
281         else if((TLastByte - Thead) < Input_Buffer_Length){
282                 PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
283
284                 NdisAcquireSpinLock( &Open->BufLock );
285                 
286                 Open->BLastByte = Open->Btail;
287                 Open->Bhead = 0;
288
289                 NdisReleaseSpinLock( &Open->BufLock );
290                 
291                 EXIT_SUCCESS(TLastByte-Thead);
292         }
293         
294         //the buffer must be scannned to determine the number of bytes to copy
295         SizeToCopy = 0;
296         while(TRUE){
297                 if(Thead + SizeToCopy == Ttail)
298                         break;
299
300                 if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
301
302                         PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
303                         // Reset the buffer
304                         NdisAcquireSpinLock( &Open->BufLock );
305                         (INT)Open->BLastByte = -1;
306                         Open->Bhead = 0;                        
307                         NdisReleaseSpinLock( &Open->BufLock );
308
309                         EXIT_SUCCESS(SizeToCopy);
310                 }
311
312                 // Get the size of the next packet in the buffer
313                 PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
314
315                 // The length is aligned to 32-bit boundary
316                 PktLen = Packet_WORDALIGN(PktLen);
317
318                 if(SizeToCopy + PktLen > Input_Buffer_Length)
319                         break;
320                 
321                 SizeToCopy += PktLen;
322         }
323
324         PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
325         EXIT_SUCCESS(SizeToCopy);
326
327 }
328
329 //-------------------------------------------------------------------
330
331 NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
332                         IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
333                         IN UINT LookaheadBufferSize,IN UINT PacketSize)
334 {
335     POPEN_INSTANCE      Open;
336     PNDIS_PACKET        pPacketb;
337     ULONG               SizeToTransfer;
338     NDIS_STATUS         Status;
339     UINT                BytesTransfered;
340     ULONG               BufferLength;
341     PMDL                pMdl;
342         LARGE_INTEGER           CapTime;
343         LARGE_INTEGER           TimeFreq;
344         struct bpf_hdr          *header;
345         PUCHAR                          CurrBuff;
346         UINT                            Thead;
347         UINT                            Ttail;
348         UINT                            TLastByte;
349         UINT                            fres;
350         UINT                            maxbufspace;
351         USHORT                          NPFHdrSize;
352         UINT                            BufOccupation;
353         BOOLEAN                         ResetBuff = FALSE;
354
355     IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
356     IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n", 
357         HeaderBufferSize,
358         LookAheadBuffer,
359         LookaheadBufferSize,
360         PacketSize);)
361
362         Open= (POPEN_INSTANCE)ProtocolBindingContext;
363
364         Open->Received++;               // Number of packets received by filter ++
365
366         BufOccupation = GetBuffOccupation(Open);        // Get the full buffer space
367
368         if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
369                 // Heuristic that drops the packet also if it possibly fits in the buffer.
370                 // It allows to avoid filtering in critical situations when CPU is very important.
371                 Open->Dropped++;
372                 return NDIS_STATUS_NOT_ACCEPTED;
373         }
374
375         NdisAcquireSpinLock(&Open->machine_lock);
376         
377         //
378         //Check if the lookahead buffer follows the mac header.
379         //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
380         //executed on the packet.
381         //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
382         //things like this) bpf_filter_with_2_buffers() is executed.
383         //
384         if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
385                 fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
386                                                                            HeaderBuffer,
387                                                                            LookAheadBuffer,
388                                                                            HeaderBufferSize,
389                                                                            PacketSize+HeaderBufferSize,
390                                                                            LookaheadBufferSize+HeaderBufferSize,
391                                                                            &Open->mem_ex,
392                                                                            &Open->tme,
393                                                                            &G_Start_Time);
394         
395         
396         else 
397                 if(Open->Filter != NULL)
398                 {
399                         if (Open->bpfprogram != NULL)
400                         {
401                                 fres=Open->Filter->Function(HeaderBuffer,
402                                                                         PacketSize+HeaderBufferSize,
403                                                                         LookaheadBufferSize+HeaderBufferSize);
404                 
405                                 // Restore the stack. 
406                                 // I ignore the reason, but this instruction is needed only at kernel level
407 #ifndef __GNUC__
408                                 _asm add esp,12         
409 #else
410                 asm("add $0x12,%esp;");
411 #endif
412                         }
413                         else
414                                 fres = -1;
415                 }
416                 else
417                         fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
418                                 HeaderBuffer,
419                                                 PacketSize+HeaderBufferSize,
420                                                 LookaheadBufferSize+HeaderBufferSize,
421                                                 &Open->mem_ex,
422                                                 &Open->tme,
423                                                 &G_Start_Time);
424
425         NdisReleaseSpinLock(&Open->machine_lock);
426         
427         if(Open->mode==MODE_MON)
428         // we are in monitor mode
429         {
430                 if (fres==1) 
431                         KeSetEvent(Open->ReadEvent,0,FALSE);
432                 return NDIS_STATUS_NOT_ACCEPTED;
433
434         }
435
436         if(fres==0)
437                 // Packet not accepted by the filter, ignore it.
438                 return NDIS_STATUS_NOT_ACCEPTED;
439
440         //if the filter returns -1 the whole packet must be accepted
441         if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize; 
442
443         if(Open->mode & MODE_STAT){
444         // we are in statistics mode
445                 NdisAcquireSpinLock( &Open->CountersLock );
446
447                 Open->Npackets.QuadPart++;
448                 
449                 if(PacketSize+HeaderBufferSize<60)
450                         Open->Nbytes.QuadPart+=60;
451                 else
452                         Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
453                 // add preamble+SFD+FCS to the packet
454                 // these values must be considered because are not part of the packet received from NDIS
455                 Open->Nbytes.QuadPart+=12;
456
457                 NdisReleaseSpinLock( &Open->CountersLock );
458                 
459                 if(!(Open->mode & MODE_DUMP)){
460                         return NDIS_STATUS_NOT_ACCEPTED;
461                 }
462         }
463
464         if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
465         
466         if(Open->mode & MODE_DUMP && Open->MaxDumpPacks &&      (UINT)Open->Accepted > Open->MaxDumpPacks){
467                 // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
468                 Open->DumpLimitReached = TRUE; // This stops the thread
469                 // Awake the dump thread
470                 NdisSetEvent(&Open->DumpEvent);
471
472                 // Awake the application
473                 KeSetEvent(Open->ReadEvent,0,FALSE);
474
475                 return NDIS_STATUS_NOT_ACCEPTED;
476         }
477
478         // Calculate the correct size for the header associated with the packet
479         NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
480  
481         NdisAcquireSpinLock( &Open->BufLock );
482
483         Thead=Open->Bhead;
484         Ttail=Open->Btail;
485         TLastByte = Open->BLastByte;
486
487         NdisReleaseSpinLock( &Open->BufLock );
488         
489         maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
490
491         if(Ttail+maxbufspace >= Open->BufSize){
492                 if(Thead <= maxbufspace)
493                 {
494                         Open->Dropped++;
495                         return NDIS_STATUS_NOT_ACCEPTED;
496                 }
497                 else{
498                         Ttail=0;
499                         ResetBuff = TRUE;
500                 }
501         }
502         
503         if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
504         {
505                 Open->Dropped++;
506                 return NDIS_STATUS_NOT_ACCEPTED;
507         }
508         
509         CurrBuff=Open->Buffer+Ttail;
510
511         if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
512         {
513                 //  Allocate an MDL to map the portion of the buffer following the header
514                 pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
515                         maxbufspace,
516                         FALSE,
517                         FALSE,
518                         NULL);
519
520                 if (pMdl == NULL)
521                 {
522                         // Unable to map the memory: packet lost
523                         IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
524                                 Open->Dropped++;
525                         return NDIS_STATUS_NOT_ACCEPTED;
526                 }
527                 MmBuildMdlForNonPagedPool(pMdl);
528                 
529                 //allocate the packet from NDIS
530                 NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
531                 if (Status != NDIS_STATUS_SUCCESS)
532                 {
533                         IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
534                         IoFreeMdl(pMdl);
535                         Open->Dropped++;
536                         return NDIS_STATUS_NOT_ACCEPTED;
537                 }
538                 //link the buffer to the packet
539                 NdisChainBufferAtFront(pPacketb,pMdl);
540                 
541                 BufferLength=fres-HeaderBufferSize;
542                 //Find out how much to transfer
543                 SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
544                 
545                 //copy the ethernet header into buffer
546                 NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
547                 
548                 //Copy the look ahead buffer
549                 if(LookaheadBufferSize)
550                 {
551                         NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
552                                 LookAheadBuffer, 
553                                 (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
554                         
555                         SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
556                                 SizeToTransfer - LookaheadBufferSize : 0;
557                 }
558                 
559                 Open->TransferMdl=pMdl;
560                 
561                 if(SizeToTransfer)
562                 {
563                         //Call the Mac to transfer the packet
564                         NdisTransferData(&Status,
565                                 Open->AdapterHandle,
566                                 MacReceiveContext,
567                                 LookaheadBufferSize,
568                                 SizeToTransfer,
569                                 pPacketb,
570                                 &BytesTransfered);
571                 }
572                 else{
573                         BytesTransfered = 0;
574                 }
575                 
576         }
577         else
578         {
579         // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
580         // This allows us to avoid the allocation of the MDL and the NDIS packet as well
581         RtlCopyMemory((CurrBuff) + NPFHdrSize,
582                 HeaderBuffer,
583                 HeaderBufferSize + LookaheadBufferSize);
584
585                 BytesTransfered = 0;
586
587                 Open->TransferMdl = NULL;
588                 Status = NDIS_STATUS_SUCCESS;
589         }
590
591         if (Status != NDIS_STATUS_FAILURE)
592         {
593
594                 Open->Accepted++;               // Increase the accepted packets counter
595
596                 if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
597                         fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
598                 
599                 //
600                 // Build the header
601                 //
602                 header=(struct bpf_hdr*)CurrBuff;
603                 GET_TIME(&header->bh_tstamp,&G_Start_Time);
604                 header->bh_caplen=fres;
605                 header->bh_datalen=PacketSize+HeaderBufferSize;
606                 if(Open->mode==MODE_CAPT){
607                         header->bh_hdrlen=NPFHdrSize;
608                         // Don't align if the packet goes to disk
609                         Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
610                 }
611                 else
612                         Ttail+=fres+NPFHdrSize;
613                 
614                 //update the buffer     
615                 NdisAcquireSpinLock( &Open->BufLock );
616                 
617                 if(ResetBuff){
618                         Open->BLastByte = Open->Btail;
619                 }
620                 Open->Btail=Ttail;
621                 
622                 NdisReleaseSpinLock( &Open->BufLock );
623         }
624
625         if (Status != NDIS_STATUS_PENDING){
626
627                 if( Open->TransferMdl != NULL)
628                         // Complete the request and free the buffers
629                         NPF_TransferDataComplete(Open,pPacketb,Status,fres);
630                 else{
631                         // Unfreeze the consumer
632                         if(GetBuffOccupation(Open)>Open->MinToCopy){
633                                 if(Open->mode & MODE_DUMP){
634                                         NdisSetEvent(&Open->DumpEvent);
635                                 }
636                                 else
637                                         KeSetEvent(Open->ReadEvent,0,FALSE);    
638                         }
639                         
640                 }
641         }
642         
643         return NDIS_STATUS_SUCCESS;
644         
645 }
646
647 //-------------------------------------------------------------------
648
649 VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
650                                  IN NDIS_STATUS Status,IN UINT BytesTransfered)
651 {
652     POPEN_INSTANCE      Open;
653
654     IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
655     
656         Open= (POPEN_INSTANCE)ProtocolBindingContext;
657
658         IoFreeMdl(Open->TransferMdl);
659         //recylcle the packet
660         NdisReinitializePacket(pPacket);
661         //Put the packet on the free queue
662         NdisFreePacket(pPacket);
663         // Unfreeze the consumer
664         if(GetBuffOccupation(Open)>Open->MinToCopy){
665                 if(Open->mode & MODE_DUMP){
666                         NdisSetEvent(&Open->DumpEvent);
667                 }
668                 else
669                         KeSetEvent(Open->ReadEvent,0,FALSE);    
670         }
671         return;
672 }
673
674 //-------------------------------------------------------------------
675
676 VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
677 {
678     IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
679     return;
680 }