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