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 FORCEINLINE 14 ULONG 15 SkipToOffset( 16 IN PNDIS_BUFFER Buffer, 17 IN UINT Offset, 18 IN OUT PUCHAR *Data, 19 IN OUT PUINT Size) 20 /* 21 * FUNCTION: Skips Offset bytes into a buffer chain 22 * ARGUMENTS: 23 * Buffer = Pointer to NDIS buffer 24 * Offset = Number of bytes to skip 25 * Data = Address of a pointer that on return will contain the 26 * address of the offset in the buffer 27 * Size = Address of a pointer that on return will contain the 28 * size of the destination buffer 29 * RETURNS: 30 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes 31 * NOTES: 32 * Buffer may be NULL 33 */ 34 { 35 for (;;) { 36 37 if (!Buffer) 38 return 0xFFFFFFFF; 39 40 NdisQueryBuffer(Buffer, (PVOID)Data, Size); 41 42 if (Offset < *Size) { 43 *Data = (PUCHAR) ((ULONG_PTR) *Data + Offset); 44 *Size -= Offset; 45 break; 46 } 47 48 Offset -= *Size; 49 50 NdisGetNextBuffer(Buffer, &Buffer); 51 } 52 53 return Offset; 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) == 0xFFFFFFFF) 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 SrcData = (PUCHAR) ((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 destination 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) == 0xFFFFFFFF) 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 DstData = (PUCHAR)((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) == 0xFFFFFFFF) 239 return 0; 240 /* Skip SrcOffset bytes in the source packet */ 241 NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total); 242 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 243 return 0; 244 /* Copy the data */ 245 for (Total = 0;;) { 246 /* Find out how many bytes we can copy at one time */ 247 if (Length < SrcSize) 248 Count = Length; 249 else 250 Count = SrcSize; 251 if (DstSize < Count) 252 Count = DstSize; 253 254 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); 255 256 Total += Count; 257 Length -= Count; 258 if (Length == 0) 259 break; 260 261 DstSize -= Count; 262 if (DstSize == 0) { 263 /* No more bytes in destination buffer. Proceed to 264 the next buffer in the destination buffer chain */ 265 NdisGetNextBuffer(DstBuffer, &DstBuffer); 266 if (!DstBuffer) 267 break; 268 269 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 270 } 271 272 SrcSize -= Count; 273 if (SrcSize == 0) { 274 /* No more bytes in source buffer. Proceed to 275 the next buffer in the source buffer chain */ 276 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 277 if (!SrcBuffer) 278 break; 279 280 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 281 } 282 } 283 284 return Total; 285 } 286 287 288 /* 289 * @implemented 290 */ 291 #undef NdisAdjustBufferLength 292 VOID 293 EXPORT 294 NdisAdjustBufferLength( 295 IN PNDIS_BUFFER Buffer, 296 IN UINT Length) 297 /* 298 * FUNCTION: Modifies the length of an NDIS buffer 299 * ARGUMENTS: 300 * Buffer = Pointer to NDIS buffer descriptor 301 * Length = New size of buffer 302 */ 303 { 304 Buffer->ByteCount = Length; 305 } 306 307 308 /* 309 * @implemented 310 */ 311 #undef NDIS_BUFFER_TO_SPAN_PAGES 312 ULONG 313 EXPORT 314 NDIS_BUFFER_TO_SPAN_PAGES( 315 IN PNDIS_BUFFER Buffer) 316 /* 317 * FUNCTION: Determines how many physical pages a buffer is made of 318 * ARGUMENTS: 319 * Buffer = Pointer to NDIS buffer descriptor 320 */ 321 { 322 if (MmGetMdlByteCount(Buffer) == 0) 323 return 1; 324 325 return ADDRESS_AND_SIZE_TO_SPAN_PAGES( 326 MmGetMdlVirtualAddress(Buffer), 327 MmGetMdlByteCount(Buffer)); 328 } 329 330 331 /* 332 * @implemented 333 */ 334 VOID 335 EXPORT 336 NdisAllocateBuffer( 337 OUT PNDIS_STATUS Status, 338 OUT PNDIS_BUFFER * Buffer, 339 IN NDIS_HANDLE PoolHandle, 340 IN PVOID VirtualAddress, 341 IN UINT Length) 342 /* 343 * FUNCTION: Allocates an NDIS buffer descriptor 344 * ARGUMENTS: 345 * Status = Address of buffer for status 346 * Buffer = Address of buffer for NDIS buffer descriptor 347 * PoolHandle = Handle returned by NdisAllocateBufferPool 348 * VirtualAddress = Pointer to virtual address of data buffer 349 * Length = Number of bytes in data buffer 350 */ 351 { 352 ASSERT(VirtualAddress != NULL); 353 ASSERT(Length > 0); 354 355 *Buffer = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL); 356 if (*Buffer != NULL) { 357 MmBuildMdlForNonPagedPool(*Buffer); 358 (*Buffer)->Next = NULL; 359 *Status = NDIS_STATUS_SUCCESS; 360 } else { 361 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress, Length)); 362 *Status = NDIS_STATUS_FAILURE; 363 } 364 } 365 366 367 /* 368 * @implemented 369 */ 370 VOID 371 EXPORT 372 NdisAllocateBufferPool( 373 OUT PNDIS_STATUS Status, 374 OUT PNDIS_HANDLE PoolHandle, 375 IN UINT NumberOfDescriptors) 376 /* 377 * FUNCTION: Allocates storage for an NDIS buffer pool 378 * ARGUMENTS: 379 * Status = Address of buffer for status 380 * PoolHandle = Address of buffer for pool handle 381 * NumberOfDescriptors = Size of buffer pool in number of descriptors 382 */ 383 { 384 *Status = NDIS_STATUS_SUCCESS; 385 *PoolHandle = 0; 386 } 387 388 389 /* 390 * @implemented 391 */ 392 VOID 393 EXPORT 394 NdisAllocatePacket( 395 OUT PNDIS_STATUS Status, 396 OUT PNDIS_PACKET * Packet, 397 IN NDIS_HANDLE PoolHandle) 398 /* 399 * FUNCTION: Allocates an NDIS packet descriptor 400 * ARGUMENTS: 401 * Status = Address of buffer for status 402 * Packet = Address of buffer for packet descriptor 403 * PoolHandle = Handle returned by NdisAllocatePacketPool 404 */ 405 { 406 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 407 408 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql); 409 NdisDprAllocatePacketNonInterlocked(Status, 410 Packet, 411 PoolHandle); 412 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql); 413 } 414 415 416 /* 417 * @implemented 418 */ 419 VOID 420 EXPORT 421 NdisAllocatePacketPool( 422 OUT PNDIS_STATUS Status, 423 OUT PNDIS_HANDLE PoolHandle, 424 IN UINT NumberOfDescriptors, 425 IN UINT ProtocolReservedLength) 426 /* 427 * FUNCTION: Allocates storage for an NDIS packet pool 428 * ARGUMENTS: 429 * Status = Address of buffer for status 430 * PoolHandle = Address of buffer for pool handle 431 * NumberOfDescriptors = Size of packet pool in number of descriptors 432 * ProtocolReservedLength = Size of protocol reserved area in bytes 433 */ 434 { 435 NdisAllocatePacketPoolEx( 436 Status, 437 PoolHandle, 438 NumberOfDescriptors, 439 0, 440 ProtocolReservedLength); 441 } 442 443 444 /* 445 * @implemented 446 */ 447 VOID 448 EXPORT 449 NdisAllocatePacketPoolEx( 450 OUT PNDIS_STATUS Status, 451 OUT PNDIS_HANDLE PoolHandle, 452 IN UINT NumberOfDescriptors, 453 IN UINT NumberOfOverflowDescriptors, 454 IN UINT ProtocolReservedLength) 455 /* 456 * FUNCTION: 457 * ARGUMENTS: 458 * NOTES: 459 * NDIS 5.0 460 */ 461 { 462 PNDISI_PACKET_POOL Pool; 463 UINT Size, Length, i; 464 PNDIS_PACKET Packet, NextPacket; 465 466 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) " 467 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n", 468 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength)); 469 470 *PoolHandle = NULL; 471 472 if (NumberOfDescriptors > 0xffff) 473 { 474 NDIS_DbgPrint(MIN_TRACE, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors)) 475 *Status = NDIS_STATUS_RESOURCES; 476 } 477 else 478 { 479 NumberOfDescriptors += NumberOfOverflowDescriptors; 480 if (NumberOfDescriptors > 0xffff) 481 { 482 NDIS_DbgPrint(MIN_TRACE, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors)); 483 NumberOfDescriptors = 0xffff; 484 } 485 486 Length = sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 487 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedLength; 488 Size = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors; 489 490 Pool = ExAllocatePool(NonPagedPool, Size); 491 if (Pool) 492 { 493 KeInitializeSpinLock(&Pool->SpinLock.SpinLock); 494 Pool->PacketLength = Length; 495 496 if (NumberOfDescriptors > 0) 497 { 498 Packet = (PNDIS_PACKET)&Pool->Buffer; 499 Pool->FreeList = Packet; 500 501 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); 502 for (i = 1; i < NumberOfDescriptors; i++) 503 { 504 Packet->Reserved[0] = (ULONG_PTR)NextPacket; 505 Packet = NextPacket; 506 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); 507 } 508 Packet->Reserved[0] = 0; 509 } 510 else { 511 NDIS_DbgPrint(MIN_TRACE, ("Attempted to allocate a packet pool with 0 descriptors\n")); 512 Pool->FreeList = NULL; 513 } 514 515 *Status = NDIS_STATUS_SUCCESS; 516 *PoolHandle = (PNDIS_HANDLE)Pool; 517 } else { 518 *Status = NDIS_STATUS_RESOURCES; 519 } 520 } 521 } 522 523 524 /* 525 * @implemented 526 */ 527 #undef NdisBufferLength 528 ULONG 529 EXPORT 530 NdisBufferLength( 531 IN PNDIS_BUFFER Buffer) 532 /* 533 * FUNCTION: Modifies the length of an NDIS buffer 534 * ARGUMENTS: 535 * Buffer = Pointer to NDIS buffer descriptor 536 * Length = New size of buffer 537 * NOTES: 538 * NDIS 5.0 539 * RETURNS: 540 * Length of NDIS buffer 541 */ 542 { 543 return MmGetMdlByteCount(Buffer); 544 } 545 546 547 /* 548 * @implemented 549 */ 550 #undef NdisBufferVirtualAddress 551 PVOID 552 EXPORT 553 NdisBufferVirtualAddress( 554 IN PNDIS_BUFFER Buffer) 555 /* 556 * FUNCTION: 557 * ARGUMENTS: 558 * NOTES: 559 * NDIS 5.0 560 */ 561 { 562 return MmGetSystemAddressForMdl(Buffer); 563 } 564 565 566 /* 567 * @implemented 568 */ 569 VOID 570 EXPORT 571 NdisCopyFromPacketToPacket( 572 IN PNDIS_PACKET Destination, 573 IN UINT DestinationOffset, 574 IN UINT BytesToCopy, 575 IN PNDIS_PACKET Source, 576 IN UINT SourceOffset, 577 OUT PUINT BytesCopied) 578 /* 579 * FUNCTION: Copies data from one packet to another 580 * ARGUMENTS: 581 * Destination = Pointer to packet to copy data to 582 * DestinationOffset = Offset in destination packet to copy data to 583 * BytesToCopy = Number of bytes to copy 584 * Source = Pointer to packet descriptor to copy from 585 * SourceOffset = Offset in source packet to start copying from 586 * BytesCopied = Address of buffer to place number of bytes copied 587 */ 588 { 589 PNDIS_BUFFER SrcBuffer; 590 PNDIS_BUFFER DstBuffer; 591 PUCHAR DstData, SrcData; 592 UINT DstSize, SrcSize; 593 UINT Count, Total; 594 595 *BytesCopied = 0; 596 597 /* Skip DestinationOffset bytes in the destination packet */ 598 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total); 599 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF) 600 return; 601 602 /* Skip SourceOffset bytes in the source packet */ 603 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total); 604 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 605 return; 606 607 /* Copy the data */ 608 for (Total = 0;;) { 609 /* Find out how many bytes we can copy at one time */ 610 if (BytesToCopy < SrcSize) 611 Count = BytesToCopy; 612 else 613 Count = SrcSize; 614 if (DstSize < Count) 615 Count = DstSize; 616 617 RtlCopyMemory(DstData, SrcData, Count); 618 619 Total += Count; 620 BytesToCopy -= Count; 621 if (BytesToCopy == 0) 622 break; 623 624 DstSize -= Count; 625 if (DstSize == 0) { 626 /* No more bytes in destination buffer. Proceed to 627 the next buffer in the destination buffer chain */ 628 NdisGetNextBuffer(DstBuffer, &DstBuffer); 629 if (!DstBuffer) 630 break; 631 632 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 633 } 634 635 SrcSize -= Count; 636 if (SrcSize == 0) { 637 /* No more bytes in source buffer. Proceed to 638 the next buffer in the source buffer chain */ 639 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 640 if (!SrcBuffer) 641 break; 642 643 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 644 } 645 } 646 647 *BytesCopied = Total; 648 } 649 650 651 /* 652 * @implemented 653 */ 654 VOID 655 EXPORT 656 NdisDprAllocatePacket( 657 OUT PNDIS_STATUS Status, 658 OUT PNDIS_PACKET *Packet, 659 IN NDIS_HANDLE PoolHandle) 660 /* 661 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL 662 * ARGUMENTS: 663 * Status = Address of buffer to place status of operation 664 * Packet = Address of buffer to place a pointer to a packet descriptor 665 * PoolHandle = Handle returned by NdisAllocatePacketPool 666 */ 667 { 668 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 669 670 KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock); 671 NdisDprAllocatePacketNonInterlocked(Status, 672 Packet, 673 PoolHandle); 674 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock); 675 } 676 677 678 /* 679 * @implemented 680 */ 681 VOID 682 EXPORT 683 NdisDprAllocatePacketNonInterlocked( 684 OUT PNDIS_STATUS Status, 685 OUT PNDIS_PACKET *Packet, 686 IN NDIS_HANDLE PoolHandle) 687 /* 688 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization) 689 * ARGUMENTS: 690 * Status = Address of buffer to place status of operation 691 * Packet = Address of buffer to place a pointer to a packet descriptor 692 * PoolHandle = Handle returned by NdisAllocatePacketPool 693 */ 694 { 695 PNDIS_PACKET Temp; 696 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 697 698 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n", 699 Status, Packet, PoolHandle)); 700 701 *Packet = NULL; 702 703 if (Pool == NULL) 704 { 705 *Status = NDIS_STATUS_FAILURE; 706 NDIS_DbgPrint(MIN_TRACE, ("Called passed a bad pool handle\n")); 707 return; 708 } 709 710 if (Pool->FreeList) { 711 Temp = Pool->FreeList; 712 Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0]; 713 714 RtlZeroMemory(Temp, Pool->PacketLength); 715 Temp->Private.Pool = Pool; 716 Temp->Private.ValidCounts = TRUE; 717 Temp->Private.NdisPacketFlags = fPACKET_ALLOCATED_BY_NDIS; 718 Temp->Private.NdisPacketOobOffset = Pool->PacketLength - 719 (sizeof(NDIS_PACKET_OOB_DATA) + 720 sizeof(NDIS_PACKET_EXTENSION)); 721 722 *Packet = Temp; 723 *Status = NDIS_STATUS_SUCCESS; 724 } else { 725 NDIS_DbgPrint(MIN_TRACE, ("No more free descriptors\n")); 726 *Status = NDIS_STATUS_RESOURCES; 727 } 728 } 729 730 731 /* 732 * @implemented 733 */ 734 VOID 735 EXPORT 736 NdisDprFreePacket( 737 IN PNDIS_PACKET Packet) 738 /* 739 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL 740 * ARGUMENTS: 741 * Packet = Pointer to packet to free 742 */ 743 { 744 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool; 745 746 KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock); 747 NdisDprFreePacketNonInterlocked(Packet); 748 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock); 749 } 750 751 752 /* 753 * @implemented 754 */ 755 VOID 756 EXPORT 757 NdisDprFreePacketNonInterlocked( 758 IN PNDIS_PACKET Packet) 759 /* 760 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization) 761 * ARGUMENTS: 762 * Packet = Pointer to packet to free 763 */ 764 { 765 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet)); 766 767 Packet->Reserved[0] = (ULONG_PTR)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList; 768 ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet; 769 } 770 771 772 /* 773 * @implemented 774 */ 775 VOID 776 EXPORT 777 NdisFreeBufferPool( 778 IN NDIS_HANDLE PoolHandle) 779 /* 780 * FUNCTION: Frees storage allocated for an NDIS buffer pool 781 * ARGUMENTS: 782 * PoolHandle = Handle returned by NdisAllocateBufferPool 783 */ 784 { 785 } 786 787 788 /* 789 * @implemented 790 */ 791 VOID 792 EXPORT 793 NdisFreePacketPool( 794 IN NDIS_HANDLE PoolHandle) 795 /* 796 * FUNCTION: Frees storage allocated for an NDIS packet pool 797 * ARGUMENTS: 798 * PoolHandle = Handle returned by NdisAllocatePacketPool 799 */ 800 { 801 ExFreePool((PVOID)PoolHandle); 802 } 803 804 805 /* 806 * @implemented 807 */ 808 #undef NdisFreeBuffer 809 VOID 810 EXPORT 811 NdisFreeBuffer( 812 IN PNDIS_BUFFER Buffer) 813 /* 814 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool 815 * ARGUMENTS: 816 * Buffer = Pointer to buffer descriptor 817 */ 818 { 819 IoFreeMdl(Buffer); 820 } 821 822 823 /* 824 * @implemented 825 */ 826 VOID 827 EXPORT 828 NdisFreePacket( 829 IN PNDIS_PACKET Packet) 830 /* 831 * FUNCTION: Puts an NDIS packet descriptor back in it's pool 832 * ARGUMENTS: 833 * Packet = Pointer to packet descriptor 834 */ 835 { 836 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool; 837 838 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql); 839 NdisDprFreePacketNonInterlocked(Packet); 840 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql); 841 } 842 843 844 /* 845 * @implemented 846 */ 847 #undef NdisGetBufferPhysicalArraySize 848 VOID 849 EXPORT 850 NdisGetBufferPhysicalArraySize( 851 IN PNDIS_BUFFER Buffer, 852 OUT PUINT ArraySize) 853 /* 854 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer 855 * ARGUMENTS: 856 * Buffer = Pointer to buffer descriptor 857 * ArraySize = Address of buffer to place number of physical blocks 858 */ 859 { 860 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 861 ASSERT(Buffer && ArraySize); 862 863 *ArraySize = NDIS_BUFFER_TO_SPAN_PAGES(Buffer); 864 } 865 866 867 /* 868 * @implemented 869 */ 870 #undef NdisGetFirstBufferFromPacket 871 VOID 872 EXPORT 873 NdisGetFirstBufferFromPacket( 874 IN PNDIS_PACKET _Packet, 875 OUT PNDIS_BUFFER *_FirstBuffer, 876 OUT PVOID *_FirstBufferVA, 877 OUT PUINT _FirstBufferLength, 878 OUT PUINT _TotalBufferLength) 879 /* 880 * FUNCTION: Retrieves information about an NDIS packet 881 * ARGUMENTS: 882 * _Packet = Pointer to NDIS packet 883 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer 884 * _FirstBufferVA = Address of buffer for address of first NDIS buffer 885 * _FirstBufferLength = Address of buffer for length of first buffer 886 * _TotalBufferLength = Address of buffer for total length of packet 887 */ 888 { 889 PNDIS_BUFFER Buffer; 890 891 Buffer = _Packet->Private.Head; 892 *_FirstBuffer = Buffer; 893 894 if (Buffer != NULL) { 895 *_FirstBufferLength = MmGetMdlByteCount(Buffer); 896 *_FirstBufferVA = MmGetSystemAddressForMdl(Buffer); 897 Buffer = Buffer->Next; 898 } else { 899 NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n")); 900 *_FirstBufferLength = 0; 901 *_FirstBufferVA = NULL; 902 } 903 904 *_TotalBufferLength = *_FirstBufferLength; 905 906 while (Buffer != NULL) { 907 *_TotalBufferLength += MmGetMdlByteCount(Buffer); 908 Buffer = Buffer->Next; 909 } 910 } 911 912 #undef NdisGetFirstBufferFromPacketSafe 913 /* 914 * @implemented 915 */ 916 VOID 917 EXPORT 918 NdisGetFirstBufferFromPacketSafe( 919 IN PNDIS_PACKET _Packet, 920 OUT PNDIS_BUFFER *_FirstBuffer, 921 OUT PVOID *_FirstBufferVA, 922 OUT PUINT _FirstBufferLength, 923 OUT PUINT _TotalBufferLength, 924 IN MM_PAGE_PRIORITY Priority) 925 { 926 PNDIS_BUFFER Buffer; 927 928 Buffer = _Packet->Private.Head; 929 *_FirstBuffer = Buffer; 930 931 if (Buffer != NULL) { 932 *_FirstBufferLength = MmGetMdlByteCount(Buffer); 933 *_FirstBufferVA = MmGetSystemAddressForMdlSafe(Buffer, Priority); 934 Buffer = Buffer->Next; 935 } else { 936 NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n")); 937 *_FirstBufferLength = 0; 938 *_FirstBufferVA = NULL; 939 } 940 941 *_TotalBufferLength = *_FirstBufferLength; 942 943 while (Buffer != NULL) { 944 *_TotalBufferLength += MmGetMdlByteCount(Buffer); 945 Buffer = Buffer->Next; 946 } 947 } 948 949 /* 950 * @implemented 951 */ 952 #undef NdisQueryBuffer 953 VOID 954 EXPORT 955 NdisQueryBuffer( 956 IN PNDIS_BUFFER Buffer, 957 OUT PVOID *VirtualAddress OPTIONAL, 958 OUT PUINT Length) 959 /* 960 * FUNCTION: 961 * Queries an NDIS buffer for information 962 * ARGUMENTS: 963 * Buffer = Pointer to NDIS buffer to query 964 * VirtualAddress = Address of buffer to place virtual address 965 * Length = Address of buffer to place length of buffer 966 */ 967 { 968 if (VirtualAddress != NULL) 969 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer); 970 971 *Length = MmGetMdlByteCount(Buffer); 972 } 973 974 975 /* 976 * @implemented 977 */ 978 #undef NdisQueryBufferSafe 979 VOID 980 EXPORT 981 NdisQueryBufferSafe( 982 IN PNDIS_BUFFER Buffer, 983 OUT PVOID *VirtualAddress OPTIONAL, 984 OUT PUINT Length, 985 IN UINT Priority) 986 /* 987 * FUNCTION: 988 * ARGUMENTS: 989 * NOTES: 990 * NDIS 5.0 991 */ 992 { 993 if (VirtualAddress != NULL) 994 *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority); 995 *Length = MmGetMdlByteCount(Buffer); 996 } 997 998 999 /* 1000 * @implemented 1001 */ 1002 #undef NdisQueryBufferOffset 1003 VOID 1004 EXPORT 1005 NdisQueryBufferOffset( 1006 IN PNDIS_BUFFER Buffer, 1007 OUT PUINT Offset, 1008 OUT PUINT Length) 1009 { 1010 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer); 1011 *((PUINT)Length) = MmGetMdlByteCount(Buffer); 1012 } 1013 1014 1015 /* 1016 * @implemented 1017 */ 1018 VOID 1019 EXPORT 1020 NdisUnchainBufferAtBack( 1021 IN OUT PNDIS_PACKET Packet, 1022 OUT PNDIS_BUFFER *Buffer) 1023 /* 1024 * FUNCTION: 1025 * Removes the last buffer in a packet 1026 * ARGUMENTS: 1027 * Packet = Pointer to NDIS packet 1028 * Buffer = Address of buffer to place pointer to removed NDIS buffer 1029 */ 1030 { 1031 PNDIS_BUFFER NdisBuffer, Previous; 1032 1033 NdisQueryPacket(Packet, 1034 NULL, 1035 NULL, 1036 &NdisBuffer, 1037 NULL); 1038 if (!NdisBuffer) { 1039 NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n")); 1040 *Buffer = NULL; 1041 return; 1042 } 1043 1044 Previous = NULL; 1045 while (NdisBuffer->Next) { 1046 Previous = NdisBuffer; 1047 NdisBuffer = NdisBuffer->Next; 1048 } 1049 1050 if (Previous) { 1051 Previous->Next = NULL; 1052 Packet->Private.Tail = Previous; 1053 } else { 1054 Packet->Private.Head = NULL; 1055 Packet->Private.Tail = NULL; 1056 } 1057 1058 Packet->Private.ValidCounts = FALSE; 1059 1060 *Buffer = NdisBuffer; 1061 } 1062 1063 1064 /* 1065 * @implemented 1066 */ 1067 VOID 1068 EXPORT 1069 NdisUnchainBufferAtFront( 1070 IN OUT PNDIS_PACKET Packet, 1071 OUT PNDIS_BUFFER *Buffer) 1072 /* 1073 * FUNCTION: 1074 * Removes the first buffer in a packet 1075 * ARGUMENTS: 1076 * Packet = Pointer to NDIS packet 1077 * Buffer = Address of buffer to place pointer to removed NDIS buffer 1078 */ 1079 { 1080 PNDIS_BUFFER NdisBuffer; 1081 1082 NdisQueryPacket(Packet, 1083 NULL, 1084 NULL, 1085 &NdisBuffer, 1086 NULL); 1087 if (!NdisBuffer) { 1088 NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n")); 1089 *Buffer = NULL; 1090 return; 1091 } 1092 1093 Packet->Private.Head = NdisBuffer->Next; 1094 1095 if (!NdisBuffer->Next) 1096 Packet->Private.Tail = NULL; 1097 1098 NdisBuffer->Next = NULL; 1099 1100 Packet->Private.ValidCounts = FALSE; 1101 1102 *Buffer = NdisBuffer; 1103 } 1104 1105 /* 1106 * @implemented 1107 */ 1108 VOID 1109 EXPORT 1110 NdisCopyBuffer( 1111 OUT PNDIS_STATUS Status, 1112 OUT PNDIS_BUFFER *Buffer, 1113 IN NDIS_HANDLE PoolHandle, 1114 IN PVOID MemoryDescriptor, 1115 IN UINT Offset, 1116 IN UINT Length) 1117 /* 1118 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer 1119 * ARGUMENTS: 1120 * Status = Address of a buffer to place status of operation 1121 * Buffer = Address of a buffer to place new buffer descriptor 1122 * PoolHandle = Handle returned by NdisAllocateBufferPool 1123 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER) 1124 * Offset = Offset in buffer to start copying 1125 * Length = Number of bytes to copy 1126 */ 1127 { 1128 PVOID CurrentVa = (PUCHAR)(MmGetMdlVirtualAddress((PNDIS_BUFFER)MemoryDescriptor)) + Offset; 1129 1130 NDIS_DbgPrint(MAX_TRACE, ("Called\n")); 1131 1132 *Buffer = IoAllocateMdl(CurrentVa, Length, FALSE, FALSE, NULL); 1133 if (!*Buffer) 1134 { 1135 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa, Length)); 1136 *Status = NDIS_STATUS_FAILURE; 1137 return; 1138 } 1139 1140 IoBuildPartialMdl((PNDIS_BUFFER)MemoryDescriptor, 1141 *Buffer, 1142 CurrentVa, 1143 Length); 1144 1145 (*Buffer)->Next = NULL; 1146 *Status = NDIS_STATUS_SUCCESS; 1147 } 1148 1149 /* 1150 * @implemented 1151 */ 1152 NDIS_HANDLE 1153 EXPORT 1154 NdisGetPoolFromPacket( 1155 IN PNDIS_PACKET Packet) 1156 { 1157 return Packet->Private.Pool; 1158 } 1159 1160 /* 1161 * @implemented 1162 */ 1163 UINT 1164 EXPORT 1165 NdisPacketSize( 1166 IN UINT ProtocolReservedSize) 1167 { 1168 return sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 1169 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedSize; 1170 } 1171 1172 /* 1173 * @implemented 1174 */ 1175 #undef NdisGetPacketCancelId 1176 PVOID 1177 EXPORT 1178 NdisGetPacketCancelId( 1179 IN PNDIS_PACKET Packet) 1180 { 1181 return NDIS_GET_PACKET_CANCEL_ID(Packet); 1182 } 1183 1184 /* 1185 * @implemented 1186 */ 1187 #undef NdisSetPacketCancelId 1188 VOID 1189 EXPORT 1190 NdisSetPacketCancelId( 1191 IN PNDIS_PACKET Packet, 1192 IN PVOID CancelId) 1193 { 1194 NDIS_SET_PACKET_CANCEL_ID(Packet, CancelId); 1195 } 1196 1197 /* 1198 * @implemented 1199 */ 1200 VOID 1201 EXPORT 1202 NdisCopyFromPacketToPacketSafe( 1203 IN PNDIS_PACKET Destination, 1204 IN UINT DestinationOffset, 1205 IN UINT BytesToCopy, 1206 IN PNDIS_PACKET Source, 1207 IN UINT SourceOffset, 1208 OUT PUINT BytesCopied, 1209 IN MM_PAGE_PRIORITY Priority) 1210 { 1211 PNDIS_BUFFER SrcBuffer; 1212 PNDIS_BUFFER DstBuffer; 1213 PUCHAR DstData, SrcData; 1214 UINT DstSize, SrcSize; 1215 UINT Count, Total; 1216 1217 *BytesCopied = 0; 1218 1219 /* Skip DestinationOffset bytes in the destination packet */ 1220 NdisGetFirstBufferFromPacketSafe(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total, Priority); 1221 if (!DstData || SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF) 1222 return; 1223 1224 /* Skip SourceOffset bytes in the source packet */ 1225 NdisGetFirstBufferFromPacketSafe(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total, Priority); 1226 if (!SrcData || SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 1227 return; 1228 1229 /* Copy the data */ 1230 for (Total = 0;;) { 1231 /* Find out how many bytes we can copy at one time */ 1232 if (BytesToCopy < SrcSize) 1233 Count = BytesToCopy; 1234 else 1235 Count = SrcSize; 1236 if (DstSize < Count) 1237 Count = DstSize; 1238 1239 RtlCopyMemory(DstData, SrcData, Count); 1240 1241 Total += Count; 1242 BytesToCopy -= Count; 1243 if (BytesToCopy == 0) 1244 break; 1245 1246 DstSize -= Count; 1247 if (DstSize == 0) { 1248 /* No more bytes in destination buffer. Proceed to 1249 the next buffer in the destination buffer chain */ 1250 NdisGetNextBuffer(DstBuffer, &DstBuffer); 1251 if (!DstBuffer) 1252 break; 1253 1254 NdisQueryBufferSafe(DstBuffer, (PVOID)&DstData, &DstSize, Priority); 1255 if (!DstData) 1256 break; 1257 } 1258 1259 SrcSize -= Count; 1260 if (SrcSize == 0) { 1261 /* No more bytes in source buffer. Proceed to 1262 the next buffer in the source buffer chain */ 1263 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 1264 if (!SrcBuffer) 1265 break; 1266 1267 NdisQueryBufferSafe(SrcBuffer, (PVOID)&SrcData, &SrcSize, Priority); 1268 if (!SrcData) 1269 break; 1270 } 1271 } 1272 1273 *BytesCopied = Total; 1274 } 1275 1276 /* 1277 * @implemented 1278 */ 1279 VOID 1280 EXPORT 1281 NdisIMCopySendCompletePerPacketInfo( 1282 IN PNDIS_PACKET DstPacket, 1283 IN PNDIS_PACKET SrcPacket) 1284 /* 1285 * FUNCTION: 1286 * ARGUMENTS: 1287 * NOTES: 1288 * NDIS 5.0 1289 */ 1290 { 1291 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and 1292 * NdisIMCopySendCompletePerPacketInfo? 1293 */ 1294 1295 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 1296 1297 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket), 1298 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket), 1299 sizeof(NDIS_PACKET_EXTENSION)); 1300 } 1301 1302 1303 /* 1304 * @implemented 1305 */ 1306 VOID 1307 EXPORT 1308 NdisIMCopySendPerPacketInfo( 1309 IN PNDIS_PACKET DstPacket, 1310 IN PNDIS_PACKET SrcPacket) 1311 /* 1312 * FUNCTION: 1313 * ARGUMENTS: 1314 * NOTES: 1315 * NDIS 5.0 1316 */ 1317 { 1318 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and 1319 * NdisIMCopySendCompletePerPacketInfo? 1320 */ 1321 1322 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 1323 1324 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket), 1325 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket), 1326 sizeof(NDIS_PACKET_EXTENSION)); 1327 } 1328 1329 /* EOF */ 1330