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