2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: Buffer management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
14 __inline ULONG
SkipToOffset(
15 IN PNDIS_BUFFER Buffer
,
20 * FUNCTION: Skips Offset bytes into a buffer chain
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
29 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
39 NdisQueryBuffer(Buffer
, (PVOID
)Data
, Size
);
42 *Data
= (PUCHAR
) ((ULONG_PTR
) *Data
+ Offset
);
49 NdisGetNextBuffer(Buffer
, &Buffer
);
55 UINT
CopyBufferToBufferChain(
56 PNDIS_BUFFER DstBuffer
,
61 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
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
68 * Number of bytes copied to destination buffer
70 * The number of bytes copied may be limited by the destination
74 UINT BytesCopied
, BytesToCopy
, DstSize
;
77 NDIS_DbgPrint(MAX_TRACE
, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer
, DstOffset
, SrcData
, Length
));
79 /* Skip DstOffset bytes in the destination buffer chain */
80 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
83 /* Start copying the data */
86 BytesToCopy
= MIN(DstSize
, Length
);
88 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
89 BytesCopied
+= BytesToCopy
;
90 SrcData
= (PUCHAR
) ((ULONG_PTR
) SrcData
+ BytesToCopy
);
92 Length
-= BytesToCopy
;
96 DstSize
-= BytesToCopy
;
98 /* No more bytes in desination buffer. Proceed to
99 the next buffer in the destination buffer chain */
100 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
104 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
112 UINT
CopyBufferChainToBuffer(
114 PNDIS_BUFFER SrcBuffer
,
118 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
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
125 * Number of bytes copied to destination buffer
127 * The number of bytes copied may be limited by the source
131 UINT BytesCopied
, BytesToCopy
, SrcSize
;
134 NDIS_DbgPrint(MAX_TRACE
, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData
,SrcBuffer
, SrcOffset
, Length
));
136 /* Skip SrcOffset bytes in the source buffer chain */
137 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
140 /* Start copying the data */
143 BytesToCopy
= MIN(SrcSize
, Length
);
145 NDIS_DbgPrint(MAX_TRACE
, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy
, SrcData
, DstData
));
147 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
148 BytesCopied
+= BytesToCopy
;
149 DstData
= (PUCHAR
)((ULONG_PTR
) DstData
+ BytesToCopy
);
151 Length
-= BytesToCopy
;
155 SrcSize
-= BytesToCopy
;
157 /* No more bytes in source buffer. Proceed to
158 the next buffer in the source buffer chain */
159 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
163 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
171 UINT
CopyPacketToBuffer(
173 PNDIS_PACKET SrcPacket
,
177 * FUNCTION: Copies data from an NDIS packet to a buffer
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
184 * Number of bytes copied to destination buffer
186 * The number of bytes copied may be limited by the source
190 PNDIS_BUFFER FirstBuffer
;
195 NDIS_DbgPrint(MAX_TRACE
, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData
, SrcPacket
, SrcOffset
, Length
));
197 NdisGetFirstBufferFromPacket(SrcPacket
,
203 return CopyBufferChainToBuffer(DstData
, FirstBuffer
, SrcOffset
, Length
);
207 UINT
CopyPacketToBufferChain(
208 PNDIS_BUFFER DstBuffer
,
210 PNDIS_PACKET SrcPacket
,
214 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
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
222 * Number of bytes copied to destination buffer
224 * The number of bytes copied may be limited by the source and
225 * destination buffer sizes
228 PNDIS_BUFFER SrcBuffer
;
229 PUCHAR DstData
, SrcData
;
230 UINT DstSize
, SrcSize
;
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
));
235 /* Skip DstOffset bytes in the destination buffer chain */
236 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
237 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
239 /* Skip SrcOffset bytes in the source packet */
240 NdisGetFirstBufferFromPacket(SrcPacket
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
);
241 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
245 /* Find out how many bytes we can copy at one time */
246 if (Length
< SrcSize
)
253 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, Count
);
262 /* No more bytes in destination buffer. Proceed to
263 the next buffer in the destination buffer chain */
264 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
268 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
273 /* No more bytes in source buffer. Proceed to
274 the next buffer in the source buffer chain */
275 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
279 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
290 #undef NdisAdjustBufferLength
293 NdisAdjustBufferLength(
294 IN PNDIS_BUFFER Buffer
,
297 * FUNCTION: Modifies the length of an NDIS buffer
299 * Buffer = Pointer to NDIS buffer descriptor
300 * Length = New size of buffer
303 Buffer
->ByteCount
= Length
;
310 #undef NDIS_BUFFER_TO_SPAN_PAGES
313 NDIS_BUFFER_TO_SPAN_PAGES(
314 IN PNDIS_BUFFER Buffer
)
316 * FUNCTION: Determines how many physical pages a buffer is made of
318 * Buffer = Pointer to NDIS buffer descriptor
321 if (MmGetMdlByteCount(Buffer
) == 0)
324 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
325 MmGetMdlVirtualAddress(Buffer
),
326 MmGetMdlByteCount(Buffer
));
336 OUT PNDIS_STATUS Status
,
337 OUT PNDIS_BUFFER
* Buffer
,
338 IN NDIS_HANDLE PoolHandle
,
339 IN PVOID VirtualAddress
,
342 * FUNCTION: Allocates an NDIS buffer descriptor
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
351 ASSERT(VirtualAddress
!= NULL
);
354 *Buffer
= IoAllocateMdl(VirtualAddress
, Length
, FALSE
, FALSE
, NULL
);
355 if (*Buffer
!= NULL
) {
356 MmBuildMdlForNonPagedPool(*Buffer
);
357 (*Buffer
)->Next
= NULL
;
358 *Status
= NDIS_STATUS_SUCCESS
;
360 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress
, Length
));
361 *Status
= NDIS_STATUS_FAILURE
;
371 NdisAllocateBufferPool(
372 OUT PNDIS_STATUS Status
,
373 OUT PNDIS_HANDLE PoolHandle
,
374 IN UINT NumberOfDescriptors
)
376 * FUNCTION: Allocates storage for an NDIS buffer pool
378 * Status = Address of buffer for status
379 * PoolHandle = Address of buffer for pool handle
380 * NumberOfDescriptors = Size of buffer pool in number of descriptors
383 *Status
= NDIS_STATUS_SUCCESS
;
394 OUT PNDIS_STATUS Status
,
395 OUT PNDIS_PACKET
* Packet
,
396 IN NDIS_HANDLE PoolHandle
)
398 * FUNCTION: Allocates an NDIS packet descriptor
400 * Status = Address of buffer for status
401 * Packet = Address of buffer for packet descriptor
402 * PoolHandle = Handle returned by NdisAllocatePacketPool
405 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
407 KeAcquireSpinLock(&Pool
->SpinLock
.SpinLock
, &Pool
->SpinLock
.OldIrql
);
408 NdisDprAllocatePacketNonInterlocked(Status
,
411 KeReleaseSpinLock(&Pool
->SpinLock
.SpinLock
, Pool
->SpinLock
.OldIrql
);
420 NdisAllocatePacketPool(
421 OUT PNDIS_STATUS Status
,
422 OUT PNDIS_HANDLE PoolHandle
,
423 IN UINT NumberOfDescriptors
,
424 IN UINT ProtocolReservedLength
)
426 * FUNCTION: Allocates storage for an NDIS packet pool
428 * Status = Address of buffer for status
429 * PoolHandle = Address of buffer for pool handle
430 * NumberOfDescriptors = Size of packet pool in number of descriptors
431 * ProtocolReservedLength = Size of protocol reserved area in bytes
434 NdisAllocatePacketPoolEx(
439 ProtocolReservedLength
);
448 NdisAllocatePacketPoolEx(
449 OUT PNDIS_STATUS Status
,
450 OUT PNDIS_HANDLE PoolHandle
,
451 IN UINT NumberOfDescriptors
,
452 IN UINT NumberOfOverflowDescriptors
,
453 IN UINT ProtocolReservedLength
)
461 PNDISI_PACKET_POOL Pool
;
462 UINT Size
, Length
, i
;
463 PNDIS_PACKET Packet
, NextPacket
;
465 NDIS_DbgPrint(MAX_TRACE
, ("Status (0x%X) PoolHandle (0x%X) "
466 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
467 Status
, PoolHandle
, NumberOfDescriptors
, ProtocolReservedLength
));
471 if (NumberOfDescriptors
> 0xffff)
473 NDIS_DbgPrint(MIN_TRACE
, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors
))
474 *Status
= NDIS_STATUS_RESOURCES
;
478 NumberOfDescriptors
+= NumberOfOverflowDescriptors
;
479 if (NumberOfDescriptors
> 0xffff)
481 NDIS_DbgPrint(MIN_TRACE
, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors
));
482 NumberOfDescriptors
= 0xffff;
485 Length
= sizeof(NDIS_PACKET
) + sizeof(NDIS_PACKET_OOB_DATA
) +
486 sizeof(NDIS_PACKET_EXTENSION
) + ProtocolReservedLength
;
487 Size
= sizeof(NDISI_PACKET_POOL
) + Length
* NumberOfDescriptors
;
489 Pool
= ExAllocatePool(NonPagedPool
, Size
);
492 KeInitializeSpinLock(&Pool
->SpinLock
.SpinLock
);
493 Pool
->PacketLength
= Length
;
495 if (NumberOfDescriptors
> 0)
497 Packet
= (PNDIS_PACKET
)&Pool
->Buffer
;
498 Pool
->FreeList
= Packet
;
500 NextPacket
= (PNDIS_PACKET
)((ULONG_PTR
)Packet
+ Length
);
501 for (i
= 1; i
< NumberOfDescriptors
; i
++)
503 Packet
->Reserved
[0] = (ULONG_PTR
)NextPacket
;
505 NextPacket
= (PNDIS_PACKET
)((ULONG_PTR
)Packet
+ Length
);
507 Packet
->Reserved
[0] = 0;
510 NDIS_DbgPrint(MIN_TRACE
, ("Attempted to allocate a packet pool with 0 descriptors\n"));
511 Pool
->FreeList
= NULL
;
514 *Status
= NDIS_STATUS_SUCCESS
;
515 *PoolHandle
= (PNDIS_HANDLE
)Pool
;
517 *Status
= NDIS_STATUS_RESOURCES
;
526 #undef NdisBufferLength
530 IN PNDIS_BUFFER Buffer
)
532 * FUNCTION: Modifies the length of an NDIS buffer
534 * Buffer = Pointer to NDIS buffer descriptor
535 * Length = New size of buffer
539 * Length of NDIS buffer
542 return MmGetMdlByteCount(Buffer
);
549 #undef NdisBufferVirtualAddress
552 NdisBufferVirtualAddress(
553 IN PNDIS_BUFFER Buffer
)
561 return MmGetSystemAddressForMdl(Buffer
);
570 NdisCopyFromPacketToPacket(
571 IN PNDIS_PACKET Destination
,
572 IN UINT DestinationOffset
,
574 IN PNDIS_PACKET Source
,
575 IN UINT SourceOffset
,
576 OUT PUINT BytesCopied
)
578 * FUNCTION: Copies data from one packet to another
580 * Destination = Pointer to packet to copy data to
581 * DestinationOffset = Offset in destination packet to copy data to
582 * BytesToCopy = Number of bytes to copy
583 * Source = Pointer to packet descriptor to copy from
584 * SourceOffset = Offset in source packet to start copying from
585 * BytesCopied = Address of buffer to place number of bytes copied
588 PNDIS_BUFFER SrcBuffer
;
589 PNDIS_BUFFER DstBuffer
;
590 PUCHAR DstData
, SrcData
;
591 UINT DstSize
, SrcSize
;
596 /* Skip DestinationOffset bytes in the destination packet */
597 NdisGetFirstBufferFromPacket(Destination
, &DstBuffer
, (PVOID
*)&DstData
, &DstSize
, &Total
);
598 if (SkipToOffset(DstBuffer
, DestinationOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
601 /* Skip SourceOffset bytes in the source packet */
602 NdisGetFirstBufferFromPacket(Source
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
);
603 if (SkipToOffset(SrcBuffer
, SourceOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
608 /* Find out how many bytes we can copy at one time */
609 if (BytesToCopy
< SrcSize
)
616 RtlCopyMemory(DstData
, SrcData
, Count
);
619 BytesToCopy
-= Count
;
620 if (BytesToCopy
== 0)
625 /* No more bytes in destination buffer. Proceed to
626 the next buffer in the destination buffer chain */
627 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
631 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
636 /* No more bytes in source buffer. Proceed to
637 the next buffer in the source buffer chain */
638 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
642 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
646 *BytesCopied
= Total
;
655 NdisDprAllocatePacket(
656 OUT PNDIS_STATUS Status
,
657 OUT PNDIS_PACKET
*Packet
,
658 IN NDIS_HANDLE PoolHandle
)
660 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
662 * Status = Address of buffer to place status of operation
663 * Packet = Address of buffer to place a pointer to a packet descriptor
664 * PoolHandle = Handle returned by NdisAllocatePacketPool
667 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
669 KeAcquireSpinLockAtDpcLevel(&Pool
->SpinLock
.SpinLock
);
670 NdisDprAllocatePacketNonInterlocked(Status
,
673 KeReleaseSpinLockFromDpcLevel(&Pool
->SpinLock
.SpinLock
);
682 NdisDprAllocatePacketNonInterlocked(
683 OUT PNDIS_STATUS Status
,
684 OUT PNDIS_PACKET
*Packet
,
685 IN NDIS_HANDLE PoolHandle
)
687 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
689 * Status = Address of buffer to place status of operation
690 * Packet = Address of buffer to place a pointer to a packet descriptor
691 * PoolHandle = Handle returned by NdisAllocatePacketPool
695 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
697 NDIS_DbgPrint(MAX_TRACE
, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
698 Status
, Packet
, PoolHandle
));
704 *Status
= NDIS_STATUS_FAILURE
;
705 NDIS_DbgPrint(MIN_TRACE
, ("Called passed a bad pool handle\n"));
709 if (Pool
->FreeList
) {
710 Temp
= Pool
->FreeList
;
711 Pool
->FreeList
= (PNDIS_PACKET
)Temp
->Reserved
[0];
713 RtlZeroMemory(Temp
, Pool
->PacketLength
);
714 Temp
->Private
.Pool
= Pool
;
715 Temp
->Private
.ValidCounts
= TRUE
;
716 Temp
->Private
.NdisPacketFlags
= fPACKET_ALLOCATED_BY_NDIS
;
717 Temp
->Private
.NdisPacketOobOffset
= Pool
->PacketLength
-
718 (sizeof(NDIS_PACKET_OOB_DATA
) +
719 sizeof(NDIS_PACKET_EXTENSION
));
722 *Status
= NDIS_STATUS_SUCCESS
;
724 NDIS_DbgPrint(MIN_TRACE
, ("No more free descriptors\n"));
725 *Status
= NDIS_STATUS_RESOURCES
;
736 IN PNDIS_PACKET Packet
)
738 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
740 * Packet = Pointer to packet to free
743 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)Packet
->Private
.Pool
;
745 KeAcquireSpinLockAtDpcLevel(&Pool
->SpinLock
.SpinLock
);
746 NdisDprFreePacketNonInterlocked(Packet
);
747 KeReleaseSpinLockFromDpcLevel(&Pool
->SpinLock
.SpinLock
);
756 NdisDprFreePacketNonInterlocked(
757 IN PNDIS_PACKET Packet
)
759 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
761 * Packet = Pointer to packet to free
764 NDIS_DbgPrint(MAX_TRACE
, ("Packet (0x%X).\n", Packet
));
766 Packet
->Reserved
[0] = (ULONG_PTR
)((NDISI_PACKET_POOL
*)Packet
->Private
.Pool
)->FreeList
;
767 ((NDISI_PACKET_POOL
*)Packet
->Private
.Pool
)->FreeList
= Packet
;
777 IN NDIS_HANDLE PoolHandle
)
779 * FUNCTION: Frees storage allocated for an NDIS buffer pool
781 * PoolHandle = Handle returned by NdisAllocateBufferPool
793 IN NDIS_HANDLE PoolHandle
)
795 * FUNCTION: Frees storage allocated for an NDIS packet pool
797 * PoolHandle = Handle returned by NdisAllocatePacketPool
800 ExFreePool((PVOID
)PoolHandle
);
807 #undef NdisFreeBuffer
811 IN PNDIS_BUFFER Buffer
)
813 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
815 * Buffer = Pointer to buffer descriptor
828 IN PNDIS_PACKET Packet
)
830 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
832 * Packet = Pointer to packet descriptor
835 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)Packet
->Private
.Pool
;
837 KeAcquireSpinLock(&Pool
->SpinLock
.SpinLock
, &Pool
->SpinLock
.OldIrql
);
838 NdisDprFreePacketNonInterlocked(Packet
);
839 KeReleaseSpinLock(&Pool
->SpinLock
.SpinLock
, Pool
->SpinLock
.OldIrql
);
846 #undef NdisGetBufferPhysicalArraySize
849 NdisGetBufferPhysicalArraySize(
850 IN PNDIS_BUFFER Buffer
,
853 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
855 * Buffer = Pointer to buffer descriptor
856 * ArraySize = Address of buffer to place number of physical blocks
859 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
860 ASSERT(Buffer
&& ArraySize
);
862 *ArraySize
= NDIS_BUFFER_TO_SPAN_PAGES(Buffer
);
869 #undef NdisGetFirstBufferFromPacket
872 NdisGetFirstBufferFromPacket(
873 IN PNDIS_PACKET _Packet
,
874 OUT PNDIS_BUFFER
*_FirstBuffer
,
875 OUT PVOID
*_FirstBufferVA
,
876 OUT PUINT _FirstBufferLength
,
877 OUT PUINT _TotalBufferLength
)
879 * FUNCTION: Retrieves information about an NDIS packet
881 * _Packet = Pointer to NDIS packet
882 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
883 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
884 * _FirstBufferLength = Address of buffer for length of first buffer
885 * _TotalBufferLength = Address of buffer for total length of packet
890 Buffer
= _Packet
->Private
.Head
;
891 *_FirstBuffer
= Buffer
;
893 if (Buffer
!= NULL
) {
894 *_FirstBufferLength
= MmGetMdlByteCount(Buffer
);
895 *_FirstBufferVA
= MmGetSystemAddressForMdl(Buffer
);
896 Buffer
= Buffer
->Next
;
898 NDIS_DbgPrint(MID_TRACE
, ("No buffers linked to this packet\n"));
899 *_FirstBufferLength
= 0;
900 *_FirstBufferVA
= NULL
;
903 *_TotalBufferLength
= *_FirstBufferLength
;
905 while (Buffer
!= NULL
) {
906 *_TotalBufferLength
+= MmGetMdlByteCount(Buffer
);
907 Buffer
= Buffer
->Next
;
911 #undef NdisGetFirstBufferFromPacketSafe
917 NdisGetFirstBufferFromPacketSafe(
918 IN PNDIS_PACKET _Packet
,
919 OUT PNDIS_BUFFER
*_FirstBuffer
,
920 OUT PVOID
*_FirstBufferVA
,
921 OUT PUINT _FirstBufferLength
,
922 OUT PUINT _TotalBufferLength
,
923 IN MM_PAGE_PRIORITY Priority
)
927 Buffer
= _Packet
->Private
.Head
;
928 *_FirstBuffer
= Buffer
;
930 if (Buffer
!= NULL
) {
931 *_FirstBufferLength
= MmGetMdlByteCount(Buffer
);
932 *_FirstBufferVA
= MmGetSystemAddressForMdlSafe(Buffer
, Priority
);
933 Buffer
= Buffer
->Next
;
935 NDIS_DbgPrint(MID_TRACE
, ("No buffers linked to this packet\n"));
936 *_FirstBufferLength
= 0;
937 *_FirstBufferVA
= NULL
;
940 *_TotalBufferLength
= *_FirstBufferLength
;
942 while (Buffer
!= NULL
) {
943 *_TotalBufferLength
+= MmGetMdlByteCount(Buffer
);
944 Buffer
= Buffer
->Next
;
951 #undef NdisQueryBuffer
955 IN PNDIS_BUFFER Buffer
,
956 OUT PVOID
*VirtualAddress OPTIONAL
,
960 * Queries an NDIS buffer for information
962 * Buffer = Pointer to NDIS buffer to query
963 * VirtualAddress = Address of buffer to place virtual address
964 * Length = Address of buffer to place length of buffer
967 if (VirtualAddress
!= NULL
)
968 *(PVOID
*)VirtualAddress
= MmGetSystemAddressForMdl(Buffer
);
970 *Length
= MmGetMdlByteCount(Buffer
);
977 #undef NdisQueryBufferSafe
981 IN PNDIS_BUFFER Buffer
,
982 OUT PVOID
*VirtualAddress OPTIONAL
,
992 if (VirtualAddress
!= NULL
)
993 *VirtualAddress
= MmGetSystemAddressForMdlSafe(Buffer
, Priority
);
994 *Length
= MmGetMdlByteCount(Buffer
);
1001 #undef NdisQueryBufferOffset
1004 NdisQueryBufferOffset(
1005 IN PNDIS_BUFFER Buffer
,
1009 *((PUINT
)Offset
) = MmGetMdlByteOffset(Buffer
);
1010 *((PUINT
)Length
) = MmGetMdlByteCount(Buffer
);
1019 NdisUnchainBufferAtBack(
1020 IN OUT PNDIS_PACKET Packet
,
1021 OUT PNDIS_BUFFER
*Buffer
)
1024 * Removes the last buffer in a packet
1026 * Packet = Pointer to NDIS packet
1027 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1030 PNDIS_BUFFER NdisBuffer
, Previous
;
1032 NdisQueryPacket(Packet
,
1038 NDIS_DbgPrint(MID_TRACE
, ("No buffer to unchain\n"));
1044 while (NdisBuffer
->Next
) {
1045 Previous
= NdisBuffer
;
1046 NdisBuffer
= NdisBuffer
->Next
;
1050 Previous
->Next
= NULL
;
1051 Packet
->Private
.Tail
= Previous
;
1053 Packet
->Private
.Head
= NULL
;
1054 Packet
->Private
.Tail
= NULL
;
1057 Packet
->Private
.ValidCounts
= FALSE
;
1059 *Buffer
= NdisBuffer
;
1068 NdisUnchainBufferAtFront(
1069 IN OUT PNDIS_PACKET Packet
,
1070 OUT PNDIS_BUFFER
*Buffer
)
1073 * Removes the first buffer in a packet
1075 * Packet = Pointer to NDIS packet
1076 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1079 PNDIS_BUFFER NdisBuffer
;
1081 NdisQueryPacket(Packet
,
1087 NDIS_DbgPrint(MID_TRACE
, ("No buffer to unchain\n"));
1092 Packet
->Private
.Head
= NdisBuffer
->Next
;
1094 if (!NdisBuffer
->Next
)
1095 Packet
->Private
.Tail
= NULL
;
1097 NdisBuffer
->Next
= NULL
;
1099 Packet
->Private
.ValidCounts
= FALSE
;
1101 *Buffer
= NdisBuffer
;
1110 OUT PNDIS_STATUS Status
,
1111 OUT PNDIS_BUFFER
*Buffer
,
1112 IN NDIS_HANDLE PoolHandle
,
1113 IN PVOID MemoryDescriptor
,
1117 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
1119 * Status = Address of a buffer to place status of operation
1120 * Buffer = Address of a buffer to place new buffer descriptor
1121 * PoolHandle = Handle returned by NdisAllocateBufferPool
1122 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
1123 * Offset = Offset in buffer to start copying
1124 * Length = Number of bytes to copy
1127 PVOID CurrentVa
= (PUCHAR
)(MmGetMdlVirtualAddress((PNDIS_BUFFER
)MemoryDescriptor
)) + Offset
;
1129 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
1131 *Buffer
= IoAllocateMdl(CurrentVa
, Length
, FALSE
, FALSE
, NULL
);
1134 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa
, Length
));
1135 *Status
= NDIS_STATUS_FAILURE
;
1139 IoBuildPartialMdl((PNDIS_BUFFER
)MemoryDescriptor
,
1144 (*Buffer
)->Next
= NULL
;
1145 *Status
= NDIS_STATUS_SUCCESS
;
1153 NdisGetPoolFromPacket(
1154 IN PNDIS_PACKET Packet
)
1156 return Packet
->Private
.Pool
;
1165 IN UINT ProtocolReservedSize
)
1167 return sizeof(NDIS_PACKET
) + sizeof(NDIS_PACKET_OOB_DATA
) +
1168 sizeof(NDIS_PACKET_EXTENSION
) + ProtocolReservedSize
;
1174 #undef NdisGetPacketCancelId
1177 NdisGetPacketCancelId(
1178 IN PNDIS_PACKET Packet
)
1180 return NDIS_GET_PACKET_CANCEL_ID(Packet
);
1186 #undef NdisSetPacketCancelId
1189 NdisSetPacketCancelId(
1190 IN PNDIS_PACKET Packet
,
1193 NDIS_SET_PACKET_CANCEL_ID(Packet
, CancelId
);
1201 NdisCopyFromPacketToPacketSafe(
1202 IN PNDIS_PACKET Destination
,
1203 IN UINT DestinationOffset
,
1204 IN UINT BytesToCopy
,
1205 IN PNDIS_PACKET Source
,
1206 IN UINT SourceOffset
,
1207 OUT PUINT BytesCopied
,
1208 IN MM_PAGE_PRIORITY Priority
)
1210 PNDIS_BUFFER SrcBuffer
;
1211 PNDIS_BUFFER DstBuffer
;
1212 PUCHAR DstData
, SrcData
;
1213 UINT DstSize
, SrcSize
;
1218 /* Skip DestinationOffset bytes in the destination packet */
1219 NdisGetFirstBufferFromPacketSafe(Destination
, &DstBuffer
, (PVOID
*)&DstData
, &DstSize
, &Total
, Priority
);
1220 if (!DstData
|| SkipToOffset(DstBuffer
, DestinationOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
1223 /* Skip SourceOffset bytes in the source packet */
1224 NdisGetFirstBufferFromPacketSafe(Source
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
, Priority
);
1225 if (!SrcData
|| SkipToOffset(SrcBuffer
, SourceOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
1230 /* Find out how many bytes we can copy at one time */
1231 if (BytesToCopy
< SrcSize
)
1232 Count
= BytesToCopy
;
1235 if (DstSize
< Count
)
1238 RtlCopyMemory(DstData
, SrcData
, Count
);
1241 BytesToCopy
-= Count
;
1242 if (BytesToCopy
== 0)
1247 /* No more bytes in destination buffer. Proceed to
1248 the next buffer in the destination buffer chain */
1249 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
1253 NdisQueryBufferSafe(DstBuffer
, (PVOID
)&DstData
, &DstSize
, Priority
);
1260 /* No more bytes in source buffer. Proceed to
1261 the next buffer in the source buffer chain */
1262 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
1266 NdisQueryBufferSafe(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
, Priority
);
1272 *BytesCopied
= Total
;
1280 NdisIMCopySendCompletePerPacketInfo(
1281 IN PNDIS_PACKET DstPacket
,
1282 IN PNDIS_PACKET SrcPacket
)
1290 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1291 * NdisIMCopySendCompletePerPacketInfo?
1294 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1296 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket
),
1297 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket
),
1298 sizeof(NDIS_PACKET_EXTENSION
));
1307 NdisIMCopySendPerPacketInfo(
1308 IN PNDIS_PACKET DstPacket
,
1309 IN PNDIS_PACKET SrcPacket
)
1317 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1318 * NdisIMCopySendCompletePerPacketInfo?
1321 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1323 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket
),
1324 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket
),
1325 sizeof(NDIS_PACKET_EXTENSION
));