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