fixed some signed/unsigned comparison warnings with -Wsign-compare
[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 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
473
474 if (Pool->FreeList) {
475 Temp = Pool->FreeList;
476 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
477
478 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
479
480 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
481 Temp->Private.Pool = Pool;
482
483 *Packet = Temp;
484 *Status = NDIS_STATUS_SUCCESS;
485 } else {
486 *Status = NDIS_STATUS_RESOURCES;
487 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
488 }
489 }
490
491
492 /*
493 * @implemented
494 */
495 VOID
496 EXPORT
497 NdisAllocatePacketPool(
498 OUT PNDIS_STATUS Status,
499 OUT PNDIS_HANDLE PoolHandle,
500 IN UINT NumberOfDescriptors,
501 IN UINT ProtocolReservedLength)
502 /*
503 * FUNCTION: Allocates storage for an NDIS packet pool
504 * ARGUMENTS:
505 * Status = Address of buffer for status
506 * PoolHandle = Address of buffer for pool handle
507 * NumberOfDescriptors = Size of packet pool in number of descriptors
508 * ProtocolReservedLength = Size of protocol reserved area in bytes
509 */
510 {
511 PNDIS_PACKET_POOL Pool;
512 UINT Size, Length, i;
513 PNDIS_PACKET Packet, NextPacket;
514
515 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) "
516 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
517 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
518
519 Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
520 Size = sizeof(NDIS_PACKET_POOL) + Length * NumberOfDescriptors;
521
522 Pool = ExAllocatePool(NonPagedPool, Size);
523 if (Pool) {
524 KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
525 Pool->PacketLength = Length;
526
527 if (NumberOfDescriptors > 0) {
528 Packet = (PNDIS_PACKET)&Pool->Buffer;
529 Pool->FreeList = Packet;
530
531 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
532 for (i = 1; i < NumberOfDescriptors; i++) {
533 Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
534 Packet = NextPacket;
535 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
536 }
537 Packet->Private.Head = NULL;
538 } else
539 Pool->FreeList = NULL;
540
541 *Status = NDIS_STATUS_SUCCESS;
542 *PoolHandle = (PNDIS_HANDLE)Pool;
543 } else
544 *Status = NDIS_STATUS_RESOURCES;
545 }
546
547
548 /*
549 * @unimplemented
550 */
551 VOID
552 EXPORT
553 NdisAllocatePacketPoolEx(
554 OUT PNDIS_STATUS Status,
555 OUT PNDIS_HANDLE PoolHandle,
556 IN UINT NumberOfDescriptors,
557 IN UINT NumberOfOverflowDescriptors,
558 IN UINT ProtocolReservedLength)
559 /*
560 * FUNCTION:
561 * ARGUMENTS:
562 * NOTES:
563 * NDIS 5.0
564 */
565 {
566 UNIMPLEMENTED
567 }
568
569
570 /*
571 * @implemented
572 */
573 ULONG
574 EXPORT
575 NdisBufferLength(
576 IN PNDIS_BUFFER Buffer)
577 /*
578 * FUNCTION: Modifies the length of an NDIS buffer
579 * ARGUMENTS:
580 * Buffer = Pointer to NDIS buffer descriptor
581 * Length = New size of buffer
582 * NOTES:
583 * NDIS 5.0
584 * RETURNS:
585 * Length of NDIS buffer
586 */
587 {
588 return Buffer->ByteCount;
589 }
590
591
592 /*
593 * @unimplemented
594 */
595 PVOID
596 EXPORT
597 NdisBufferVirtualAddress(
598 IN PNDIS_BUFFER Buffer)
599 /*
600 * FUNCTION:
601 * ARGUMENTS:
602 * NOTES:
603 * NDIS 5.0
604 */
605 {
606 UNIMPLEMENTED
607
608 return NULL;
609 }
610
611
612 /*
613 * @unimplemented
614 */
615 VOID
616 EXPORT
617 NdisCopyBuffer(
618 OUT PNDIS_STATUS Status,
619 OUT PNDIS_BUFFER *Buffer,
620 IN NDIS_HANDLE PoolHandle,
621 IN PVOID MemoryDescriptor,
622 IN UINT Offset,
623 IN UINT Length)
624 /*
625 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
626 * ARGUMENTS:
627 * Status = Address of a buffer to place status of operation
628 * Buffer = Address of a buffer to place new buffer descriptor
629 * PoolHandle = Handle returned by NdisAllocateBufferPool
630 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
631 * Offset = Offset in buffer to start copying
632 * Length = Number of bytes to copy
633 */
634 {
635 *Status = NDIS_STATUS_FAILURE;
636 }
637
638
639 /*
640 * @implemented
641 */
642 VOID
643 EXPORT
644 NdisCopyFromPacketToPacket(
645 IN PNDIS_PACKET Destination,
646 IN UINT DestinationOffset,
647 IN UINT BytesToCopy,
648 IN PNDIS_PACKET Source,
649 IN UINT SourceOffset,
650 OUT PUINT BytesCopied)
651 /*
652 * FUNCTION: Copies data from one packet to another
653 * ARGUMENTS:
654 * Destination = Pointer to packet to copy data to
655 * DestinationOffset = Offset in destination packet to copy data to
656 * BytesToCopy = Number of bytes to copy
657 * Source = Pointer to packet descriptor to copy from
658 * SourceOffset = Offset in source packet to start copying from
659 * BytesCopied = Address of buffer to place number of bytes copied
660 */
661 {
662 PNDIS_BUFFER SrcBuffer;
663 PNDIS_BUFFER DstBuffer;
664 PUCHAR DstData, SrcData;
665 UINT DstSize, SrcSize;
666 UINT Count, Total;
667
668 *BytesCopied = 0;
669
670 /* Skip DestinationOffset bytes in the destination packet */
671 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID)&DstData, &DstSize, &Total);
672 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
673 return;
674
675 /* Skip SourceOffset bytes in the source packet */
676 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
677 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
678 return;
679
680 /* Copy the data */
681 for (Total = 0;;) {
682 /* Find out how many bytes we can copy at one time */
683 if (BytesToCopy < SrcSize)
684 Count = BytesToCopy;
685 else
686 Count = SrcSize;
687 if (DstSize < Count)
688 Count = DstSize;
689
690 RtlCopyMemory(DstData, SrcData, Count);
691
692 Total += Count;
693 BytesToCopy -= Count;
694 if (BytesToCopy == 0)
695 break;
696
697 DstSize -= Count;
698 if (DstSize == 0) {
699 /* No more bytes in destination buffer. Proceed to
700 the next buffer in the destination buffer chain */
701 NdisGetNextBuffer(DstBuffer, &DstBuffer);
702 if (!DstBuffer)
703 break;
704
705 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
706 }
707
708 SrcSize -= Count;
709 if (SrcSize == 0) {
710 /* No more bytes in source buffer. Proceed to
711 the next buffer in the source buffer chain */
712 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
713 if (!SrcBuffer)
714 break;
715
716 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
717 }
718 }
719
720 *BytesCopied = Total;
721 }
722
723
724 /*
725 * @unimplemented
726 */
727 VOID
728 EXPORT
729 NdisDprAllocatePacket(
730 OUT PNDIS_STATUS Status,
731 OUT PNDIS_PACKET *Packet,
732 IN NDIS_HANDLE PoolHandle)
733 /*
734 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
735 * ARGUMENTS:
736 * Status = Address of buffer to place status of operation
737 * Packet = Address of buffer to place a pointer to a packet descriptor
738 * PoolHandle = Handle returned by NdisAllocatePacketPool
739 */
740 {
741 }
742
743
744 /*
745 * @unimplemented
746 */
747 VOID
748 EXPORT
749 NdisDprAllocatePacketNonInterlocked(
750 OUT PNDIS_STATUS Status,
751 OUT PNDIS_PACKET *Packet,
752 IN NDIS_HANDLE PoolHandle)
753 /*
754 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
755 * ARGUMENTS:
756 * Status = Address of buffer to place status of operation
757 * Packet = Address of buffer to place a pointer to a packet descriptor
758 * PoolHandle = Handle returned by NdisAllocatePacketPool
759 */
760 {
761 *Status = NDIS_STATUS_FAILURE;
762 }
763
764
765 /*
766 * @unimplemented
767 */
768 VOID
769 EXPORT
770 NdisDprFreePacket(
771 IN PNDIS_PACKET Packet)
772 /*
773 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
774 * ARGUMENTS:
775 * Packet = Pointer to packet to free
776 */
777 {
778 }
779
780
781 /*
782 * @unimplemented
783 */
784 VOID
785 EXPORT
786 NdisDprFreePacketNonInterlocked(
787 IN PNDIS_PACKET Packet)
788 /*
789 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
790 * ARGUMENTS:
791 * Packet = Pointer to packet to free
792 */
793 {
794 }
795
796
797 /*
798 * @implemented
799 */
800 VOID
801 EXPORT
802 NdisFreeBufferPool(
803 IN NDIS_HANDLE PoolHandle)
804 /*
805 * FUNCTION: Frees storage allocated for an NDIS buffer pool
806 * ARGUMENTS:
807 * PoolHandle = Handle returned by NdisAllocateBufferPool
808 */
809 {
810 ExFreePool((PVOID)PoolHandle);
811 }
812
813
814 /*
815 * @implemented
816 */
817 VOID
818 EXPORT
819 NdisFreePacketPool(
820 IN NDIS_HANDLE PoolHandle)
821 /*
822 * FUNCTION: Frees storage allocated for an NDIS packet pool
823 * ARGUMENTS:
824 * PoolHandle = Handle returned by NdisAllocatePacketPool
825 */
826 {
827 ExFreePool((PVOID)PoolHandle);
828 }
829
830
831 /*
832 * @implemented
833 */
834 VOID
835 EXPORT
836 NdisFreeBuffer(
837 IN PNDIS_BUFFER Buffer)
838 /*
839 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
840 * ARGUMENTS:
841 * Buffer = Pointer to buffer descriptor
842 */
843 {
844 KIRQL OldIrql;
845 PNDIS_BUFFER_POOL Pool;
846 PNETWORK_HEADER Temp = (PNETWORK_HEADER)Buffer;
847
848 NDIS_DbgPrint(MAX_TRACE, ("Buffer (0x%X).\n", Buffer));
849
850 Pool = Temp->BufferPool;
851
852 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
853 Temp->Next = (PNETWORK_HEADER)Pool->FreeList;
854 Pool->FreeList = (PNETWORK_HEADER)Temp;
855 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
856 }
857
858
859 /*
860 * @implemented
861 */
862 VOID
863 EXPORT
864 NdisFreePacket(
865 IN PNDIS_PACKET Packet)
866 /*
867 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
868 * ARGUMENTS:
869 * Packet = Pointer to packet descriptor
870 */
871 {
872 KIRQL OldIrql;
873
874 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
875
876 KeAcquireSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, &OldIrql);
877 Packet->Private.Head = (PNDIS_BUFFER)Packet->Private.Pool->FreeList;
878 Packet->Private.Pool->FreeList = Packet;
879 KeReleaseSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, OldIrql);
880 }
881
882
883 /*
884 * @implemented
885 */
886 VOID
887 EXPORT
888 NdisGetBufferPhysicalArraySize(
889 IN PNDIS_BUFFER Buffer,
890 OUT PUINT ArraySize)
891 /*
892 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
893 * ARGUMENTS:
894 * Buffer = Pointer to buffer descriptor
895 * ArraySize = Address of buffer to place number of physical blocks
896 */
897 {
898 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
899 ASSERT(Buffer && ArraySize);
900
901 *ArraySize = NDIS_BUFFER_TO_SPAN_PAGES(Buffer);
902 }
903
904
905 /*
906 * @implemented
907 */
908 VOID
909 EXPORT
910 NdisGetFirstBufferFromPacket(
911 IN PNDIS_PACKET _Packet,
912 OUT PNDIS_BUFFER *_FirstBuffer,
913 OUT PVOID *_FirstBufferVA,
914 OUT PUINT _FirstBufferLength,
915 OUT PUINT _TotalBufferLength)
916 /*
917 * FUNCTION: Retrieves information about an NDIS packet
918 * ARGUMENTS:
919 * _Packet = Pointer to NDIS packet
920 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
921 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
922 * _FirstBufferLength = Address of buffer for length of first buffer
923 * _TotalBufferLength = Address of buffer for total length of packet
924 */
925 {
926 PNDIS_BUFFER Buffer;
927
928 Buffer = _Packet->Private.Head;
929 *_FirstBuffer = Buffer;
930 *_FirstBufferVA = MmGetMdlVirtualAddress(Buffer);
931
932 if (Buffer != NULL) {
933 *_FirstBufferLength = MmGetMdlByteCount(Buffer);
934 Buffer = Buffer->Next;
935 } else
936 *_FirstBufferLength = 0;
937
938 *_TotalBufferLength = *_FirstBufferLength;
939
940 while (Buffer != NULL) {
941 *_TotalBufferLength += MmGetMdlByteCount(Buffer);
942 Buffer = Buffer->Next;
943 }
944 }
945
946
947 /*
948 * @unimplemented
949 */
950 VOID
951 EXPORT
952 NdisReturnPackets(
953 IN PNDIS_PACKET *PacketsToReturn,
954 IN UINT NumberOfPackets)
955 /*
956 * FUNCTION: Releases ownership of one or more packets
957 * ARGUMENTS:
958 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
959 * NumberOfPackets = Number of pointers in descriptor pointer array
960 */
961 {
962 UNIMPLEMENTED
963 }
964
965
966 /*
967 * @unimplemented
968 */
969 UINT
970 EXPORT
971 NdisPacketPoolUsage(
972 IN NDIS_HANDLE PoolHandle)
973 /*
974 * FUNCTION:
975 * ARGUMENTS:
976 * NOTES:
977 * NDIS 5.0
978 */
979 {
980 UNIMPLEMENTED
981
982 return 0;
983 }
984
985
986 /*
987 * @implemented
988 */
989 VOID
990 EXPORT
991 NdisQueryBuffer(
992 IN PNDIS_BUFFER Buffer,
993 OUT PVOID *VirtualAddress OPTIONAL,
994 OUT PUINT Length)
995 /*
996 * FUNCTION:
997 * Queries an NDIS buffer for information
998 * ARGUMENTS:
999 * Buffer = Pointer to NDIS buffer to query
1000 * VirtualAddress = Address of buffer to place virtual address
1001 * Length = Address of buffer to place length of buffer
1002 */
1003 {
1004 if (VirtualAddress != NULL)
1005 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
1006
1007 *Length = MmGetMdlByteCount(Buffer);
1008 }
1009
1010
1011 /*
1012 * @implemented
1013 */
1014 VOID
1015 EXPORT
1016 NdisQueryBufferSafe(
1017 IN PNDIS_BUFFER Buffer,
1018 OUT PVOID *VirtualAddress OPTIONAL,
1019 OUT PUINT Length,
1020 IN UINT Priority)
1021 /*
1022 * FUNCTION:
1023 * ARGUMENTS:
1024 * NOTES:
1025 * NDIS 5.0
1026 */
1027 {
1028 if (VirtualAddress != NULL)
1029 *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority);
1030 *Length = MmGetMdlByteCount(Buffer);
1031 }
1032
1033
1034 /*
1035 * @implemented
1036 */
1037 VOID
1038 EXPORT
1039 NdisQueryBufferOffset(
1040 IN PNDIS_BUFFER Buffer,
1041 OUT PUINT Offset,
1042 OUT PUINT Length)
1043 {
1044 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer);
1045 *((PUINT)Length) = MmGetMdlByteCount(Buffer);
1046 }
1047
1048
1049 /*
1050 * @implemented
1051 */
1052 VOID
1053 EXPORT
1054 NdisUnchainBufferAtBack(
1055 IN OUT PNDIS_PACKET Packet,
1056 OUT PNDIS_BUFFER *Buffer)
1057 /*
1058 * FUNCTION:
1059 * Removes the last buffer in a packet
1060 * ARGUMENTS:
1061 * Packet = Pointer to NDIS packet
1062 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1063 */
1064 {
1065 PNDIS_BUFFER NdisBuffer, Previous;
1066
1067 NdisQueryPacket(Packet,
1068 NULL,
1069 NULL,
1070 &NdisBuffer,
1071 NULL);
1072 if (!NdisBuffer) {
1073 *Buffer = NULL;
1074 return;
1075 }
1076
1077 Previous = NULL;
1078 while (NdisBuffer->Next) {
1079 Previous = NdisBuffer;
1080 NdisBuffer = NdisBuffer->Next;
1081 }
1082
1083 if (Previous) {
1084 Previous->Next = NULL;
1085 Packet->Private.Tail = Previous;
1086 } else {
1087 Packet->Private.Head = NULL;
1088 Packet->Private.Tail = NULL;
1089 }
1090
1091 Packet->Private.ValidCounts = FALSE;
1092
1093 *Buffer = NdisBuffer;
1094 }
1095
1096
1097 /*
1098 * @implemented
1099 */
1100 VOID
1101 EXPORT
1102 NdisUnchainBufferAtFront(
1103 IN OUT PNDIS_PACKET Packet,
1104 OUT PNDIS_BUFFER *Buffer)
1105 /*
1106 * FUNCTION:
1107 * Removes the first buffer in a packet
1108 * ARGUMENTS:
1109 * Packet = Pointer to NDIS packet
1110 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1111 */
1112 {
1113 PNDIS_BUFFER NdisBuffer;
1114
1115 NdisQueryPacket(Packet,
1116 NULL,
1117 NULL,
1118 &NdisBuffer,
1119 NULL);
1120 if (!NdisBuffer) {
1121 *Buffer = NULL;
1122 return;
1123 }
1124
1125 Packet->Private.Head = NdisBuffer->Next;
1126
1127 if (!NdisBuffer->Next)
1128 Packet->Private.Tail = NULL;
1129
1130 NdisBuffer->Next = NULL;
1131
1132 Packet->Private.ValidCounts = FALSE;
1133
1134 *Buffer = NdisBuffer;
1135 }
1136
1137 /* EOF */