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