:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / 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 */