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