- Merge aicom-network-fixes up to r36740
[reactos.git] / reactos / drivers / network / ndis / ndis / buffer.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/buffer.c
5 * PURPOSE: Buffer management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include <ndissys.h>
12
13
14 __inline ULONG SkipToOffset(
15 IN PNDIS_BUFFER Buffer,
16 IN UINT Offset,
17 IN OUT PUCHAR *Data,
18 IN OUT PUINT Size)
19 /*
20 * FUNCTION: Skips Offset bytes into a buffer chain
21 * ARGUMENTS:
22 * Buffer = Pointer to NDIS buffer
23 * Offset = Number of bytes to skip
24 * Data = Address of a pointer that on return will contain the
25 * address of the offset in the buffer
26 * Size = Address of a pointer that on return will contain the
27 * size of the destination buffer
28 * RETURNS:
29 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
30 * NOTES:
31 * Buffer may be NULL
32 */
33 {
34 for (;;) {
35
36 if (!Buffer)
37 return 0xFFFFFFFF;
38
39 NdisQueryBuffer(Buffer, (PVOID)Data, Size);
40
41 if (Offset < *Size) {
42 *Data = (PUCHAR) ((ULONG_PTR) *Data + Offset);
43 *Size -= Offset;
44 break;
45 }
46
47 Offset -= *Size;
48
49 NdisGetNextBuffer(Buffer, &Buffer);
50 }
51
52 return Offset;
53 }
54
55 UINT CopyBufferToBufferChain(
56 PNDIS_BUFFER DstBuffer,
57 UINT DstOffset,
58 PUCHAR SrcData,
59 UINT Length)
60 /*
61 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
62 * ARGUMENTS:
63 * DstBuffer = Pointer to destination NDIS buffer
64 * DstOffset = Destination start offset
65 * SrcData = Pointer to source buffer
66 * Length = Number of bytes to copy
67 * RETURNS:
68 * Number of bytes copied to destination buffer
69 * NOTES:
70 * The number of bytes copied may be limited by the destination
71 * buffer size
72 */
73 {
74 UINT BytesCopied, BytesToCopy, DstSize;
75 PUCHAR DstData;
76
77 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
78
79 /* Skip DstOffset bytes in the destination buffer chain */
80 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
81 return 0;
82
83 /* Start copying the data */
84 BytesCopied = 0;
85 for (;;) {
86 BytesToCopy = MIN(DstSize, Length);
87
88 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
89 BytesCopied += BytesToCopy;
90 SrcData = (PUCHAR) ((ULONG_PTR) SrcData + BytesToCopy);
91
92 Length -= BytesToCopy;
93 if (Length == 0)
94 break;
95
96 DstSize -= BytesToCopy;
97 if (DstSize == 0) {
98 /* No more bytes in desination buffer. Proceed to
99 the next buffer in the destination buffer chain */
100 NdisGetNextBuffer(DstBuffer, &DstBuffer);
101 if (!DstBuffer)
102 break;
103
104 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
105 }
106 }
107
108 return BytesCopied;
109 }
110
111
112 UINT CopyBufferChainToBuffer(
113 PUCHAR DstData,
114 PNDIS_BUFFER SrcBuffer,
115 UINT SrcOffset,
116 UINT Length)
117 /*
118 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
119 * ARGUMENTS:
120 * DstData = Pointer to destination buffer
121 * SrcBuffer = Pointer to source NDIS buffer
122 * SrcOffset = Source start offset
123 * Length = Number of bytes to copy
124 * RETURNS:
125 * Number of bytes copied to destination buffer
126 * NOTES:
127 * The number of bytes copied may be limited by the source
128 * buffer size
129 */
130 {
131 UINT BytesCopied, BytesToCopy, SrcSize;
132 PUCHAR SrcData;
133
134 NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
135
136 /* Skip SrcOffset bytes in the source buffer chain */
137 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
138 return 0;
139
140 /* Start copying the data */
141 BytesCopied = 0;
142 for (;;) {
143 BytesToCopy = MIN(SrcSize, Length);
144
145 NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
146
147 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
148 BytesCopied += BytesToCopy;
149 DstData = (PUCHAR)((ULONG_PTR) DstData + BytesToCopy);
150
151 Length -= BytesToCopy;
152 if (Length == 0)
153 break;
154
155 SrcSize -= BytesToCopy;
156 if (SrcSize == 0) {
157 /* No more bytes in source buffer. Proceed to
158 the next buffer in the source buffer chain */
159 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
160 if (!SrcBuffer)
161 break;
162
163 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
164 }
165 }
166
167 return BytesCopied;
168 }
169
170
171 UINT CopyPacketToBuffer(
172 PUCHAR DstData,
173 PNDIS_PACKET SrcPacket,
174 UINT SrcOffset,
175 UINT Length)
176 /*
177 * FUNCTION: Copies data from an NDIS packet to a buffer
178 * ARGUMENTS:
179 * DstData = Pointer to destination buffer
180 * SrcPacket = Pointer to source NDIS packet
181 * SrcOffset = Source start offset
182 * Length = Number of bytes to copy
183 * RETURNS:
184 * Number of bytes copied to destination buffer
185 * NOTES:
186 * The number of bytes copied may be limited by the source
187 * buffer size
188 */
189 {
190 PNDIS_BUFFER FirstBuffer;
191 PVOID Address;
192 UINT FirstLength;
193 UINT TotalLength;
194
195 NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
196
197 NdisGetFirstBufferFromPacket(SrcPacket,
198 &FirstBuffer,
199 &Address,
200 &FirstLength,
201 &TotalLength);
202
203 return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
204 }
205
206
207 UINT CopyPacketToBufferChain(
208 PNDIS_BUFFER DstBuffer,
209 UINT DstOffset,
210 PNDIS_PACKET SrcPacket,
211 UINT SrcOffset,
212 UINT Length)
213 /*
214 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
215 * ARGUMENTS:
216 * DstBuffer = Pointer to destination NDIS buffer
217 * DstOffset = Destination start offset
218 * SrcPacket = Pointer to source NDIS packet
219 * SrcOffset = Source start offset
220 * Length = Number of bytes to copy
221 * RETURNS:
222 * Number of bytes copied to destination buffer
223 * NOTES:
224 * The number of bytes copied may be limited by the source and
225 * destination buffer sizes
226 */
227 {
228 PNDIS_BUFFER SrcBuffer;
229 PUCHAR DstData, SrcData;
230 UINT DstSize, SrcSize;
231 UINT Count, Total;
232
233 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));
234
235 /* Skip DstOffset bytes in the destination buffer chain */
236 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
237 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
238 return 0;
239 /* Skip SrcOffset bytes in the source packet */
240 NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total);
241 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
242 return 0;
243 /* Copy the data */
244 for (Total = 0;;) {
245 /* Find out how many bytes we can copy at one time */
246 if (Length < SrcSize)
247 Count = Length;
248 else
249 Count = SrcSize;
250 if (DstSize < Count)
251 Count = DstSize;
252
253 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
254
255 Total += Count;
256 Length -= Count;
257 if (Length == 0)
258 break;
259
260 DstSize -= Count;
261 if (DstSize == 0) {
262 /* No more bytes in destination buffer. Proceed to
263 the next buffer in the destination buffer chain */
264 NdisGetNextBuffer(DstBuffer, &DstBuffer);
265 if (!DstBuffer)
266 break;
267
268 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
269 }
270
271 SrcSize -= Count;
272 if (SrcSize == 0) {
273 /* No more bytes in source buffer. Proceed to
274 the next buffer in the source buffer chain */
275 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
276 if (!SrcBuffer)
277 break;
278
279 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
280 }
281 }
282
283 return Total;
284 }
285
286
287 /*
288 * @implemented
289 */
290 #undef NdisAdjustBufferLength
291 VOID
292 EXPORT
293 NdisAdjustBufferLength(
294 IN PNDIS_BUFFER Buffer,
295 IN UINT Length)
296 /*
297 * FUNCTION: Modifies the length of an NDIS buffer
298 * ARGUMENTS:
299 * Buffer = Pointer to NDIS buffer descriptor
300 * Length = New size of buffer
301 */
302 {
303 Buffer->ByteCount = Length;
304 }
305
306
307 /*
308 * @implemented
309 */
310 #undef NDIS_BUFFER_TO_SPAN_PAGES
311 ULONG
312 EXPORT
313 NDIS_BUFFER_TO_SPAN_PAGES(
314 IN PNDIS_BUFFER Buffer)
315 /*
316 * FUNCTION: Determines how many physical pages a buffer is made of
317 * ARGUMENTS:
318 * Buffer = Pointer to NDIS buffer descriptor
319 */
320 {
321 if (MmGetMdlByteCount(Buffer) == 0)
322 return 1;
323
324 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
325 MmGetMdlVirtualAddress(Buffer),
326 MmGetMdlByteCount(Buffer));
327 }
328
329
330 /*
331 * @implemented
332 */
333 VOID
334 EXPORT
335 NdisAllocateBuffer(
336 OUT PNDIS_STATUS Status,
337 OUT PNDIS_BUFFER * Buffer,
338 IN NDIS_HANDLE PoolHandle,
339 IN PVOID VirtualAddress,
340 IN UINT Length)
341 /*
342 * FUNCTION: Allocates an NDIS buffer descriptor
343 * ARGUMENTS:
344 * Status = Address of buffer for status
345 * Buffer = Address of buffer for NDIS buffer descriptor
346 * PoolHandle = Handle returned by NdisAllocateBufferPool
347 * VirtualAddress = Pointer to virtual address of data buffer
348 * Length = Number of bytes in data buffer
349 */
350 {
351 ASSERT(VirtualAddress != NULL);
352 ASSERT(Length > 0);
353
354 *Buffer = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL);
355 if (*Buffer != NULL) {
356 MmBuildMdlForNonPagedPool(*Buffer);
357 (*Buffer)->Next = NULL;
358 *Status = NDIS_STATUS_SUCCESS;
359 } else {
360 *Status = NDIS_STATUS_FAILURE;
361 }
362 }
363
364
365 /*
366 * @implemented
367 */
368 VOID
369 EXPORT
370 NdisAllocateBufferPool(
371 OUT PNDIS_STATUS Status,
372 OUT PNDIS_HANDLE PoolHandle,
373 IN UINT NumberOfDescriptors)
374 /*
375 * FUNCTION: Allocates storage for an NDIS buffer pool
376 * ARGUMENTS:
377 * Status = Address of buffer for status
378 * PoolHandle = Address of buffer for pool handle
379 * NumberOfDescriptors = Size of buffer pool in number of descriptors
380 */
381 {
382 *Status = NDIS_STATUS_SUCCESS;
383 *PoolHandle = 0;
384 }
385
386
387 /*
388 * @implemented
389 */
390 VOID
391 EXPORT
392 NdisAllocatePacket(
393 OUT PNDIS_STATUS Status,
394 OUT PNDIS_PACKET * Packet,
395 IN NDIS_HANDLE PoolHandle)
396 /*
397 * FUNCTION: Allocates an NDIS packet descriptor
398 * ARGUMENTS:
399 * Status = Address of buffer for status
400 * Packet = Address of buffer for packet descriptor
401 * PoolHandle = Handle returned by NdisAllocatePacketPool
402 */
403 {
404 KIRQL OldIrql;
405 PNDIS_PACKET Temp;
406 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
407
408 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
409 Status, Packet, PoolHandle));
410
411 *Packet = NULL;
412
413 if (Pool == NULL)
414 {
415 *Status = NDIS_STATUS_FAILURE;
416 return;
417 }
418
419 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
420
421 if (Pool->FreeList) {
422 Temp = Pool->FreeList;
423 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
424
425 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
426
427 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
428 Temp->Private.Pool = Pool;
429
430 *Packet = Temp;
431 *Status = NDIS_STATUS_SUCCESS;
432 } else {
433 *Status = NDIS_STATUS_RESOURCES;
434 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
435 }
436 }
437
438
439 /*
440 * @implemented
441 */
442 VOID
443 EXPORT
444 NdisAllocatePacketPool(
445 OUT PNDIS_STATUS Status,
446 OUT PNDIS_HANDLE PoolHandle,
447 IN UINT NumberOfDescriptors,
448 IN UINT ProtocolReservedLength)
449 /*
450 * FUNCTION: Allocates storage for an NDIS packet pool
451 * ARGUMENTS:
452 * Status = Address of buffer for status
453 * PoolHandle = Address of buffer for pool handle
454 * NumberOfDescriptors = Size of packet pool in number of descriptors
455 * ProtocolReservedLength = Size of protocol reserved area in bytes
456 */
457 {
458 NdisAllocatePacketPoolEx(
459 Status,
460 PoolHandle,
461 NumberOfDescriptors,
462 0,
463 ProtocolReservedLength);
464 }
465
466
467 /*
468 * @implemented
469 */
470 VOID
471 EXPORT
472 NdisAllocatePacketPoolEx(
473 OUT PNDIS_STATUS Status,
474 OUT PNDIS_HANDLE PoolHandle,
475 IN UINT NumberOfDescriptors,
476 IN UINT NumberOfOverflowDescriptors,
477 IN UINT ProtocolReservedLength)
478 /*
479 * FUNCTION:
480 * ARGUMENTS:
481 * NOTES:
482 * NDIS 5.0
483 */
484 {
485 PNDISI_PACKET_POOL Pool;
486 UINT Size, Length, i;
487 PNDIS_PACKET Packet, NextPacket;
488
489 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) "
490 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
491 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
492
493 *PoolHandle = NULL;
494
495 if (NumberOfDescriptors > 0xffff)
496 {
497 *Status = NDIS_STATUS_RESOURCES;
498 }
499 else
500 {
501 NumberOfDescriptors += NumberOfOverflowDescriptors;
502 if (NumberOfDescriptors > 0xffff)
503 {
504 NumberOfDescriptors = 0xffff;
505 }
506
507 Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
508 Size = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors;
509
510 Pool = ExAllocatePool(NonPagedPool, Size);
511 if (Pool)
512 {
513 KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
514 Pool->PacketLength = Length;
515
516 if (NumberOfDescriptors > 0)
517 {
518 Packet = (PNDIS_PACKET)&Pool->Buffer;
519 Pool->FreeList = Packet;
520
521 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
522 for (i = 1; i < NumberOfDescriptors; i++)
523 {
524 Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
525 Packet = NextPacket;
526 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
527 }
528 Packet->Private.Head = NULL;
529 }
530 else
531 Pool->FreeList = NULL;
532
533 *Status = NDIS_STATUS_SUCCESS;
534 *PoolHandle = (PNDIS_HANDLE)Pool;
535 } else {
536 *Status = NDIS_STATUS_RESOURCES;
537 }
538 }
539 }
540
541
542 /*
543 * @implemented
544 */
545 #undef NdisBufferLength
546 ULONG
547 EXPORT
548 NdisBufferLength(
549 IN PNDIS_BUFFER Buffer)
550 /*
551 * FUNCTION: Modifies the length of an NDIS buffer
552 * ARGUMENTS:
553 * Buffer = Pointer to NDIS buffer descriptor
554 * Length = New size of buffer
555 * NOTES:
556 * NDIS 5.0
557 * RETURNS:
558 * Length of NDIS buffer
559 */
560 {
561 return MmGetMdlByteCount(Buffer);
562 }
563
564
565 /*
566 * @implemented
567 */
568 #undef NdisBufferVirtualAddress
569 PVOID
570 EXPORT
571 NdisBufferVirtualAddress(
572 IN PNDIS_BUFFER Buffer)
573 /*
574 * FUNCTION:
575 * ARGUMENTS:
576 * NOTES:
577 * NDIS 5.0
578 */
579 {
580 return MmGetSystemAddressForMdl(Buffer);
581 }
582
583
584 /*
585 * @unimplemented
586 */
587 VOID
588 EXPORT
589 NdisCopyBuffer(
590 OUT PNDIS_STATUS Status,
591 OUT PNDIS_BUFFER *Buffer,
592 IN NDIS_HANDLE PoolHandle,
593 IN PVOID MemoryDescriptor,
594 IN UINT Offset,
595 IN UINT Length)
596 /*
597 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
598 * ARGUMENTS:
599 * Status = Address of a buffer to place status of operation
600 * Buffer = Address of a buffer to place new buffer descriptor
601 * PoolHandle = Handle returned by NdisAllocateBufferPool
602 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
603 * Offset = Offset in buffer to start copying
604 * Length = Number of bytes to copy
605 */
606 {
607 *Status = NDIS_STATUS_FAILURE;
608 }
609
610
611 /*
612 * @implemented
613 */
614 VOID
615 EXPORT
616 NdisCopyFromPacketToPacket(
617 IN PNDIS_PACKET Destination,
618 IN UINT DestinationOffset,
619 IN UINT BytesToCopy,
620 IN PNDIS_PACKET Source,
621 IN UINT SourceOffset,
622 OUT PUINT BytesCopied)
623 /*
624 * FUNCTION: Copies data from one packet to another
625 * ARGUMENTS:
626 * Destination = Pointer to packet to copy data to
627 * DestinationOffset = Offset in destination packet to copy data to
628 * BytesToCopy = Number of bytes to copy
629 * Source = Pointer to packet descriptor to copy from
630 * SourceOffset = Offset in source packet to start copying from
631 * BytesCopied = Address of buffer to place number of bytes copied
632 */
633 {
634 PNDIS_BUFFER SrcBuffer;
635 PNDIS_BUFFER DstBuffer;
636 PUCHAR DstData, SrcData;
637 UINT DstSize, SrcSize;
638 UINT Count, Total;
639
640 *BytesCopied = 0;
641
642 /* Skip DestinationOffset bytes in the destination packet */
643 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total);
644 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
645 return;
646
647 /* Skip SourceOffset bytes in the source packet */
648 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total);
649 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
650 return;
651
652 /* Copy the data */
653 for (Total = 0;;) {
654 /* Find out how many bytes we can copy at one time */
655 if (BytesToCopy < SrcSize)
656 Count = BytesToCopy;
657 else
658 Count = SrcSize;
659 if (DstSize < Count)
660 Count = DstSize;
661
662 RtlCopyMemory(DstData, SrcData, Count);
663
664 Total += Count;
665 BytesToCopy -= Count;
666 if (BytesToCopy == 0)
667 break;
668
669 DstSize -= Count;
670 if (DstSize == 0) {
671 /* No more bytes in destination buffer. Proceed to
672 the next buffer in the destination buffer chain */
673 NdisGetNextBuffer(DstBuffer, &DstBuffer);
674 if (!DstBuffer)
675 break;
676
677 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
678 }
679
680 SrcSize -= Count;
681 if (SrcSize == 0) {
682 /* No more bytes in source buffer. Proceed to
683 the next buffer in the source buffer chain */
684 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
685 if (!SrcBuffer)
686 break;
687
688 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
689 }
690 }
691
692 *BytesCopied = Total;
693 }
694
695
696 /*
697 * @implemented
698 */
699 VOID
700 EXPORT
701 NdisDprAllocatePacket(
702 OUT PNDIS_STATUS Status,
703 OUT PNDIS_PACKET *Packet,
704 IN NDIS_HANDLE PoolHandle)
705 /*
706 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
707 * ARGUMENTS:
708 * Status = Address of buffer to place status of operation
709 * Packet = Address of buffer to place a pointer to a packet descriptor
710 * PoolHandle = Handle returned by NdisAllocatePacketPool
711 */
712 {
713 PNDIS_PACKET Temp;
714 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
715
716 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
717 Status, Packet, PoolHandle));
718
719 *Packet = NULL;
720
721 if (Pool == NULL)
722 {
723 *Status = NDIS_STATUS_FAILURE;
724 return;
725 }
726
727 KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock);
728
729 if (Pool->FreeList) {
730 Temp = Pool->FreeList;
731 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
732
733 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
734
735 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
736 Temp->Private.Pool = Pool;
737
738 *Packet = Temp;
739 *Status = NDIS_STATUS_SUCCESS;
740 } else {
741 *Status = NDIS_STATUS_RESOURCES;
742 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
743 }
744 }
745
746
747 /*
748 * @implemented
749 */
750 VOID
751 EXPORT
752 NdisDprAllocatePacketNonInterlocked(
753 OUT PNDIS_STATUS Status,
754 OUT PNDIS_PACKET *Packet,
755 IN NDIS_HANDLE PoolHandle)
756 /*
757 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
758 * ARGUMENTS:
759 * Status = Address of buffer to place status of operation
760 * Packet = Address of buffer to place a pointer to a packet descriptor
761 * PoolHandle = Handle returned by NdisAllocatePacketPool
762 */
763 {
764 PNDIS_PACKET Temp;
765 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
766
767 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
768 Status, Packet, PoolHandle));
769
770 *Packet = NULL;
771
772 if (Pool == NULL)
773 {
774 *Status = NDIS_STATUS_FAILURE;
775 return;
776 }
777
778 if (Pool->FreeList) {
779 Temp = Pool->FreeList;
780 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
781
782 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
783 Temp->Private.Pool = Pool;
784
785 *Packet = Temp;
786 *Status = NDIS_STATUS_SUCCESS;
787 } else {
788 *Status = NDIS_STATUS_RESOURCES;
789 }
790 }
791
792
793 /*
794 * @implemented
795 */
796 VOID
797 EXPORT
798 NdisDprFreePacket(
799 IN PNDIS_PACKET Packet)
800 /*
801 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
802 * ARGUMENTS:
803 * Packet = Pointer to packet to free
804 */
805 {
806 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
807
808 KeAcquireSpinLockAtDpcLevel(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock);
809 Packet->Private.Head = (PNDIS_BUFFER)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
810 ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
811 KeReleaseSpinLockFromDpcLevel(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock);
812 }
813
814
815 /*
816 * @implemented
817 */
818 VOID
819 EXPORT
820 NdisDprFreePacketNonInterlocked(
821 IN PNDIS_PACKET Packet)
822 /*
823 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
824 * ARGUMENTS:
825 * Packet = Pointer to packet to free
826 */
827 {
828 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
829
830 Packet->Private.Head = (PNDIS_BUFFER)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
831 ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
832 }
833
834
835 /*
836 * @implemented
837 */
838 VOID
839 EXPORT
840 NdisFreeBufferPool(
841 IN NDIS_HANDLE PoolHandle)
842 /*
843 * FUNCTION: Frees storage allocated for an NDIS buffer pool
844 * ARGUMENTS:
845 * PoolHandle = Handle returned by NdisAllocateBufferPool
846 */
847 {
848 }
849
850
851 /*
852 * @implemented
853 */
854 VOID
855 EXPORT
856 NdisFreePacketPool(
857 IN NDIS_HANDLE PoolHandle)
858 /*
859 * FUNCTION: Frees storage allocated for an NDIS packet pool
860 * ARGUMENTS:
861 * PoolHandle = Handle returned by NdisAllocatePacketPool
862 */
863 {
864 ExFreePool((PVOID)PoolHandle);
865 }
866
867
868 /*
869 * @implemented
870 */
871 #undef NdisFreeBuffer
872 VOID
873 EXPORT
874 NdisFreeBuffer(
875 IN PNDIS_BUFFER Buffer)
876 /*
877 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
878 * ARGUMENTS:
879 * Buffer = Pointer to buffer descriptor
880 */
881 {
882 IoFreeMdl(Buffer);
883 }
884
885
886 /*
887 * @implemented
888 */
889 VOID
890 EXPORT
891 NdisFreePacket(
892 IN PNDIS_PACKET Packet)
893 /*
894 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
895 * ARGUMENTS:
896 * Packet = Pointer to packet descriptor
897 */
898 {
899 KIRQL OldIrql;
900
901 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
902
903 KeAcquireSpinLock(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock, &OldIrql);
904 Packet->Private.Head = (PNDIS_BUFFER)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
905 ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
906 KeReleaseSpinLock(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock, OldIrql);
907 }
908
909
910 /*
911 * @implemented
912 */
913 #undef NdisGetBufferPhysicalArraySize
914 VOID
915 EXPORT
916 NdisGetBufferPhysicalArraySize(
917 IN PNDIS_BUFFER Buffer,
918 OUT PUINT ArraySize)
919 /*
920 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
921 * ARGUMENTS:
922 * Buffer = Pointer to buffer descriptor
923 * ArraySize = Address of buffer to place number of physical blocks
924 */
925 {
926 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
927 ASSERT(Buffer && ArraySize);
928
929 *ArraySize = NDIS_BUFFER_TO_SPAN_PAGES(Buffer);
930 }
931
932
933 /*
934 * @implemented
935 */
936 #undef NdisGetFirstBufferFromPacket
937 VOID
938 EXPORT
939 NdisGetFirstBufferFromPacket(
940 IN PNDIS_PACKET _Packet,
941 OUT PNDIS_BUFFER *_FirstBuffer,
942 OUT PVOID *_FirstBufferVA,
943 OUT PUINT _FirstBufferLength,
944 OUT PUINT _TotalBufferLength)
945 /*
946 * FUNCTION: Retrieves information about an NDIS packet
947 * ARGUMENTS:
948 * _Packet = Pointer to NDIS packet
949 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
950 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
951 * _FirstBufferLength = Address of buffer for length of first buffer
952 * _TotalBufferLength = Address of buffer for total length of packet
953 */
954 {
955 PNDIS_BUFFER Buffer;
956
957 Buffer = _Packet->Private.Head;
958 *_FirstBuffer = Buffer;
959
960 if (Buffer != NULL) {
961 *_FirstBufferLength = MmGetMdlByteCount(Buffer);
962 *_FirstBufferVA = MmGetSystemAddressForMdl(Buffer);
963 Buffer = Buffer->Next;
964 } else {
965 *_FirstBufferLength = 0;
966 *_FirstBufferVA = NULL;
967 }
968
969 *_TotalBufferLength = *_FirstBufferLength;
970
971 while (Buffer != NULL) {
972 *_TotalBufferLength += MmGetMdlByteCount(Buffer);
973 Buffer = Buffer->Next;
974 }
975 }
976
977
978 /*
979 * @unimplemented
980 */
981 VOID
982 EXPORT
983 NdisReturnPackets(
984 IN PNDIS_PACKET *PacketsToReturn,
985 IN UINT NumberOfPackets)
986 /*
987 * FUNCTION: Releases ownership of one or more packets
988 * ARGUMENTS:
989 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
990 * NumberOfPackets = Number of pointers in descriptor pointer array
991 */
992 {
993 UNIMPLEMENTED
994 }
995
996
997 /*
998 * @unimplemented
999 */
1000 UINT
1001 EXPORT
1002 NdisPacketPoolUsage(
1003 IN NDIS_HANDLE PoolHandle)
1004 /*
1005 * FUNCTION:
1006 * ARGUMENTS:
1007 * NOTES:
1008 * NDIS 5.0
1009 */
1010 {
1011 UNIMPLEMENTED
1012
1013 return 0;
1014 }
1015
1016
1017 /*
1018 * @implemented
1019 */
1020 #undef NdisQueryBuffer
1021 VOID
1022 EXPORT
1023 NdisQueryBuffer(
1024 IN PNDIS_BUFFER Buffer,
1025 OUT PVOID *VirtualAddress OPTIONAL,
1026 OUT PUINT Length)
1027 /*
1028 * FUNCTION:
1029 * Queries an NDIS buffer for information
1030 * ARGUMENTS:
1031 * Buffer = Pointer to NDIS buffer to query
1032 * VirtualAddress = Address of buffer to place virtual address
1033 * Length = Address of buffer to place length of buffer
1034 */
1035 {
1036 if (VirtualAddress != NULL)
1037 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
1038
1039 *Length = MmGetMdlByteCount(Buffer);
1040 }
1041
1042
1043 /*
1044 * @implemented
1045 */
1046 #undef NdisQueryBufferSafe
1047 VOID
1048 EXPORT
1049 NdisQueryBufferSafe(
1050 IN PNDIS_BUFFER Buffer,
1051 OUT PVOID *VirtualAddress OPTIONAL,
1052 OUT PUINT Length,
1053 IN UINT Priority)
1054 /*
1055 * FUNCTION:
1056 * ARGUMENTS:
1057 * NOTES:
1058 * NDIS 5.0
1059 */
1060 {
1061 if (VirtualAddress != NULL)
1062 *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority);
1063 *Length = MmGetMdlByteCount(Buffer);
1064 }
1065
1066
1067 /*
1068 * @implemented
1069 */
1070 #undef NdisQueryBufferOffset
1071 VOID
1072 EXPORT
1073 NdisQueryBufferOffset(
1074 IN PNDIS_BUFFER Buffer,
1075 OUT PUINT Offset,
1076 OUT PUINT Length)
1077 {
1078 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer);
1079 *((PUINT)Length) = MmGetMdlByteCount(Buffer);
1080 }
1081
1082
1083 /*
1084 * @implemented
1085 */
1086 VOID
1087 EXPORT
1088 NdisUnchainBufferAtBack(
1089 IN OUT PNDIS_PACKET Packet,
1090 OUT PNDIS_BUFFER *Buffer)
1091 /*
1092 * FUNCTION:
1093 * Removes the last buffer in a packet
1094 * ARGUMENTS:
1095 * Packet = Pointer to NDIS packet
1096 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1097 */
1098 {
1099 PNDIS_BUFFER NdisBuffer, Previous;
1100
1101 NdisQueryPacket(Packet,
1102 NULL,
1103 NULL,
1104 &NdisBuffer,
1105 NULL);
1106 if (!NdisBuffer) {
1107 *Buffer = NULL;
1108 return;
1109 }
1110
1111 Previous = NULL;
1112 while (NdisBuffer->Next) {
1113 Previous = NdisBuffer;
1114 NdisBuffer = NdisBuffer->Next;
1115 }
1116
1117 if (Previous) {
1118 Previous->Next = NULL;
1119 Packet->Private.Tail = Previous;
1120 } else {
1121 Packet->Private.Head = NULL;
1122 Packet->Private.Tail = NULL;
1123 }
1124
1125 Packet->Private.ValidCounts = FALSE;
1126
1127 *Buffer = NdisBuffer;
1128 }
1129
1130
1131 /*
1132 * @implemented
1133 */
1134 VOID
1135 EXPORT
1136 NdisUnchainBufferAtFront(
1137 IN OUT PNDIS_PACKET Packet,
1138 OUT PNDIS_BUFFER *Buffer)
1139 /*
1140 * FUNCTION:
1141 * Removes the first buffer in a packet
1142 * ARGUMENTS:
1143 * Packet = Pointer to NDIS packet
1144 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1145 */
1146 {
1147 PNDIS_BUFFER NdisBuffer;
1148
1149 NdisQueryPacket(Packet,
1150 NULL,
1151 NULL,
1152 &NdisBuffer,
1153 NULL);
1154 if (!NdisBuffer) {
1155 *Buffer = NULL;
1156 return;
1157 }
1158
1159 Packet->Private.Head = NdisBuffer->Next;
1160
1161 if (!NdisBuffer->Next)
1162 Packet->Private.Tail = NULL;
1163
1164 NdisBuffer->Next = NULL;
1165
1166 Packet->Private.ValidCounts = FALSE;
1167
1168 *Buffer = NdisBuffer;
1169 }
1170
1171 /* EOF */