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