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
13 __inline ULONG
SkipToOffset(
14 IN PNDIS_BUFFER Buffer
,
19 * FUNCTION: Skips Offset bytes into a buffer chain
21 * Buffer = Pointer to NDIS buffer
22 * Offset = Number of bytes to skip
23 * Data = Address of a pointer that on return will contain the
24 * address of the offset in the buffer
25 * Size = Address of a pointer that on return will contain the
26 * size of the destination buffer
28 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
38 NdisQueryBuffer(Buffer
, (PVOID
)Data
, Size
);
41 *Data
= (PUCHAR
) ((ULONG_PTR
) *Data
+ Offset
);
48 NdisGetNextBuffer(Buffer
, &Buffer
);
54 UINT
CopyBufferToBufferChain(
55 PNDIS_BUFFER DstBuffer
,
60 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
62 * DstBuffer = Pointer to destination NDIS buffer
63 * DstOffset = Destination start offset
64 * SrcData = Pointer to source buffer
65 * Length = Number of bytes to copy
67 * Number of bytes copied to destination buffer
69 * The number of bytes copied may be limited by the destination
73 UINT BytesCopied
, BytesToCopy
, DstSize
;
76 NDIS_DbgPrint(MAX_TRACE
, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer
, DstOffset
, SrcData
, Length
));
78 /* Skip DstOffset bytes in the destination buffer chain */
79 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
82 /* Start copying the data */
85 BytesToCopy
= MIN(DstSize
, Length
);
87 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
88 BytesCopied
+= BytesToCopy
;
89 SrcData
= (PUCHAR
) ((ULONG_PTR
) SrcData
+ BytesToCopy
);
91 Length
-= BytesToCopy
;
95 DstSize
-= BytesToCopy
;
97 /* No more bytes in destination buffer. Proceed to
98 the next buffer in the destination buffer chain */
99 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
103 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
111 UINT
CopyBufferChainToBuffer(
113 PNDIS_BUFFER SrcBuffer
,
117 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
119 * DstData = Pointer to destination buffer
120 * SrcBuffer = Pointer to source NDIS buffer
121 * SrcOffset = Source start offset
122 * Length = Number of bytes to copy
124 * Number of bytes copied to destination buffer
126 * The number of bytes copied may be limited by the source
130 UINT BytesCopied
, BytesToCopy
, SrcSize
;
133 NDIS_DbgPrint(MAX_TRACE
, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData
,SrcBuffer
, SrcOffset
, Length
));
135 /* Skip SrcOffset bytes in the source buffer chain */
136 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
139 /* Start copying the data */
142 BytesToCopy
= MIN(SrcSize
, Length
);
144 NDIS_DbgPrint(MAX_TRACE
, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy
, SrcData
, DstData
));
146 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
147 BytesCopied
+= BytesToCopy
;
148 DstData
= (PUCHAR
)((ULONG_PTR
) DstData
+ BytesToCopy
);
150 Length
-= BytesToCopy
;
154 SrcSize
-= BytesToCopy
;
156 /* No more bytes in source buffer. Proceed to
157 the next buffer in the source buffer chain */
158 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
162 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
170 UINT
CopyPacketToBuffer(
172 PNDIS_PACKET SrcPacket
,
176 * FUNCTION: Copies data from an NDIS packet to a buffer
178 * DstData = Pointer to destination buffer
179 * SrcPacket = Pointer to source NDIS packet
180 * SrcOffset = Source start offset
181 * Length = Number of bytes to copy
183 * Number of bytes copied to destination buffer
185 * The number of bytes copied may be limited by the source
189 PNDIS_BUFFER FirstBuffer
;
194 NDIS_DbgPrint(MAX_TRACE
, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData
, SrcPacket
, SrcOffset
, Length
));
196 NdisGetFirstBufferFromPacket(SrcPacket
,
202 return CopyBufferChainToBuffer(DstData
, FirstBuffer
, SrcOffset
, Length
);
206 UINT
CopyPacketToBufferChain(
207 PNDIS_BUFFER DstBuffer
,
209 PNDIS_PACKET SrcPacket
,
213 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
215 * DstBuffer = Pointer to destination NDIS buffer
216 * DstOffset = Destination start offset
217 * SrcPacket = Pointer to source NDIS packet
218 * SrcOffset = Source start offset
219 * Length = Number of bytes to copy
221 * Number of bytes copied to destination buffer
223 * The number of bytes copied may be limited by the source and
224 * destination buffer sizes
227 PNDIS_BUFFER SrcBuffer
;
228 PUCHAR DstData
, SrcData
;
229 UINT DstSize
, SrcSize
;
232 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 /* Skip DstOffset bytes in the destination buffer chain */
235 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
236 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
238 /* Skip SrcOffset bytes in the source packet */
239 NdisGetFirstBufferFromPacket(SrcPacket
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
);
240 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
244 /* Find out how many bytes we can copy at one time */
245 if (Length
< SrcSize
)
252 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, Count
);
261 /* No more bytes in destination buffer. Proceed to
262 the next buffer in the destination buffer chain */
263 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
267 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
272 /* No more bytes in source buffer. Proceed to
273 the next buffer in the source buffer chain */
274 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
278 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
289 #undef NdisAdjustBufferLength
292 NdisAdjustBufferLength(
293 IN PNDIS_BUFFER Buffer
,
296 * FUNCTION: Modifies the length of an NDIS buffer
298 * Buffer = Pointer to NDIS buffer descriptor
299 * Length = New size of buffer
302 Buffer
->ByteCount
= Length
;
309 #undef NDIS_BUFFER_TO_SPAN_PAGES
312 NDIS_BUFFER_TO_SPAN_PAGES(
313 IN PNDIS_BUFFER Buffer
)
315 * FUNCTION: Determines how many physical pages a buffer is made of
317 * Buffer = Pointer to NDIS buffer descriptor
320 if (MmGetMdlByteCount(Buffer
) == 0)
323 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
324 MmGetMdlVirtualAddress(Buffer
),
325 MmGetMdlByteCount(Buffer
));
335 OUT PNDIS_STATUS Status
,
336 OUT PNDIS_BUFFER
* Buffer
,
337 IN NDIS_HANDLE PoolHandle
,
338 IN PVOID VirtualAddress
,
341 * FUNCTION: Allocates an NDIS buffer descriptor
343 * Status = Address of buffer for status
344 * Buffer = Address of buffer for NDIS buffer descriptor
345 * PoolHandle = Handle returned by NdisAllocateBufferPool
346 * VirtualAddress = Pointer to virtual address of data buffer
347 * Length = Number of bytes in data buffer
350 ASSERT(VirtualAddress
!= NULL
);
353 *Buffer
= IoAllocateMdl(VirtualAddress
, Length
, FALSE
, FALSE
, NULL
);
354 if (*Buffer
!= NULL
) {
355 MmBuildMdlForNonPagedPool(*Buffer
);
356 (*Buffer
)->Next
= NULL
;
357 *Status
= NDIS_STATUS_SUCCESS
;
359 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress
, Length
));
360 *Status
= NDIS_STATUS_FAILURE
;
370 NdisAllocateBufferPool(
371 OUT PNDIS_STATUS Status
,
372 OUT PNDIS_HANDLE PoolHandle
,
373 IN UINT NumberOfDescriptors
)
375 * FUNCTION: Allocates storage for an NDIS buffer pool
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
382 *Status
= NDIS_STATUS_SUCCESS
;
393 OUT PNDIS_STATUS Status
,
394 OUT PNDIS_PACKET
* Packet
,
395 IN NDIS_HANDLE PoolHandle
)
397 * FUNCTION: Allocates an NDIS packet descriptor
399 * Status = Address of buffer for status
400 * Packet = Address of buffer for packet descriptor
401 * PoolHandle = Handle returned by NdisAllocatePacketPool
404 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
406 KeAcquireSpinLock(&Pool
->SpinLock
.SpinLock
, &Pool
->SpinLock
.OldIrql
);
407 NdisDprAllocatePacketNonInterlocked(Status
,
410 KeReleaseSpinLock(&Pool
->SpinLock
.SpinLock
, Pool
->SpinLock
.OldIrql
);
419 NdisAllocatePacketPool(
420 OUT PNDIS_STATUS Status
,
421 OUT PNDIS_HANDLE PoolHandle
,
422 IN UINT NumberOfDescriptors
,
423 IN UINT ProtocolReservedLength
)
425 * FUNCTION: Allocates storage for an NDIS packet pool
427 * Status = Address of buffer for status
428 * PoolHandle = Address of buffer for pool handle
429 * NumberOfDescriptors = Size of packet pool in number of descriptors
430 * ProtocolReservedLength = Size of protocol reserved area in bytes
433 NdisAllocatePacketPoolEx(
438 ProtocolReservedLength
);
447 NdisAllocatePacketPoolEx(
448 OUT PNDIS_STATUS Status
,
449 OUT PNDIS_HANDLE PoolHandle
,
450 IN UINT NumberOfDescriptors
,
451 IN UINT NumberOfOverflowDescriptors
,
452 IN UINT ProtocolReservedLength
)
460 PNDISI_PACKET_POOL Pool
;
461 UINT Size
, Length
, i
;
462 PNDIS_PACKET Packet
, NextPacket
;
464 NDIS_DbgPrint(MAX_TRACE
, ("Status (0x%X) PoolHandle (0x%X) "
465 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
466 Status
, PoolHandle
, NumberOfDescriptors
, ProtocolReservedLength
));
470 if (NumberOfDescriptors
> 0xffff)
472 NDIS_DbgPrint(MIN_TRACE
, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors
))
473 *Status
= NDIS_STATUS_RESOURCES
;
477 NumberOfDescriptors
+= NumberOfOverflowDescriptors
;
478 if (NumberOfDescriptors
> 0xffff)
480 NDIS_DbgPrint(MIN_TRACE
, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors
));
481 NumberOfDescriptors
= 0xffff;
484 Length
= sizeof(NDIS_PACKET
) + sizeof(NDIS_PACKET_OOB_DATA
) +
485 sizeof(NDIS_PACKET_EXTENSION
) + ProtocolReservedLength
;
486 Size
= sizeof(NDISI_PACKET_POOL
) + Length
* NumberOfDescriptors
;
488 Pool
= ExAllocatePool(NonPagedPool
, Size
);
491 KeInitializeSpinLock(&Pool
->SpinLock
.SpinLock
);
492 Pool
->PacketLength
= Length
;
494 if (NumberOfDescriptors
> 0)
496 Packet
= (PNDIS_PACKET
)&Pool
->Buffer
;
497 Pool
->FreeList
= Packet
;
499 NextPacket
= (PNDIS_PACKET
)((ULONG_PTR
)Packet
+ Length
);
500 for (i
= 1; i
< NumberOfDescriptors
; i
++)
502 Packet
->Reserved
[0] = (ULONG_PTR
)NextPacket
;
504 NextPacket
= (PNDIS_PACKET
)((ULONG_PTR
)Packet
+ Length
);
506 Packet
->Reserved
[0] = 0;
509 NDIS_DbgPrint(MIN_TRACE
, ("Attempted to allocate a packet pool with 0 descriptors\n"));
510 Pool
->FreeList
= NULL
;
513 *Status
= NDIS_STATUS_SUCCESS
;
514 *PoolHandle
= (PNDIS_HANDLE
)Pool
;
516 *Status
= NDIS_STATUS_RESOURCES
;
525 #undef NdisBufferLength
529 IN PNDIS_BUFFER Buffer
)
531 * FUNCTION: Modifies the length of an NDIS buffer
533 * Buffer = Pointer to NDIS buffer descriptor
534 * Length = New size of buffer
538 * Length of NDIS buffer
541 return MmGetMdlByteCount(Buffer
);
548 #undef NdisBufferVirtualAddress
551 NdisBufferVirtualAddress(
552 IN PNDIS_BUFFER Buffer
)
560 return MmGetSystemAddressForMdl(Buffer
);
569 NdisCopyFromPacketToPacket(
570 IN PNDIS_PACKET Destination
,
571 IN UINT DestinationOffset
,
573 IN PNDIS_PACKET Source
,
574 IN UINT SourceOffset
,
575 OUT PUINT BytesCopied
)
577 * FUNCTION: Copies data from one packet to another
579 * Destination = Pointer to packet to copy data to
580 * DestinationOffset = Offset in destination packet to copy data to
581 * BytesToCopy = Number of bytes to copy
582 * Source = Pointer to packet descriptor to copy from
583 * SourceOffset = Offset in source packet to start copying from
584 * BytesCopied = Address of buffer to place number of bytes copied
587 PNDIS_BUFFER SrcBuffer
;
588 PNDIS_BUFFER DstBuffer
;
589 PUCHAR DstData
, SrcData
;
590 UINT DstSize
, SrcSize
;
595 /* Skip DestinationOffset bytes in the destination packet */
596 NdisGetFirstBufferFromPacket(Destination
, &DstBuffer
, (PVOID
*)&DstData
, &DstSize
, &Total
);
597 if (SkipToOffset(DstBuffer
, DestinationOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
600 /* Skip SourceOffset bytes in the source packet */
601 NdisGetFirstBufferFromPacket(Source
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
);
602 if (SkipToOffset(SrcBuffer
, SourceOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
607 /* Find out how many bytes we can copy at one time */
608 if (BytesToCopy
< SrcSize
)
615 RtlCopyMemory(DstData
, SrcData
, Count
);
618 BytesToCopy
-= Count
;
619 if (BytesToCopy
== 0)
624 /* No more bytes in destination buffer. Proceed to
625 the next buffer in the destination buffer chain */
626 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
630 NdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
635 /* No more bytes in source buffer. Proceed to
636 the next buffer in the source buffer chain */
637 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
641 NdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
645 *BytesCopied
= Total
;
654 NdisDprAllocatePacket(
655 OUT PNDIS_STATUS Status
,
656 OUT PNDIS_PACKET
*Packet
,
657 IN NDIS_HANDLE PoolHandle
)
659 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
661 * Status = Address of buffer to place status of operation
662 * Packet = Address of buffer to place a pointer to a packet descriptor
663 * PoolHandle = Handle returned by NdisAllocatePacketPool
666 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
668 KeAcquireSpinLockAtDpcLevel(&Pool
->SpinLock
.SpinLock
);
669 NdisDprAllocatePacketNonInterlocked(Status
,
672 KeReleaseSpinLockFromDpcLevel(&Pool
->SpinLock
.SpinLock
);
681 NdisDprAllocatePacketNonInterlocked(
682 OUT PNDIS_STATUS Status
,
683 OUT PNDIS_PACKET
*Packet
,
684 IN NDIS_HANDLE PoolHandle
)
686 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
688 * Status = Address of buffer to place status of operation
689 * Packet = Address of buffer to place a pointer to a packet descriptor
690 * PoolHandle = Handle returned by NdisAllocatePacketPool
694 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)PoolHandle
;
696 NDIS_DbgPrint(MAX_TRACE
, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
697 Status
, Packet
, PoolHandle
));
703 *Status
= NDIS_STATUS_FAILURE
;
704 NDIS_DbgPrint(MIN_TRACE
, ("Called passed a bad pool handle\n"));
708 if (Pool
->FreeList
) {
709 Temp
= Pool
->FreeList
;
710 Pool
->FreeList
= (PNDIS_PACKET
)Temp
->Reserved
[0];
712 RtlZeroMemory(Temp
, Pool
->PacketLength
);
713 Temp
->Private
.Pool
= Pool
;
714 Temp
->Private
.ValidCounts
= TRUE
;
715 Temp
->Private
.NdisPacketFlags
= fPACKET_ALLOCATED_BY_NDIS
;
716 Temp
->Private
.NdisPacketOobOffset
= Pool
->PacketLength
-
717 (sizeof(NDIS_PACKET_OOB_DATA
) +
718 sizeof(NDIS_PACKET_EXTENSION
));
721 *Status
= NDIS_STATUS_SUCCESS
;
723 NDIS_DbgPrint(MIN_TRACE
, ("No more free descriptors\n"));
724 *Status
= NDIS_STATUS_RESOURCES
;
735 IN PNDIS_PACKET Packet
)
737 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
739 * Packet = Pointer to packet to free
742 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)Packet
->Private
.Pool
;
744 KeAcquireSpinLockAtDpcLevel(&Pool
->SpinLock
.SpinLock
);
745 NdisDprFreePacketNonInterlocked(Packet
);
746 KeReleaseSpinLockFromDpcLevel(&Pool
->SpinLock
.SpinLock
);
755 NdisDprFreePacketNonInterlocked(
756 IN PNDIS_PACKET Packet
)
758 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
760 * Packet = Pointer to packet to free
763 NDIS_DbgPrint(MAX_TRACE
, ("Packet (0x%X).\n", Packet
));
765 Packet
->Reserved
[0] = (ULONG_PTR
)((NDISI_PACKET_POOL
*)Packet
->Private
.Pool
)->FreeList
;
766 ((NDISI_PACKET_POOL
*)Packet
->Private
.Pool
)->FreeList
= Packet
;
776 IN NDIS_HANDLE PoolHandle
)
778 * FUNCTION: Frees storage allocated for an NDIS buffer pool
780 * PoolHandle = Handle returned by NdisAllocateBufferPool
792 IN NDIS_HANDLE PoolHandle
)
794 * FUNCTION: Frees storage allocated for an NDIS packet pool
796 * PoolHandle = Handle returned by NdisAllocatePacketPool
799 ExFreePool((PVOID
)PoolHandle
);
806 #undef NdisFreeBuffer
810 IN PNDIS_BUFFER Buffer
)
812 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
814 * Buffer = Pointer to buffer descriptor
827 IN PNDIS_PACKET Packet
)
829 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
831 * Packet = Pointer to packet descriptor
834 PNDISI_PACKET_POOL Pool
= (PNDISI_PACKET_POOL
)Packet
->Private
.Pool
;
836 KeAcquireSpinLock(&Pool
->SpinLock
.SpinLock
, &Pool
->SpinLock
.OldIrql
);
837 NdisDprFreePacketNonInterlocked(Packet
);
838 KeReleaseSpinLock(&Pool
->SpinLock
.SpinLock
, Pool
->SpinLock
.OldIrql
);
845 #undef NdisGetBufferPhysicalArraySize
848 NdisGetBufferPhysicalArraySize(
849 IN PNDIS_BUFFER Buffer
,
852 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
854 * Buffer = Pointer to buffer descriptor
855 * ArraySize = Address of buffer to place number of physical blocks
858 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
859 ASSERT(Buffer
&& ArraySize
);
861 *ArraySize
= NDIS_BUFFER_TO_SPAN_PAGES(Buffer
);
868 #undef NdisGetFirstBufferFromPacket
871 NdisGetFirstBufferFromPacket(
872 IN PNDIS_PACKET _Packet
,
873 OUT PNDIS_BUFFER
*_FirstBuffer
,
874 OUT PVOID
*_FirstBufferVA
,
875 OUT PUINT _FirstBufferLength
,
876 OUT PUINT _TotalBufferLength
)
878 * FUNCTION: Retrieves information about an NDIS packet
880 * _Packet = Pointer to NDIS packet
881 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
882 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
883 * _FirstBufferLength = Address of buffer for length of first buffer
884 * _TotalBufferLength = Address of buffer for total length of packet
889 Buffer
= _Packet
->Private
.Head
;
890 *_FirstBuffer
= Buffer
;
892 if (Buffer
!= NULL
) {
893 *_FirstBufferLength
= MmGetMdlByteCount(Buffer
);
894 *_FirstBufferVA
= MmGetSystemAddressForMdl(Buffer
);
895 Buffer
= Buffer
->Next
;
897 NDIS_DbgPrint(MID_TRACE
, ("No buffers linked to this packet\n"));
898 *_FirstBufferLength
= 0;
899 *_FirstBufferVA
= NULL
;
902 *_TotalBufferLength
= *_FirstBufferLength
;
904 while (Buffer
!= NULL
) {
905 *_TotalBufferLength
+= MmGetMdlByteCount(Buffer
);
906 Buffer
= Buffer
->Next
;
910 #undef NdisGetFirstBufferFromPacketSafe
916 NdisGetFirstBufferFromPacketSafe(
917 IN PNDIS_PACKET _Packet
,
918 OUT PNDIS_BUFFER
*_FirstBuffer
,
919 OUT PVOID
*_FirstBufferVA
,
920 OUT PUINT _FirstBufferLength
,
921 OUT PUINT _TotalBufferLength
,
922 IN MM_PAGE_PRIORITY Priority
)
926 Buffer
= _Packet
->Private
.Head
;
927 *_FirstBuffer
= Buffer
;
929 if (Buffer
!= NULL
) {
930 *_FirstBufferLength
= MmGetMdlByteCount(Buffer
);
931 *_FirstBufferVA
= MmGetSystemAddressForMdlSafe(Buffer
, Priority
);
932 Buffer
= Buffer
->Next
;
934 NDIS_DbgPrint(MID_TRACE
, ("No buffers linked to this packet\n"));
935 *_FirstBufferLength
= 0;
936 *_FirstBufferVA
= NULL
;
939 *_TotalBufferLength
= *_FirstBufferLength
;
941 while (Buffer
!= NULL
) {
942 *_TotalBufferLength
+= MmGetMdlByteCount(Buffer
);
943 Buffer
= Buffer
->Next
;
950 #undef NdisQueryBuffer
954 IN PNDIS_BUFFER Buffer
,
955 OUT PVOID
*VirtualAddress OPTIONAL
,
959 * Queries an NDIS buffer for information
961 * Buffer = Pointer to NDIS buffer to query
962 * VirtualAddress = Address of buffer to place virtual address
963 * Length = Address of buffer to place length of buffer
966 if (VirtualAddress
!= NULL
)
967 *(PVOID
*)VirtualAddress
= MmGetSystemAddressForMdl(Buffer
);
969 *Length
= MmGetMdlByteCount(Buffer
);
976 #undef NdisQueryBufferSafe
980 IN PNDIS_BUFFER Buffer
,
981 OUT PVOID
*VirtualAddress OPTIONAL
,
991 if (VirtualAddress
!= NULL
)
992 *VirtualAddress
= MmGetSystemAddressForMdlSafe(Buffer
, Priority
);
993 *Length
= MmGetMdlByteCount(Buffer
);
1000 #undef NdisQueryBufferOffset
1003 NdisQueryBufferOffset(
1004 IN PNDIS_BUFFER Buffer
,
1008 *((PUINT
)Offset
) = MmGetMdlByteOffset(Buffer
);
1009 *((PUINT
)Length
) = MmGetMdlByteCount(Buffer
);
1018 NdisUnchainBufferAtBack(
1019 IN OUT PNDIS_PACKET Packet
,
1020 OUT PNDIS_BUFFER
*Buffer
)
1023 * Removes the last buffer in a packet
1025 * Packet = Pointer to NDIS packet
1026 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1029 PNDIS_BUFFER NdisBuffer
, Previous
;
1031 NdisQueryPacket(Packet
,
1037 NDIS_DbgPrint(MID_TRACE
, ("No buffer to unchain\n"));
1043 while (NdisBuffer
->Next
) {
1044 Previous
= NdisBuffer
;
1045 NdisBuffer
= NdisBuffer
->Next
;
1049 Previous
->Next
= NULL
;
1050 Packet
->Private
.Tail
= Previous
;
1052 Packet
->Private
.Head
= NULL
;
1053 Packet
->Private
.Tail
= NULL
;
1056 Packet
->Private
.ValidCounts
= FALSE
;
1058 *Buffer
= NdisBuffer
;
1067 NdisUnchainBufferAtFront(
1068 IN OUT PNDIS_PACKET Packet
,
1069 OUT PNDIS_BUFFER
*Buffer
)
1072 * Removes the first buffer in a packet
1074 * Packet = Pointer to NDIS packet
1075 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1078 PNDIS_BUFFER NdisBuffer
;
1080 NdisQueryPacket(Packet
,
1086 NDIS_DbgPrint(MID_TRACE
, ("No buffer to unchain\n"));
1091 Packet
->Private
.Head
= NdisBuffer
->Next
;
1093 if (!NdisBuffer
->Next
)
1094 Packet
->Private
.Tail
= NULL
;
1096 NdisBuffer
->Next
= NULL
;
1098 Packet
->Private
.ValidCounts
= FALSE
;
1100 *Buffer
= NdisBuffer
;
1109 OUT PNDIS_STATUS Status
,
1110 OUT PNDIS_BUFFER
*Buffer
,
1111 IN NDIS_HANDLE PoolHandle
,
1112 IN PVOID MemoryDescriptor
,
1116 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
1118 * Status = Address of a buffer to place status of operation
1119 * Buffer = Address of a buffer to place new buffer descriptor
1120 * PoolHandle = Handle returned by NdisAllocateBufferPool
1121 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
1122 * Offset = Offset in buffer to start copying
1123 * Length = Number of bytes to copy
1126 PVOID CurrentVa
= (PUCHAR
)(MmGetMdlVirtualAddress((PNDIS_BUFFER
)MemoryDescriptor
)) + Offset
;
1128 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
1130 *Buffer
= IoAllocateMdl(CurrentVa
, Length
, FALSE
, FALSE
, NULL
);
1133 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa
, Length
));
1134 *Status
= NDIS_STATUS_FAILURE
;
1138 IoBuildPartialMdl((PNDIS_BUFFER
)MemoryDescriptor
,
1143 (*Buffer
)->Next
= NULL
;
1144 *Status
= NDIS_STATUS_SUCCESS
;
1152 NdisGetPoolFromPacket(
1153 IN PNDIS_PACKET Packet
)
1155 return Packet
->Private
.Pool
;
1164 IN UINT ProtocolReservedSize
)
1166 return sizeof(NDIS_PACKET
) + sizeof(NDIS_PACKET_OOB_DATA
) +
1167 sizeof(NDIS_PACKET_EXTENSION
) + ProtocolReservedSize
;
1173 #undef NdisGetPacketCancelId
1176 NdisGetPacketCancelId(
1177 IN PNDIS_PACKET Packet
)
1179 return NDIS_GET_PACKET_CANCEL_ID(Packet
);
1185 #undef NdisSetPacketCancelId
1188 NdisSetPacketCancelId(
1189 IN PNDIS_PACKET Packet
,
1192 NDIS_SET_PACKET_CANCEL_ID(Packet
, CancelId
);
1200 NdisCopyFromPacketToPacketSafe(
1201 IN PNDIS_PACKET Destination
,
1202 IN UINT DestinationOffset
,
1203 IN UINT BytesToCopy
,
1204 IN PNDIS_PACKET Source
,
1205 IN UINT SourceOffset
,
1206 OUT PUINT BytesCopied
,
1207 IN MM_PAGE_PRIORITY Priority
)
1209 PNDIS_BUFFER SrcBuffer
;
1210 PNDIS_BUFFER DstBuffer
;
1211 PUCHAR DstData
, SrcData
;
1212 UINT DstSize
, SrcSize
;
1217 /* Skip DestinationOffset bytes in the destination packet */
1218 NdisGetFirstBufferFromPacketSafe(Destination
, &DstBuffer
, (PVOID
*)&DstData
, &DstSize
, &Total
, Priority
);
1219 if (!DstData
|| SkipToOffset(DstBuffer
, DestinationOffset
, &DstData
, &DstSize
) == 0xFFFFFFFF)
1222 /* Skip SourceOffset bytes in the source packet */
1223 NdisGetFirstBufferFromPacketSafe(Source
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
, Priority
);
1224 if (!SrcData
|| SkipToOffset(SrcBuffer
, SourceOffset
, &SrcData
, &SrcSize
) == 0xFFFFFFFF)
1229 /* Find out how many bytes we can copy at one time */
1230 if (BytesToCopy
< SrcSize
)
1231 Count
= BytesToCopy
;
1234 if (DstSize
< Count
)
1237 RtlCopyMemory(DstData
, SrcData
, Count
);
1240 BytesToCopy
-= Count
;
1241 if (BytesToCopy
== 0)
1246 /* No more bytes in destination buffer. Proceed to
1247 the next buffer in the destination buffer chain */
1248 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
1252 NdisQueryBufferSafe(DstBuffer
, (PVOID
)&DstData
, &DstSize
, Priority
);
1259 /* No more bytes in source buffer. Proceed to
1260 the next buffer in the source buffer chain */
1261 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
1265 NdisQueryBufferSafe(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
, Priority
);
1271 *BytesCopied
= Total
;
1279 NdisIMCopySendCompletePerPacketInfo(
1280 IN PNDIS_PACKET DstPacket
,
1281 IN PNDIS_PACKET SrcPacket
)
1289 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1290 * NdisIMCopySendCompletePerPacketInfo?
1293 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1295 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket
),
1296 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket
),
1297 sizeof(NDIS_PACKET_EXTENSION
));
1306 NdisIMCopySendPerPacketInfo(
1307 IN PNDIS_PACKET DstPacket
,
1308 IN PNDIS_PACKET SrcPacket
)
1316 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1317 * NdisIMCopySendCompletePerPacketInfo?
1320 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1322 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket
),
1323 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket
),
1324 sizeof(NDIS_PACKET_EXTENSION
));