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