9891314cd2c752a6997ece67054e3ad26cb4d079
[reactos.git] / reactos / drivers / net / 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 <buffer.h>
12
13
14 __inline ULONG SkipToOffset(
15 PNDIS_BUFFER Buffer,
16 UINT Offset,
17 PUCHAR *Data,
18 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 VOID
291 EXPORT
292 NdisAdjustBufferLength(
293 IN PNDIS_BUFFER Buffer,
294 IN UINT Length)
295 /*
296 * FUNCTION: Modifies the length of an NDIS buffer
297 * ARGUMENTS:
298 * Buffer = Pointer to NDIS buffer descriptor
299 * Length = New size of buffer
300 */
301 {
302 Buffer->ByteCount = Length;
303 }
304
305
306 /*
307 * @implemented
308 */
309 ULONG
310 EXPORT
311 NDIS_BUFFER_TO_SPAN_PAGES(
312 IN PNDIS_BUFFER Buffer)
313 /*
314 * FUNCTION: Determines how many physical pages a buffer is made of
315 * ARGUMENTS:
316 * Buffer = Pointer to NDIS buffer descriptor
317 */
318 {
319 if (MmGetMdlByteCount(Buffer) == 0)
320 return 1;
321
322 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
323 MmGetMdlVirtualAddress(Buffer),
324 MmGetMdlByteCount(Buffer));
325 }
326
327
328 /*
329 * @implemented
330 */
331 VOID
332 EXPORT
333 NdisAllocateBuffer(
334 OUT PNDIS_STATUS Status,
335 OUT PNDIS_BUFFER * Buffer,
336 IN NDIS_HANDLE PoolHandle,
337 IN PVOID VirtualAddress,
338 IN UINT Length)
339 /*
340 * FUNCTION: Allocates an NDIS buffer descriptor
341 * ARGUMENTS:
342 * Status = Address of buffer for status
343 * Buffer = Address of buffer for NDIS buffer descriptor
344 * PoolHandle = Handle returned by NdisAllocateBufferPool
345 * VirtualAddress = Pointer to virtual address of data buffer
346 * Length = Number of bytes in data buffer
347 */
348 {
349 KIRQL OldIrql;
350 PNETWORK_HEADER Temp;
351 PNDIS_BUFFER_POOL Pool = (PNDIS_BUFFER_POOL)PoolHandle;
352
353 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Buffer (0x%X) PoolHandle (0x%X) "
354 "VirtualAddress (0x%X) Length (%d)\n",
355 Status, Buffer, PoolHandle, VirtualAddress, Length));
356
357 #if 0
358 Temp = Pool->FreeList;
359 while( Temp ) {
360 NDIS_DbgPrint(MID_TRACE,("Free buffer -> %x\n", Temp));
361 Temp = Temp->Next;
362 }
363
364 NDIS_DbgPrint(MID_TRACE,("|:. <- End free buffers"));
365 #endif
366
367 if(!VirtualAddress && !Length) return;
368
369 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
370
371 if (Pool->FreeList) {
372 Temp = Pool->FreeList;
373 Pool->FreeList = Temp->Next;
374
375 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
376
377 Temp->Next = NULL;
378
379 MmInitializeMdl(&Temp->Mdl, VirtualAddress, Length);
380 Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
381 Temp->Mdl.MappedSystemVa = VirtualAddress;
382
383 Temp->BufferPool = Pool;
384
385 *Buffer = (PNDIS_BUFFER)Temp;
386 *Status = NDIS_STATUS_SUCCESS;
387 } else {
388 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
389 *Status = NDIS_STATUS_FAILURE;
390 NDIS_DbgPrint(MID_TRACE, ("Can't get another packet.\n"));
391 KeBugCheck(0);
392 }
393 }
394
395
396 /*
397 * @implemented
398 */
399 VOID
400 EXPORT
401 NdisAllocateBufferPool(
402 OUT PNDIS_STATUS Status,
403 OUT PNDIS_HANDLE PoolHandle,
404 IN UINT NumberOfDescriptors)
405 /*
406 * FUNCTION: Allocates storage for an NDIS buffer pool
407 * ARGUMENTS:
408 * Status = Address of buffer for status
409 * PoolHandle = Address of buffer for pool handle
410 * NumberOfDescriptors = Size of buffer pool in number of descriptors
411 */
412 {
413 UINT i;
414 PNDIS_BUFFER_POOL Pool;
415 PNETWORK_HEADER Buffer;
416
417 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) NumberOfDescriptors (%d).\n",
418 Status, PoolHandle, NumberOfDescriptors));
419
420 Pool = ExAllocatePool(NonPagedPool,
421 sizeof(NDIS_BUFFER_POOL) +
422 sizeof(NETWORK_HEADER) *
423 NumberOfDescriptors);
424 if (Pool) {
425 KeInitializeSpinLock(&Pool->SpinLock);
426
427 if (NumberOfDescriptors > 0) {
428 Buffer = &Pool->Buffers[0];
429 NDIS_DbgPrint(MAX_TRACE, ("NDIS BUFFER ADDRESS << %x >>\n", Buffer));
430 Pool->FreeList = Buffer;
431 for (i = 1; i < NumberOfDescriptors; i++) {
432 Buffer->Next = &Pool->Buffers[i];
433 Buffer = Buffer->Next;
434 NDIS_DbgPrint(MAX_TRACE, ("NDIS BUFFER ADDRESS << %x >>\n",
435 Buffer));
436 }
437 Buffer->Next = NULL;
438 } else
439 Pool->FreeList = NULL;
440
441 *Status = NDIS_STATUS_SUCCESS;
442 *PoolHandle = (PNDIS_HANDLE)Pool;
443 } else
444 *Status = NDIS_STATUS_RESOURCES;
445 }
446
447
448 /*
449 * @implemented
450 */
451 VOID
452 EXPORT
453 NdisAllocatePacket(
454 OUT PNDIS_STATUS Status,
455 OUT PNDIS_PACKET * Packet,
456 IN NDIS_HANDLE PoolHandle)
457 /*
458 * FUNCTION: Allocates an NDIS packet descriptor
459 * ARGUMENTS:
460 * Status = Address of buffer for status
461 * Packet = Address of buffer for packet descriptor
462 * PoolHandle = Handle returned by NdisAllocatePacketPool
463 */
464 {
465 KIRQL OldIrql;
466 PNDIS_PACKET Temp;
467 PNDIS_PACKET_POOL Pool = (PNDIS_PACKET_POOL)PoolHandle;
468
469 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
470 Status, Packet, PoolHandle));
471
472 if (Pool == NULL)
473 {
474 *Status = NDIS_STATUS_FAILURE;
475 return;
476 }
477
478 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
479
480 if (Pool->FreeList) {
481 Temp = Pool->FreeList;
482 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
483
484 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
485
486 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
487 Temp->Private.Pool = Pool;
488
489 *Packet = Temp;
490 *Status = NDIS_STATUS_SUCCESS;
491 } else {
492 *Status = NDIS_STATUS_RESOURCES;
493 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
494 }
495 }
496
497
498 /*
499 * @implemented
500 */
501 VOID
502 EXPORT
503 NdisAllocatePacketPool(
504 OUT PNDIS_STATUS Status,
505 OUT PNDIS_HANDLE PoolHandle,
506 IN UINT NumberOfDescriptors,
507 IN UINT ProtocolReservedLength)
508 /*
509 * FUNCTION: Allocates storage for an NDIS packet pool
510 * ARGUMENTS:
511 * Status = Address of buffer for status
512 * PoolHandle = Address of buffer for pool handle
513 * NumberOfDescriptors = Size of packet pool in number of descriptors
514 * ProtocolReservedLength = Size of protocol reserved area in bytes
515 */
516 {
517 NdisAllocatePacketPoolEx(
518 Status,
519 PoolHandle,
520 NumberOfDescriptors,
521 0,
522 ProtocolReservedLength);
523 }
524
525
526 /*
527 * @unimplemented
528 */
529 VOID
530 EXPORT
531 NdisAllocatePacketPoolEx(
532 OUT PNDIS_STATUS Status,
533 OUT PNDIS_HANDLE PoolHandle,
534 IN UINT NumberOfDescriptors,
535 IN UINT NumberOfOverflowDescriptors,
536 IN UINT ProtocolReservedLength)
537 /*
538 * FUNCTION:
539 * ARGUMENTS:
540 * NOTES:
541 * NDIS 5.0
542 */
543 {
544 PNDIS_PACKET_POOL Pool;
545 UINT Size, Length, i;
546 PNDIS_PACKET Packet, NextPacket;
547
548 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) "
549 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
550 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
551
552 if (NumberOfDescriptors > 0xffff)
553 {
554 *Status = NDIS_STATUS_RESOURCES;
555 }
556 else
557 {
558 NumberOfDescriptors += NumberOfOverflowDescriptors;
559 if (NumberOfDescriptors > 0xffff)
560 {
561 NumberOfDescriptors = 0xffff;
562 }
563
564 Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
565 Size = sizeof(NDIS_PACKET_POOL) + Length * NumberOfDescriptors;
566
567 Pool = ExAllocatePool(NonPagedPool, Size);
568 if (Pool)
569 {
570 KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
571 Pool->PacketLength = Length;
572
573 if (NumberOfDescriptors > 0)
574 {
575 Packet = (PNDIS_PACKET)&Pool->Buffer;
576 Pool->FreeList = Packet;
577
578 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
579 for (i = 1; i < NumberOfDescriptors; i++)
580 {
581 Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
582 Packet = NextPacket;
583 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
584 }
585 Packet->Private.Head = NULL;
586 }
587 else
588 Pool->FreeList = NULL;
589
590 *Status = NDIS_STATUS_SUCCESS;
591 *PoolHandle = (PNDIS_HANDLE)Pool;
592 } else
593 *Status = NDIS_STATUS_RESOURCES;
594 }
595 }
596
597
598 /*
599 * @implemented
600 */
601 ULONG
602 EXPORT
603 NdisBufferLength(
604 IN PNDIS_BUFFER Buffer)
605 /*
606 * FUNCTION: Modifies the length of an NDIS buffer
607 * ARGUMENTS:
608 * Buffer = Pointer to NDIS buffer descriptor
609 * Length = New size of buffer
610 * NOTES:
611 * NDIS 5.0
612 * RETURNS:
613 * Length of NDIS buffer
614 */
615 {
616 return Buffer->ByteCount;
617 }
618
619
620 /*
621 * @unimplemented
622 */
623 PVOID
624 EXPORT
625 NdisBufferVirtualAddress(
626 IN PNDIS_BUFFER Buffer)
627 /*
628 * FUNCTION:
629 * ARGUMENTS:
630 * NOTES:
631 * NDIS 5.0
632 */
633 {
634 UNIMPLEMENTED
635
636 return NULL;
637 }
638
639
640 /*
641 * @unimplemented
642 */
643 VOID
644 EXPORT
645 NdisCopyBuffer(
646 OUT PNDIS_STATUS Status,
647 OUT PNDIS_BUFFER *Buffer,
648 IN NDIS_HANDLE PoolHandle,
649 IN PVOID MemoryDescriptor,
650 IN UINT Offset,
651 IN UINT Length)
652 /*
653 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
654 * ARGUMENTS:
655 * Status = Address of a buffer to place status of operation
656 * Buffer = Address of a buffer to place new buffer descriptor
657 * PoolHandle = Handle returned by NdisAllocateBufferPool
658 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
659 * Offset = Offset in buffer to start copying
660 * Length = Number of bytes to copy
661 */
662 {
663 *Status = NDIS_STATUS_FAILURE;
664 }
665
666
667 /*
668 * @implemented
669 */
670 VOID
671 EXPORT
672 NdisCopyFromPacketToPacket(
673 IN PNDIS_PACKET Destination,
674 IN UINT DestinationOffset,
675 IN UINT BytesToCopy,
676 IN PNDIS_PACKET Source,
677 IN UINT SourceOffset,
678 OUT PUINT BytesCopied)
679 /*
680 * FUNCTION: Copies data from one packet to another
681 * ARGUMENTS:
682 * Destination = Pointer to packet to copy data to
683 * DestinationOffset = Offset in destination packet to copy data to
684 * BytesToCopy = Number of bytes to copy
685 * Source = Pointer to packet descriptor to copy from
686 * SourceOffset = Offset in source packet to start copying from
687 * BytesCopied = Address of buffer to place number of bytes copied
688 */
689 {
690 PNDIS_BUFFER SrcBuffer;
691 PNDIS_BUFFER DstBuffer;
692 PUCHAR DstData, SrcData;
693 UINT DstSize, SrcSize;
694 UINT Count, Total;
695
696 *BytesCopied = 0;
697
698 /* Skip DestinationOffset bytes in the destination packet */
699 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID)&DstData, &DstSize, &Total);
700 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
701 return;
702
703 /* Skip SourceOffset bytes in the source packet */
704 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
705 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
706 return;
707
708 /* Copy the data */
709 for (Total = 0;;) {
710 /* Find out how many bytes we can copy at one time */
711 if (BytesToCopy < SrcSize)
712 Count = BytesToCopy;
713 else
714 Count = SrcSize;
715 if (DstSize < Count)
716 Count = DstSize;
717
718 RtlCopyMemory(DstData, SrcData, Count);
719
720 Total += Count;
721 BytesToCopy -= Count;
722 if (BytesToCopy == 0)
723 break;
724
725 DstSize -= Count;
726 if (DstSize == 0) {
727 /* No more bytes in destination buffer. Proceed to
728 the next buffer in the destination buffer chain */
729 NdisGetNextBuffer(DstBuffer, &DstBuffer);
730 if (!DstBuffer)
731 break;
732
733 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
734 }
735
736 SrcSize -= Count;
737 if (SrcSize == 0) {
738 /* No more bytes in source buffer. Proceed to
739 the next buffer in the source buffer chain */
740 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
741 if (!SrcBuffer)
742 break;
743
744 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
745 }
746 }
747
748 *BytesCopied = Total;
749 }
750
751
752 /*
753 * @unimplemented
754 */
755 VOID
756 EXPORT
757 NdisDprAllocatePacket(
758 OUT PNDIS_STATUS Status,
759 OUT PNDIS_PACKET *Packet,
760 IN NDIS_HANDLE PoolHandle)
761 /*
762 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
763 * ARGUMENTS:
764 * Status = Address of buffer to place status of operation
765 * Packet = Address of buffer to place a pointer to a packet descriptor
766 * PoolHandle = Handle returned by NdisAllocatePacketPool
767 */
768 {
769 }
770
771
772 /*
773 * @unimplemented
774 */
775 VOID
776 EXPORT
777 NdisDprAllocatePacketNonInterlocked(
778 OUT PNDIS_STATUS Status,
779 OUT PNDIS_PACKET *Packet,
780 IN NDIS_HANDLE PoolHandle)
781 /*
782 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
783 * ARGUMENTS:
784 * Status = Address of buffer to place status of operation
785 * Packet = Address of buffer to place a pointer to a packet descriptor
786 * PoolHandle = Handle returned by NdisAllocatePacketPool
787 */
788 {
789 *Status = NDIS_STATUS_FAILURE;
790 }
791
792
793 /*
794 * @unimplemented
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 }
807
808
809 /*
810 * @unimplemented
811 */
812 VOID
813 EXPORT
814 NdisDprFreePacketNonInterlocked(
815 IN PNDIS_PACKET Packet)
816 /*
817 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
818 * ARGUMENTS:
819 * Packet = Pointer to packet to free
820 */
821 {
822 }
823
824
825 /*
826 * @implemented
827 */
828 VOID
829 EXPORT
830 NdisFreeBufferPool(
831 IN NDIS_HANDLE PoolHandle)
832 /*
833 * FUNCTION: Frees storage allocated for an NDIS buffer pool
834 * ARGUMENTS:
835 * PoolHandle = Handle returned by NdisAllocateBufferPool
836 */
837 {
838 ExFreePool((PVOID)PoolHandle);
839 }
840
841
842 /*
843 * @implemented
844 */
845 VOID
846 EXPORT
847 NdisFreePacketPool(
848 IN NDIS_HANDLE PoolHandle)
849 /*
850 * FUNCTION: Frees storage allocated for an NDIS packet pool
851 * ARGUMENTS:
852 * PoolHandle = Handle returned by NdisAllocatePacketPool
853 */
854 {
855 ExFreePool((PVOID)PoolHandle);
856 }
857
858
859 /*
860 * @implemented
861 */
862 VOID
863 EXPORT
864 NdisFreeBuffer(
865 IN PNDIS_BUFFER Buffer)
866 /*
867 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
868 * ARGUMENTS:
869 * Buffer = Pointer to buffer descriptor
870 */
871 {
872 KIRQL OldIrql;
873 PNDIS_BUFFER_POOL Pool;
874 PNETWORK_HEADER Temp = (PNETWORK_HEADER)Buffer;
875
876 NDIS_DbgPrint(MAX_TRACE, ("Buffer (0x%X).\n", Buffer));
877
878 Pool = Temp->BufferPool;
879
880 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
881 Temp->Next = (PNETWORK_HEADER)Pool->FreeList;
882 Pool->FreeList = (PNETWORK_HEADER)Temp;
883 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
884 }
885
886
887 /*
888 * @implemented
889 */
890 VOID
891 EXPORT
892 NdisFreePacket(
893 IN PNDIS_PACKET Packet)
894 /*
895 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
896 * ARGUMENTS:
897 * Packet = Pointer to packet descriptor
898 */
899 {
900 KIRQL OldIrql;
901
902 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
903
904 KeAcquireSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, &OldIrql);
905 Packet->Private.Head = (PNDIS_BUFFER)Packet->Private.Pool->FreeList;
906 Packet->Private.Pool->FreeList = Packet;
907 KeReleaseSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, OldIrql);
908 }
909
910
911 /*
912 * @implemented
913 */
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 VOID
937 EXPORT
938 NdisGetFirstBufferFromPacket(
939 IN PNDIS_PACKET _Packet,
940 OUT PNDIS_BUFFER *_FirstBuffer,
941 OUT PVOID *_FirstBufferVA,
942 OUT PUINT _FirstBufferLength,
943 OUT PUINT _TotalBufferLength)
944 /*
945 * FUNCTION: Retrieves information about an NDIS packet
946 * ARGUMENTS:
947 * _Packet = Pointer to NDIS packet
948 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
949 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
950 * _FirstBufferLength = Address of buffer for length of first buffer
951 * _TotalBufferLength = Address of buffer for total length of packet
952 */
953 {
954 PNDIS_BUFFER Buffer;
955
956 Buffer = _Packet->Private.Head;
957 *_FirstBuffer = Buffer;
958 *_FirstBufferVA = MmGetMdlVirtualAddress(Buffer);
959
960 if (Buffer != NULL) {
961 *_FirstBufferLength = MmGetMdlByteCount(Buffer);
962 Buffer = Buffer->Next;
963 } else
964 *_FirstBufferLength = 0;
965
966 *_TotalBufferLength = *_FirstBufferLength;
967
968 while (Buffer != NULL) {
969 *_TotalBufferLength += MmGetMdlByteCount(Buffer);
970 Buffer = Buffer->Next;
971 }
972 }
973
974
975 /*
976 * @unimplemented
977 */
978 VOID
979 EXPORT
980 NdisReturnPackets(
981 IN PNDIS_PACKET *PacketsToReturn,
982 IN UINT NumberOfPackets)
983 /*
984 * FUNCTION: Releases ownership of one or more packets
985 * ARGUMENTS:
986 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
987 * NumberOfPackets = Number of pointers in descriptor pointer array
988 */
989 {
990 UNIMPLEMENTED
991 }
992
993
994 /*
995 * @unimplemented
996 */
997 UINT
998 EXPORT
999 NdisPacketPoolUsage(
1000 IN NDIS_HANDLE PoolHandle)
1001 /*
1002 * FUNCTION:
1003 * ARGUMENTS:
1004 * NOTES:
1005 * NDIS 5.0
1006 */
1007 {
1008 UNIMPLEMENTED
1009
1010 return 0;
1011 }
1012
1013
1014 /*
1015 * @implemented
1016 */
1017 VOID
1018 EXPORT
1019 NdisQueryBuffer(
1020 IN PNDIS_BUFFER Buffer,
1021 OUT PVOID *VirtualAddress OPTIONAL,
1022 OUT PUINT Length)
1023 /*
1024 * FUNCTION:
1025 * Queries an NDIS buffer for information
1026 * ARGUMENTS:
1027 * Buffer = Pointer to NDIS buffer to query
1028 * VirtualAddress = Address of buffer to place virtual address
1029 * Length = Address of buffer to place length of buffer
1030 */
1031 {
1032 if (VirtualAddress != NULL)
1033 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
1034
1035 *Length = MmGetMdlByteCount(Buffer);
1036 }
1037
1038
1039 /*
1040 * @implemented
1041 */
1042 VOID
1043 EXPORT
1044 NdisQueryBufferSafe(
1045 IN PNDIS_BUFFER Buffer,
1046 OUT PVOID *VirtualAddress OPTIONAL,
1047 OUT PUINT Length,
1048 IN UINT Priority)
1049 /*
1050 * FUNCTION:
1051 * ARGUMENTS:
1052 * NOTES:
1053 * NDIS 5.0
1054 */
1055 {
1056 if (VirtualAddress != NULL)
1057 *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority);
1058 *Length = MmGetMdlByteCount(Buffer);
1059 }
1060
1061
1062 /*
1063 * @implemented
1064 */
1065 VOID
1066 EXPORT
1067 NdisQueryBufferOffset(
1068 IN PNDIS_BUFFER Buffer,
1069 OUT PUINT Offset,
1070 OUT PUINT Length)
1071 {
1072 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer);
1073 *((PUINT)Length) = MmGetMdlByteCount(Buffer);
1074 }
1075
1076
1077 /*
1078 * @implemented
1079 */
1080 VOID
1081 EXPORT
1082 NdisUnchainBufferAtBack(
1083 IN OUT PNDIS_PACKET Packet,
1084 OUT PNDIS_BUFFER *Buffer)
1085 /*
1086 * FUNCTION:
1087 * Removes the last buffer in a packet
1088 * ARGUMENTS:
1089 * Packet = Pointer to NDIS packet
1090 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1091 */
1092 {
1093 PNDIS_BUFFER NdisBuffer, Previous;
1094
1095 NdisQueryPacket(Packet,
1096 NULL,
1097 NULL,
1098 &NdisBuffer,
1099 NULL);
1100 if (!NdisBuffer) {
1101 *Buffer = NULL;
1102 return;
1103 }
1104
1105 Previous = NULL;
1106 while (NdisBuffer->Next) {
1107 Previous = NdisBuffer;
1108 NdisBuffer = NdisBuffer->Next;
1109 }
1110
1111 if (Previous) {
1112 Previous->Next = NULL;
1113 Packet->Private.Tail = Previous;
1114 } else {
1115 Packet->Private.Head = NULL;
1116 Packet->Private.Tail = NULL;
1117 }
1118
1119 Packet->Private.ValidCounts = FALSE;
1120
1121 *Buffer = NdisBuffer;
1122 }
1123
1124
1125 /*
1126 * @implemented
1127 */
1128 VOID
1129 EXPORT
1130 NdisUnchainBufferAtFront(
1131 IN OUT PNDIS_PACKET Packet,
1132 OUT PNDIS_BUFFER *Buffer)
1133 /*
1134 * FUNCTION:
1135 * Removes the first buffer in a packet
1136 * ARGUMENTS:
1137 * Packet = Pointer to NDIS packet
1138 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1139 */
1140 {
1141 PNDIS_BUFFER NdisBuffer;
1142
1143 NdisQueryPacket(Packet,
1144 NULL,
1145 NULL,
1146 &NdisBuffer,
1147 NULL);
1148 if (!NdisBuffer) {
1149 *Buffer = NULL;
1150 return;
1151 }
1152
1153 Packet->Private.Head = NdisBuffer->Next;
1154
1155 if (!NdisBuffer->Next)
1156 Packet->Private.Tail = NULL;
1157
1158 NdisBuffer->Next = NULL;
1159
1160 Packet->Private.ValidCounts = FALSE;
1161
1162 *Buffer = NdisBuffer;
1163 }
1164
1165 /* EOF */